{"openapi":"3.1.0","info":{"title":"Zafronix World Cup API","version":"1.2.0","summary":"Historical FIFA World Cup data (1930-2026) plus 2026 live state.","description":"Read endpoints under /fifa/worldcup/v1/*. Authenticated via X-API-Key. See https://api.zafronix.com/docs for prose docs.","contact":{"name":"Zafronix Support","url":"https://zafronix.com/contact?subject=worldcup-api"},"license":{"name":"Commercial — see /pricing","url":"https://api.zafronix.com/pricing"}},"servers":[{"url":"https://api.zafronix.com/fifa/worldcup/v1","description":"Production"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Read keys: zwc_pk_*, zwc_free_*. Write keys: zwc_sk_*. Sandbox: zwc_skt_*."}},"schemas":{"Error":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","example":"not_found"},"message":{"type":"string"},"request_id":{"type":"string"},"detail":{"type":"object"}}},"Tournament":{"type":"object","additionalProperties":true,"description":"Full tournament document. See /docs#tournaments."},"Match":{"type":"object","additionalProperties":true,"description":"Match record. See /docs#matches."},"Standing":{"type":"object","additionalProperties":true,"description":"Computed group-table row. See /docs#standings."},"BracketSlot":{"type":"object","additionalProperties":true,"description":"KO bracket slot with placeholder→team resolution."},"HistoryEvent":{"type":"object","additionalProperties":true,"description":"Audit log entry for a write operation."},"Flag":{"type":"object","properties":{"iso":{"type":["string","null"]},"iso3166_3":{"type":["string","null"]},"fifaCode":{"type":["string","null"]},"flagUrl":{"type":"string"},"flagAttribution":{"type":"string"}}}},"parameters":{"Year":{"name":"year","in":"query","required":true,"schema":{"type":"integer","minimum":1930,"maximum":9999}},"OptionalYear":{"name":"year","in":"query","required":false,"schema":{"type":"integer","minimum":1930,"maximum":9999}},"MatchId":{"name":"matchId","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{3}$"}},"Cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque pagination cursor from a previous response."},"Limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}},"TeamName":{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"Team name. Hyphens treated as spaces, case-insensitive."}}},"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Meta"},{"name":"Tournaments"},{"name":"Teams"},{"name":"Matches"},{"name":"Match Writes"},{"name":"Computed"},{"name":"Players"},{"name":"Stadiums"},{"name":"Referees"},{"name":"Trivia"},{"name":"Other"},{"name":"Aggregates"},{"name":"Discovery"},{"name":"Sandbox"}],"paths":{"/":{"get":{"summary":"API info","security":[],"tags":["Meta"],"responses":{"200":{"description":"OK"}}}},"/health":{"get":{"summary":"Health probe","security":[],"tags":["Meta"],"responses":{"200":{"description":"OK"},"503":{"description":"Dataset failed to load"}}}},"/tournaments":{"get":{"summary":"List all tournaments","security":[],"tags":["Tournaments"],"responses":{"200":{"description":"OK","headers":{"Cache-Control":{"schema":{"type":"string"},"description":"Tier-specific freshness directive."},"ETag":{"schema":{"type":"string"},"description":"SHA-256 prefix of the response body. Send back as If-None-Match for 304."}}},"304":{"description":"Not Modified"}}}},"/tournaments/{year}":{"get":{"summary":"Tournament document with teams + flag metadata","tags":["Tournaments"],"parameters":[{"name":"year","in":"path","required":true,"schema":{"type":"integer","minimum":1930,"maximum":9999}}],"responses":{"200":{"description":"OK","headers":{"Cache-Control":{"schema":{"type":"string"},"description":"Tier-specific freshness directive."},"ETag":{"schema":{"type":"string"},"description":"SHA-256 prefix of the response body. Send back as If-None-Match for 304."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Daily quota for the caller key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Epoch seconds when the window resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tournament"}}}},"304":{"description":"Not Modified"},"401":{"description":"Unauthorized"},"404":{"description":"Year not found"}}}},"/teams":{"get":{"summary":"Teams in a tournament or cross-tournament lookup by country","tags":["Teams"],"description":"Provide exactly one of `?tournament=YYYY` (returns all teams in that year) or `?country=<name>` (returns cross-tournament appearances for that country, equivalent to `GET /teams/{name}`). Hyphens in country names are treated as spaces.","parameters":[{"name":"tournament","in":"query","required":false,"schema":{"type":"integer","minimum":1930,"maximum":9999},"description":"4-digit tournament year. Mutually exclusive with country."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"Country name. Hyphens treated as spaces. Mutually exclusive with tournament. Example: New-Zealand"}],"responses":{"200":{"description":"OK","headers":{"Cache-Control":{"schema":{"type":"string"},"description":"Tier-specific freshness directive."},"ETag":{"schema":{"type":"string"},"description":"SHA-256 prefix of the response body. Send back as If-None-Match for 304."}}},"400":{"description":"Neither or both params supplied"},"404":{"description":"Tournament year or country not found"}}}},"/teams/{name}":{"get":{"summary":"Cross-tournament appearances + flag","tags":["Teams"],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Team not found"}}}},"/teams/{name}/roster":{"get":{"summary":"Squad for a single tournament","tags":["Teams"],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Year"}],"responses":{"200":{"description":"OK"},"404":{"description":"Team or year not found"}}}},"/teams/{name}/rivalries":{"get":{"summary":"Top rivalries for a specific team","tags":["Teams"],"parameters":[{"$ref":"#/components/parameters/TeamName"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":5},"description":"Max rivalries to return."}],"responses":{"200":{"description":"OK"},"404":{"description":"Team not found or no rivalry data"}}}},"/referees":{"get":{"summary":"List referees across all World Cups","tags":["Referees"],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Substring search on referee name."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by country (case-insensitive exact match)."},{"name":"year","in":"query","required":false,"schema":{"type":"integer","minimum":1930,"maximum":9999},"description":"Filter to referees who officiated in this year."},{"$ref":"#/components/parameters/Limit"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"OK"}}}},"/referees/{id}":{"get":{"summary":"Single referee with full match list","tags":["Referees"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Slug of the referee name (lowercase, accents stripped, hyphens)."}],"responses":{"200":{"description":"OK"},"404":{"description":"Referee not found"}}}},"/on-this-day":{"get":{"summary":"World Cup matches and facts for a given calendar date","tags":["Trivia"],"parameters":[{"name":"date","in":"query","required":false,"schema":{"type":"string","pattern":"^(\\d{4}-)?\\d{2}-\\d{2}$"},"description":"MM-DD (anniversary across all years) or YYYY-MM-DD (single date). Defaults to today (UTC)."}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid date format"}}}},"/matches":{"get":{"summary":"List matches. With ?year — single tournament. Without ?year — cursor-paginated cross-tournament.","tags":["Matches"],"parameters":[{"$ref":"#/components/parameters/OptionalYear"},{"name":"stage","in":"query","schema":{"type":"string"},"description":"Accepts both legacy (qf, r32) and canonical (quarter_final, round_of_32)."},{"name":"team","in":"query","schema":{"type":"string"}},{"name":"stadiumId","in":"query","schema":{"type":"string"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"OK"}}}},"/matches/{matchId}":{"get":{"summary":"Single match","tags":["Matches"],"parameters":[{"$ref":"#/components/parameters/MatchId"}],"responses":{"200":{"description":"OK"},"404":{"description":"Match not found"}}},"patch":{"summary":"Correct fields on a finalized match","tags":["Match Writes"],"parameters":[{"$ref":"#/components/parameters/MatchId"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Match not found"},"422":{"description":"Validation error"}}}},"/matches/{matchId}/history":{"get":{"summary":"Audit log for a match","tags":["Matches"],"parameters":[{"$ref":"#/components/parameters/MatchId"}],"responses":{"200":{"description":"OK"},"404":{"description":"Match not found"}}}},"/matches/{matchId}/result":{"post":{"summary":"Finalize a scoreline","tags":["Match Writes"],"parameters":[{"$ref":"#/components/parameters/MatchId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["homeScore","awayScore"],"properties":{"homeScore":{"type":"integer","minimum":0},"awayScore":{"type":"integer","minimum":0},"extraTime":{"type":"boolean"},"penalties":{"type":"object","properties":{"home":{"type":"integer"},"away":{"type":"integer"}}},"attendance":{"type":"integer"},"referee":{"type":"object","properties":{"name":{"type":"string"},"country":{"type":"string"}}},"finalizedAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Match"}}}},"403":{"description":"Read key on write endpoint"},"404":{"description":"Match not found"},"409":{"description":"Already finalized — use PATCH for corrections"},"422":{"description":"Validation error"}}}},"/matches/{matchId}/postpone":{"post":{"summary":"Mark postponed/abandoned/cancelled","tags":["Match Writes"],"parameters":[{"$ref":"#/components/parameters/MatchId"}],"responses":{"200":{"description":"OK"},"422":{"description":"Validation error"}}}},"/standings":{"get":{"summary":"Group standings with FIFA tiebreakers","tags":["Computed"],"parameters":[{"$ref":"#/components/parameters/Year"},{"name":"group","in":"query","schema":{"type":"string","pattern":"^[A-Za-z]$"}}],"responses":{"200":{"description":"OK"}}}},"/bracket":{"get":{"summary":"KO bracket with placeholder resolution","tags":["Computed"],"parameters":[{"$ref":"#/components/parameters/Year"}],"responses":{"200":{"description":"OK"}}}},"/players":{"get":{"summary":"Search/paginate players","tags":["Players"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","minLength":2,"maxLength":80}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"OK"}}}},"/players/{name}":{"get":{"summary":"Cross-tournament player career","tags":["Players"],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}}}},"/stadiums":{"get":{"summary":"List stadiums","tags":["Stadiums"],"responses":{"200":{"description":"OK"}}}},"/stadiums/{id}":{"get":{"summary":"Stadium by id","tags":["Stadiums"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}}}},"/trivia":{"get":{"summary":"Trivia facts","tags":["Other"],"parameters":[{"name":"year","in":"query","schema":{"type":"integer"}},{"name":"category","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/compare":{"get":{"summary":"Compare years","tags":["Other"],"parameters":[{"name":"years","in":"query","schema":{"type":"string"},"description":"Comma-separated YYYY,YYYY"}],"responses":{"200":{"description":"OK"}}}},"/aggregates/champions":{"get":{"summary":"Title counts by country","tags":["Aggregates"],"responses":{"200":{"description":"OK"}}}},"/aggregates/players":{"get":{"summary":"Position + birth-month + hemisphere splits","tags":["Aggregates"],"parameters":[{"name":"years","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/search":{"get":{"summary":"Cross-entity search (BM25/TF-IDF, accent-folded)","tags":["Discovery"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":120}},{"name":"types","in":"query","schema":{"type":"string"},"description":"Comma-separated: team, player, match, stadium, tournament"},{"$ref":"#/components/parameters/OptionalYear"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid types"}}}},"/me/usage":{"get":{"summary":"Caller usage stats: quota, latency, top endpoints","tags":["Discovery"],"responses":{"200":{"description":"OK","headers":{"Cache-Control":{"schema":{"type":"string","example":"private, no-cache"}}}}}}},"/sandbox/status":{"get":{"summary":"Sandbox state + counters","tags":["Sandbox"],"responses":{"200":{"description":"OK"},"403":{"description":"Sandbox key required"}}}},"/sandbox/reset":{"post":{"summary":"Reset year=9999 fixtures","tags":["Sandbox"],"responses":{"200":{"description":"OK"},"403":{"description":"Sandbox key required"},"429":{"description":"Rate limited (10/hour/key)"}}}}}}