# Moneyball AI data import Import a UTF-8 JSON file of at most 2 MB and 2,000 records. Use the MLB import form for a real, exportable starting file, or export the sample dataset to inspect the complete structure. Imports replace the active dataset after validation and review; they do not silently merge or persist. Export before refreshing or closing the page. ## Envelope - `schemaVersion`: 1 - `name`: descriptive dataset name - `mode`: `real` for sourced real players; `sample` for fictional fixtures - `season`: statistical season, integer - `salarySeason`: year represented by salary values, no earlier than the statistics season - `players`: array of player objects Each file covers one statistical season and one salary season. Join sources by MLB player ID, season and hitter/pitcher role, never by player name. Consolidate multi-team season splits before import. Two-way players may have separate hitter and pitcher records, but salary is the full player salary for each analysis; do not add these valuations together. ## Player fields | Field | Meaning | |---|---| | playerId | Numeric MLB ID as a string, e.g. `592450`. Format validation alone does not establish identity. The MLB lookup verifies IDs against MLB. | | name, team | Player name and current team. Use the exact team selector name; `Free Agent` is accepted. | | kind | `hitter` or `pitcher` | | position | C, 1B, 2B, 3B, SS, OF, LF, CF, RF, DH, SP or RP | | age | Whole years at the statistical season, or null | | salary | Positive USD amount for salarySeason, or null | | salaryBasis | `annual-salary`, `aav`, `estimate`, or `unknown` when salary is null | | war | Historical season WAR, or null | | warModel | `fWAR` or `bWAR` when WAR is present; null otherwise | | availability | `unknown`, `free-agent`, `trade-candidate`, or `under-contract` | | yearsRemaining | Guaranteed remaining contract years as of contract source date, or null | | guaranteedRemaining | Total remaining guaranteed USD commitment as of contract source date, or null | Hitter metrics: `obp`, `slg`, `ops`, `opsPlus`, `wrcPlus`, `defensiveRuns` (DRS), `pa`. Pitcher metrics: `era`, `eraPlus`, `whip`, `kRate`, `bbRate`, `ip`. K/BB rates are percentages (27.5 means 27.5%). IP is mathematical innings: 10 and one-third innings is 10.3333, not baseball notation 10.1. OPS must agree with OBP + SLG within rounding tolerance. Use numbers or null, never numeric strings, currency symbols, or commas. Do not substitute zero for missing values. Use one WAR methodology throughout a file. Defensive runs must use the same definition throughout. The importer checks numeric ranges and missingness; it cannot establish metric licensing, source accuracy, or that all sources used the same computation. ## Provenance `sources` is an object with separate `identity`, `stats`, `advanced`, `salary`, `availability`, and `contract` entries. Each populated entry is: ```json { "name": "Publisher and dataset title", "url": "https://publisher.example/path-to-the-record", "asOf": "2026-10-01" } ``` The URL above is a format placeholder. Supply the actual page or endpoint you used. `asOf` is the date the claim was valid or checked—not an invented publication date. Future and impossible dates are rejected. Stats and advanced source dates must not precede the statistical season. - identity and stats are always required. - advanced is required for WAR, wRC+, OPS+, ERA+ or defensive runs. - salary is required when salary is supplied. - availability is required for a known availability status. - contract is required when either remaining-years or remaining-guaranteed-value is supplied. Old sources produce review warnings (550 days for stats/advanced, 180 days for identity, salary, availability and contracts). These thresholds are review prompts, not proof that newer information is correct. A reported trade candidate is not necessarily being offered. A free agent's salary should normally be a sourced asking-price estimate; do not label an expired prior salary as a current agreed salary. ## Data coverage and ranking All scores require salary and WAR. Offensive production additionally needs wRC+; on-base needs OBP; power needs SLG; defense needs defensive runs; pitching needs ERA+, K%, and BB%. Missing requirements exclude a player only from searches that need them. Missing display-only statistics appear as a dash. Rankings do not estimate missing statistics or compensation. Salary basis is shown alongside every candidate. Filter to one basis for a like-for-like comparison. A contract term limit excludes unknown term values; zero years means no remaining guaranteed years. Free-agent records with nonzero remaining guaranteed terms/commitments are rejected. ## MLB lookup The server requests `https://statsapi.mlb.com/api/v1/people/{id}?hydrate=currentTeam` and `https://statsapi.mlb.com/api/v1/people/{id}/stats?stats=season&group=hitting&season={year}&sportIds=1` (or `group=pitching`). It verifies returned IDs and uses one unambiguous regular-season total. Current team and season statistics have separate sources. Pitcher role is chosen by the importer; it is not inferred from a generic P designation. MLB does not populate this app's salary, contract status, WAR, DRS or adjusted production fields. Those remain null/unknown. Add values from sources you have permission to use, with their own dates and URLs, then reimport. A successful basic MLB import may therefore produce zero ranked candidates until enriched.