{"openapi":"3.1.0","info":{"title":"UFCalendar Fight API","version":"1.3.0","description":"Fight data API by [UFCalendar](https://www.ufcalendar.com) — MMA + bare-knuckle boxing: events, full cards, results,\nper-fight and per-round statistics, fighters with complete multi-promotion careers,\nofficial rankings history (UFC 2013→), **judges' scorecards** (every round, every official,\nUFC back to 1995), UFCalendar Power Index ratings, AI win probabilities and per-country\nbroadcast rights — for **UFC, PFL, OKTAGON, BKFC and RIZIN**.\n\nKeys live at [ufcalendar.com/account/api](https://www.ufcalendar.com/account/api) — an active plan or the free 1-day trial (100 requests, no card) is required.\nPlans and quotas: [ufcalendar.com/developers](https://www.ufcalendar.com/developers).\n\nBuilt for indie developers, side projects and small teams: fantasy apps, stats sites, Discord bots, analytics\nprojects. Plans are priced for them: self-serve only, no sales-negotiated contracts, and none planned.\n\nConventions: snake_case JSON in a `{\"data\": ..., \"meta\": ...}` envelope (`meta` is ALWAYS present, `{}` at minimum); cursor\npagination; UTC ISO-8601 timestamps plus venue IANA `tz`; errors as\n`{\"error\": {\"code\", \"message\", \"request_id\"}}` (every code is in the `ErrorCode` schema); monthly-quota headers\n`X-RateLimit-Limit/-Remaining/-Reset` and `Retry-After` on 429. Every `GET /v1` 200 carries a weak `ETag` and\n`Cache-Control: private, no-cache`; send `If-None-Match` and an unchanged payload answers 304 with no body.\nEvery response body is described under `components.schemas` — closed objects, nullable as `[T, \"null\"]`, every\nvocabulary an `enum` — so generated clients get real types.\n\n**Odds (2026-09):** one UFCalendar consensus line per corner: the mean across the sportsbooks we track (book\nidentities are never exposed; `sources` is how many backed each point), refreshed every 30 minutes in the 48 hours\nbefore a card and every 2 hours otherwise. Current, opening and closing lines ship on every plan\n(`/v1/fights/{id}/odds`, `/v1/events/{id}/odds`, `include=odds`); the full movement series is Pro and up\n(`/v1/fights/{id}/odds/history`). Information only, not betting advice.\n\n**Source labels (2026-09-26):** `source` / `source_slug` fields name official publishers only — `ufc-stats`,\n`ufc-official`, `ufc-official-cards`, a promotion's own `*-official` slug, `wikipedia`, or `ufcalendar` for our\nown derivations. Every other publisher now ships as `public-records` (career records and history rows) or\n`commission-record` (judges' scorecards); credential `sources` list public reference URLs only.\n\nFighter images are Wikimedia Commons/CC\nonly — the `license`/`artist` fields you receive MUST be displayed as a credit.\nNot affiliated with UFC/Zuffa/TKO or any promotion.\n\nBoth official SDKs (`pip install ufcalendar`, `npm install @ufcalendar/sdk`) are\nconfigured with the base URL `https://api.ufcalendar.com/v1` — the same base every\ncode sample on this page uses.","contact":{"name":"UFCalendar","email":"api@ufcalendar.com","url":"https://www.ufcalendar.com/developers"},"termsOfService":"https://www.ufcalendar.com/developers/terms","x-logo":{"url":"https://www.ufcalendar.com/icon.png","altText":"UFCalendar"},"x-scalar-sdk-installation":[{"lang":"Python","source":"pip install ufcalendar","description":"Python SDK — https://pypi.org/project/ufcalendar/"},{"lang":"TypeScript","source":"npm install @ufcalendar/sdk","description":"TypeScript SDK — https://www.npmjs.com/package/@ufcalendar/sdk"}]},"externalDocs":{"description":"Plans, coverage, guides and the agent (MCP) quickstart","url":"https://www.ufcalendar.com/developers","x-agents-url":"https://www.ufcalendar.com/developers/agents"},"servers":[{"url":"https://api.ufcalendar.com"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key, e.g. `Authorization: Bearer ufcalendar_ab12…`"}},"schemas":{"ErrorCode":{"type":"string","enum":["unauthorized","subscription_required","tier_required","direct_plan_required","rate_limited","quota_exceeded","not_found","invalid_org","unsupported_org","invalid_status","invalid_date","invalid_order","invalid_query","invalid_url","invalid_events","invalid_json","invalid_id","invalid_cursor","endpoint_limit","invalid_include","invalid_boolean","invalid_country","invalid_kind","invalid_method","invalid_division","invalid_view","invalid_series","invalid_locale","invalid_metric","invalid_population","invalid_scope","invalid_filter","filter_required","page_depth_exceeded","internal_error"],"description":"Every `error.code` the API emits."},"EventStatus":{"type":"string","enum":["announced","scheduled","live","completed","cancelled","postponed"],"description":"Event lifecycle. `postponed` is stored and filterable."},"EventStatusFilter":{"type":"string","enum":["announced","scheduled","live","completed","cancelled","postponed","upcoming"],"description":"What `?status=` accepts on the event lists: every `EventStatus`, plus `upcoming` = announced, scheduled or live cards that have not finished (the site's upcoming-or-live window: started under 6 h ago, or under 14 h ago with a bout still to fight). `upcoming` is a filter only — it never appears on an event."},"FightStatus":{"type":"string","enum":["announced","confirmed","cancelled","completed","no_contest"],"description":"Bout lifecycle. `no_contest` is a settled bout with no winner."},"CardSection":{"type":"string","enum":["main","prelims","early_prelims"],"description":"Which part of the card the bout sits on."},"BroadcastKind":{"type":"string","enum":["ppv","sub","free","tv","unknown"],"description":"How the provider carries it: pay-per-view, subscription, free-to-air, linear TV, unknown."},"MethodNormalized":{"type":"string","enum":["ko_tko","submission","technical_submission","decision_unanimous","decision_split","decision_majority","decision","draw","no_contest","dq","other"],"description":"Closed vocabulary over every source spelling of a result method (`normalize.ts`). `other` = a non-empty method nothing matched."},"HistoryStatus":{"type":"string","enum":["win","loss","draw","no_contest","cancelled","upcoming","unknown"],"description":"One status vocabulary across native and history rows."},"RankingsBoard":{"type":"string","enum":["official","meta"],"description":"`official` for every org (for UFC that is the media-panel vote ufc.com publishes); UFC additionally has `meta`."},"Tier":{"type":"string","enum":["trial","hobby","pro","business"],"description":"Plan tier."},"WebhookKind":{"type":"string","enum":["event.announced","event.completed","fight.result","card.changed","odds.moved"],"description":"Webhook event types."},"ChangeKind":{"type":"string","enum":["fight-added","fight-cancelled","fight-reinstated","opponent-changed","time-changed","venue-changed","fighter-merged"],"description":"What a card-change entry describes."},"Corner":{"type":"string","enum":["a","b"],"description":"`a` = `fighter_a` (red), `b` = `fighter_b` (blue)."},"Sport":{"type":"string","description":"Sport slug — `mma`, `bare-knuckle-boxing`. Open: a new sport lands as a new value.","examples":["mma","bare-knuckle-boxing"]},"Error":{"type":"object","description":"Uniform error body on every non-2xx JSON response.","properties":{"error":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable, stable enough to show a user; do not parse."},"request_id":{"type":"string","description":"Also sent as the `x-request-id` header — quote it to support."}},"required":["code","message","request_id"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"Pagination":{"type":"object","properties":{"next_cursor":{"type":["string","null"],"description":"Opaque; pass as `?cursor=`. Null on the last page."},"has_more":{"type":"boolean"},"limit":{"type":"integer","description":"The page size actually applied (out-of-range `limit` values are clamped)."}},"required":["next_cursor","has_more","limit"],"additionalProperties":false},"CursorPagination":{"type":"object","description":"Cursor pagination WITHOUT the applied `limit` (the newer list routes — changes, fight search, splits, venues, articles — do not echo it).","properties":{"next_cursor":{"type":["string","null"],"description":"Opaque; pass as `?cursor=`. Null on the last page."},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"],"additionalProperties":false},"EmptyMeta":{"type":"object","description":"`meta` is always present; `{}` when the endpoint has nothing to add.","properties":{"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":[],"additionalProperties":false},"OrgCapabilities":{"type":"object","description":"Which datasets this org has coverage for.","properties":{"stats":{"type":"boolean"},"rounds":{"type":"boolean"},"rankings":{"type":"boolean"},"broadcasts":{"type":"boolean"},"predictions":{"type":"boolean"},"scorecards":{"type":"boolean"},"odds":{"type":"boolean","description":"UFCalendar consensus odds (`/v1/fights/{id}/odds`)."}},"required":["stats","rounds","rankings","broadcasts","predictions","scorecards","odds"],"additionalProperties":false},"Org":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"short_name":{"type":["string","null"]},"country":{"type":["string","null"],"description":"Country as stored (a name or an ISO-2 code, depending on the org)."},"country_code":{"type":["string","null"],"description":"ISO-2 derived from `country`."},"website":{"type":["string","null"]},"sport":{"$ref":"#/components/schemas/Sport"},"capabilities":{"$ref":"#/components/schemas/OrgCapabilities"}},"required":["id","slug","name","short_name","country","country_code","website","sport","capabilities"],"additionalProperties":false},"Event":{"type":"object","description":"List-shape event (no card). `headline` is present only with `?include=headline`.","properties":{"id":{"type":"integer"},"slug":{"type":"string","description":"Frozen once published; renamed events keep an alias that 308-redirects."},"title":{"type":"string"},"short_title":{"type":["string","null"],"description":"Short display title (`DWCS 93`); null when the title is already short."},"numbering":{"type":["string","null"],"description":"`UFC 320`, `DWCS 93`, … null for un-numbered cards."},"org":{"type":"string","description":"Org slug (`ufc`, `pfl`, `oktagon`, `bkfc`, `rizin`)."},"sport":{"$ref":"#/components/schemas/Sport"},"starts_at":{"type":"string","format":"date-time","description":"First bell (UTC)."},"main_card_at":{"type":["string","null"],"format":"date-time"},"prelims_at":{"type":["string","null"],"format":"date-time"},"early_prelims_at":{"type":["string","null"],"format":"date-time"},"tz":{"type":["string","null"],"description":"IANA zone of the venue."},"status":{"$ref":"#/components/schemas/EventStatus"},"is_ppv":{"type":"boolean"},"is_title_card":{"type":"boolean"},"headline":{"oneOf":[{"$ref":"#/components/schemas/EventHeadline"},{"type":"null"}]}},"required":["id","slug","title","short_title","numbering","org","sport","starts_at","main_card_at","prelims_at","early_prelims_at","tz","status","is_ppv","is_title_card"],"additionalProperties":false},"HeadlineCorner":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","slug","name"],"additionalProperties":false},"EventHeadline":{"type":"object","description":"The main event of a list-shape event (`?include=headline`). A replaced main event is skipped in favour of the active one.","properties":{"fight_id":{"type":"integer"},"fighter_a":{"oneOf":[{"$ref":"#/components/schemas/HeadlineCorner"},{"type":"null"}]},"fighter_b":{"oneOf":[{"$ref":"#/components/schemas/HeadlineCorner"},{"type":"null"}]},"weight_class":{"type":["string","null"]},"is_title":{"type":"boolean"},"winner_fighter_id":{"type":["integer","null"]},"method":{"type":["string","null"],"description":"Source spelling; null until the bout is settled."},"round":{"type":["integer","null"]},"time":{"type":["string","null"]}},"required":["fight_id","fighter_a","fighter_b","weight_class","is_title","winner_fighter_id","method","round","time"],"additionalProperties":false},"EventVenue":{"type":"object","description":"Venue as embedded on an event — the same shape as `GET /v1/venues/{id}`.","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":"string"},"city":{"type":["string","null"]},"region":{"type":["string","null"],"description":"State / province / prefecture."},"country":{"type":["string","null"]},"country_code":{"type":["string","null"],"description":"ISO-2 derived from `country`."},"tz":{"type":["string","null"]},"capacity":{"type":["integer","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["id","slug","name","city","region","country","country_code","tz","capacity","lat","lng"],"additionalProperties":false},"EventBroadcast":{"type":"object","description":"Event-scoped broadcast row.","properties":{"region":{"type":"string","description":"ISO-2 country code or `WORLD`."},"provider":{"type":"string"},"kind":{"$ref":"#/components/schemas/BroadcastKind"},"url":{"type":["string","null"]}},"required":["region","provider","kind","url"],"additionalProperties":false},"EventDetail":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string","description":"Frozen once published; renamed events keep an alias that 308-redirects."},"title":{"type":"string"},"short_title":{"type":["string","null"],"description":"Short display title (`DWCS 93`); null when the title is already short."},"numbering":{"type":["string","null"],"description":"`UFC 320`, `DWCS 93`, … null for un-numbered cards."},"org":{"type":"string","description":"Org slug (`ufc`, `pfl`, `oktagon`, `bkfc`, `rizin`)."},"sport":{"$ref":"#/components/schemas/Sport"},"starts_at":{"type":"string","format":"date-time","description":"First bell (UTC)."},"main_card_at":{"type":["string","null"],"format":"date-time"},"prelims_at":{"type":["string","null"],"format":"date-time"},"early_prelims_at":{"type":["string","null"],"format":"date-time"},"tz":{"type":["string","null"],"description":"IANA zone of the venue."},"status":{"$ref":"#/components/schemas/EventStatus"},"is_ppv":{"type":"boolean"},"is_title_card":{"type":"boolean"},"venue":{"oneOf":[{"$ref":"#/components/schemas/EventVenue"},{"type":"null"}]},"card":{"type":"array","items":{"$ref":"#/components/schemas/Fight"},"description":"Every bout, `ordering` ascending (headliner first). Cancelled bouts stay on the card with `status: cancelled`."},"broadcasts":{"type":"array","items":{"$ref":"#/components/schemas/EventBroadcast"}}},"required":["id","slug","title","short_title","numbering","org","sport","starts_at","main_card_at","prelims_at","early_prelims_at","tz","status","is_ppv","is_title_card","venue","card","broadcasts"],"additionalProperties":false},"EventChange":{"type":"object","properties":{"id":{"type":"integer","description":"Change-log row id (the cursor unit on `/v1/changes`)."},"kind":{"$ref":"#/components/schemas/ChangeKind"},"before":{"type":["object","null"],"additionalProperties":true,"description":"Payload before the change; shape depends on `kind`. Null for `fight-added`."},"after":{"type":["object","null"],"additionalProperties":true,"description":"Payload after the change; shape depends on `kind`. Null for `fight-cancelled`."},"observed_at":{"type":"string","format":"date-time"}},"required":["id","kind","before","after","observed_at"],"additionalProperties":false},"FighterRef":{"type":"object","description":"The one fighter-reference shape every card, fight and search row carries.","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nickname":{"type":["string","null"]},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it (e.g. `United States`)."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`; null when the name is unknown to our table."}},"required":["id","slug","name","nickname","nationality","country_code"],"additionalProperties":false},"FightResult":{"type":"object","properties":{"winner_fighter_id":{"type":["integer","null"],"description":"Null on a draw or no-contest."},"method":{"type":["string","null"],"description":"Source spelling (`Decision - Split`, `KO/TKO`, `Submission (Rear-Naked Choke)`)."},"method_normalized":{"oneOf":[{"$ref":"#/components/schemas/MethodNormalized"},{"type":"null"}]},"finish_detail":{"type":["string","null"],"description":"The parenthesised / trailing detail of `method`, cleaned (`Rear-Naked Choke`, `Doctor's Stoppage`)."},"round":{"type":["integer","null"]},"time":{"type":["string","null"],"description":"`m:ss` into the round."},"time_seconds":{"type":["integer","null"],"description":"`time` in seconds."},"details":{"type":["string","null"],"description":"Free text from the source — judges' totals on a decision, the strike on a KO."}},"required":["winner_fighter_id","method","method_normalized","finish_detail","round","time","time_seconds","details"],"additionalProperties":false},"Fight":{"type":"object","description":"One bout as it sits on a card.","properties":{"id":{"type":"integer"},"ordering":{"type":["integer","null"],"description":"1 = the headliner; ascends down the card."},"card_section":{"oneOf":[{"$ref":"#/components/schemas/CardSection"},{"type":"null"}]},"sport":{"$ref":"#/components/schemas/Sport"},"weight_class":{"type":["string","null"],"description":"Source spelling (`Featherweight`, `Catchweight 150 lbs`)."},"division_slug":{"type":["string","null"],"description":"Slug twin in the rankings vocabulary (`womens-strawweight`, `catchweight`); null when the text matches no division."},"is_title":{"type":"boolean"},"is_main":{"type":"boolean"},"scheduled_rounds":{"type":["integer","null"]},"status":{"oneOf":[{"$ref":"#/components/schemas/FightStatus"},{"type":"null"}]},"fighter_a":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"fighter_b":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"result":{"oneOf":[{"$ref":"#/components/schemas/FightResult"},{"type":"null"}]},"referee":{"type":["string","null"]},"bonus":{"type":["string","null"],"description":"Post-fight bonus label when awarded (`Performance of the Night`, `Fight of the Night`)."},"eta":{"type":["string","null"],"format":"date-time","description":"Estimated start of this bout (`?include=eta` on the event route only). An estimate, not a schedule; null for a cancelled bout."},"odds":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The current UFCalendar consensus line, the closing line once the bout is settled (`?include=odds` on the event route only); null when the bout is unpriced."}},"required":["id","ordering","card_section","sport","weight_class","division_slug","is_title","is_main","scheduled_rounds","status","fighter_a","fighter_b","result","referee","bonus"],"additionalProperties":false},"FightDetail":{"type":"object","description":"A bout with its event — `/v1/fights/{id}`, `/v1/fights/search` rows and the division route's `upcoming` / `recent` lists.","properties":{"id":{"type":"integer"},"ordering":{"type":["integer","null"],"description":"1 = the headliner; ascends down the card."},"card_section":{"oneOf":[{"$ref":"#/components/schemas/CardSection"},{"type":"null"}]},"sport":{"$ref":"#/components/schemas/Sport"},"weight_class":{"type":["string","null"],"description":"Source spelling (`Featherweight`, `Catchweight 150 lbs`)."},"division_slug":{"type":["string","null"],"description":"Slug twin in the rankings vocabulary (`womens-strawweight`, `catchweight`); null when the text matches no division."},"is_title":{"type":"boolean"},"is_main":{"type":"boolean"},"scheduled_rounds":{"type":["integer","null"]},"status":{"oneOf":[{"$ref":"#/components/schemas/FightStatus"},{"type":"null"}]},"fighter_a":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"fighter_b":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"result":{"oneOf":[{"$ref":"#/components/schemas/FightResult"},{"type":"null"}]},"referee":{"type":["string","null"]},"bonus":{"type":["string","null"],"description":"Post-fight bonus label when awarded (`Performance of the Night`, `Fight of the Night`)."},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"odds":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The current UFCalendar consensus line, the closing line once the bout is settled (`/v1/fights/{id}?include=odds` only); null when the bout is unpriced."}},"required":["id","ordering","card_section","sport","weight_class","division_slug","is_title","is_main","scheduled_rounds","status","fighter_a","fighter_b","result","referee","bonus","event"],"additionalProperties":false},"FightStatLine":{"type":"object","description":"Per-fight totals for ONE corner. Target/position splits are null where the source does not log them.","properties":{"fighter_id":{"type":"integer"},"fighter_position":{"type":"integer","description":"Stored corner encoding: 1 = `fighter_a`, 2 = `fighter_b`. Prefer `corner`."},"corner":{"type":["string","null"],"enum":["a","b",null],"description":"`a` = the bout's `fighter_a`, `b` = `fighter_b` (2026-09-24)."},"knockdowns":{"type":["integer","null"]},"sig_strikes_landed":{"type":["integer","null"]},"sig_strikes_attempted":{"type":["integer","null"]},"total_strikes_landed":{"type":["integer","null"]},"total_strikes_attempted":{"type":["integer","null"]},"takedowns_landed":{"type":["integer","null"]},"takedowns_attempted":{"type":["integer","null"]},"submission_attempts":{"type":["integer","null"]},"reversals":{"type":["integer","null"]},"control_time_sec":{"type":["integer","null"],"description":"Seconds of control time."},"distance_time_sec":{"type":["integer","null"],"description":"Seconds spent at distance; null where the bout has no position-time data."},"clinch_time_sec":{"type":["integer","null"],"description":"Seconds spent in the clinch; null where the bout has no position-time data."},"ground_time_sec":{"type":["integer","null"],"description":"Seconds spent on the ground; null where the bout has no position-time data."},"head_landed":{"type":["integer","null"]},"head_attempted":{"type":["integer","null"]},"body_landed":{"type":["integer","null"]},"body_attempted":{"type":["integer","null"]},"leg_landed":{"type":["integer","null"]},"leg_attempted":{"type":["integer","null"]},"distance_landed":{"type":["integer","null"]},"distance_attempted":{"type":["integer","null"]},"clinch_landed":{"type":["integer","null"]},"clinch_attempted":{"type":["integer","null"]},"ground_landed":{"type":["integer","null"]},"ground_attempted":{"type":["integer","null"]}},"required":["fighter_id","fighter_position","corner","knockdowns","sig_strikes_landed","sig_strikes_attempted","total_strikes_landed","total_strikes_attempted","takedowns_landed","takedowns_attempted","submission_attempts","reversals","control_time_sec","distance_time_sec","clinch_time_sec","ground_time_sec","head_landed","head_attempted","body_landed","body_attempted","leg_landed","leg_attempted","distance_landed","distance_attempted","clinch_landed","clinch_attempted","ground_landed","ground_attempted"],"additionalProperties":false},"RoundStatLine":{"type":"object","description":"One corner's line for one round.","properties":{"round_number":{"type":"integer","description":"Stored column; same as `round`."},"fighter_id":{"type":"integer"},"fighter_position":{"type":"integer","description":"Stored corner encoding: 1 = `fighter_a`, 2 = `fighter_b`. Prefer `corner`."},"corner":{"type":["string","null"],"enum":["a","b",null],"description":"`a` = the bout's `fighter_a`, `b` = `fighter_b` (2026-09-24)."},"knockdowns":{"type":["integer","null"]},"sig_strikes_landed":{"type":["integer","null"]},"sig_strikes_attempted":{"type":["integer","null"]},"total_strikes_landed":{"type":["integer","null"]},"total_strikes_attempted":{"type":["integer","null"]},"takedowns_landed":{"type":["integer","null"]},"takedowns_attempted":{"type":["integer","null"]},"submission_attempts":{"type":["integer","null"]},"reversals":{"type":["integer","null"]},"control_time_sec":{"type":["integer","null"],"description":"Seconds of control time."},"distance_time_sec":{"type":["integer","null"],"description":"Seconds spent at distance; null where the bout has no position-time data."},"clinch_time_sec":{"type":["integer","null"],"description":"Seconds spent in the clinch; null where the bout has no position-time data."},"ground_time_sec":{"type":["integer","null"],"description":"Seconds spent on the ground; null where the bout has no position-time data."},"head_landed":{"type":["integer","null"]},"head_attempted":{"type":["integer","null"]},"body_landed":{"type":["integer","null"]},"body_attempted":{"type":["integer","null"]},"leg_landed":{"type":["integer","null"]},"leg_attempted":{"type":["integer","null"]},"distance_landed":{"type":["integer","null"]},"distance_attempted":{"type":["integer","null"]},"clinch_landed":{"type":["integer","null"]},"clinch_attempted":{"type":["integer","null"]},"ground_landed":{"type":["integer","null"]},"ground_attempted":{"type":["integer","null"]},"round":{"type":"integer","description":"1-based round number."}},"required":["round_number","fighter_id","fighter_position","corner","knockdowns","sig_strikes_landed","sig_strikes_attempted","total_strikes_landed","total_strikes_attempted","takedowns_landed","takedowns_attempted","submission_attempts","reversals","control_time_sec","distance_time_sec","clinch_time_sec","ground_time_sec","head_landed","head_attempted","body_landed","body_attempted","leg_landed","leg_attempted","distance_landed","distance_attempted","clinch_landed","clinch_attempted","ground_landed","ground_attempted","round"],"additionalProperties":false},"ScoreRound":{"type":"object","properties":{"round":{"type":"integer"},"a":{"type":["integer","null"]},"b":{"type":["integer","null"]}},"required":["round","a","b"],"additionalProperties":false},"JudgeCard":{"type":"object","description":"One judge's card for one bout.","properties":{"judge_id":{"type":["integer","null"],"description":"Null on PFL's US results-post cards (no judge identity published)."},"judge_name":{"type":["string","null"]},"total_a":{"type":["integer","null"],"description":"Oriented to the bout's `fighter_a_id`."},"total_b":{"type":["integer","null"],"description":"Oriented to the bout's `fighter_b_id`."},"winner_fighter_id":{"type":["integer","null"],"description":"Who THIS judge gave it to."},"is_draw":{"type":"boolean"},"scores_known":{"type":"boolean","description":"false ⇒ the commission published the outcome only; totals are a 1-0 / 1-1 / 0-0 placeholder and `rounds` is empty."},"rounds":{"type":"array","items":{"$ref":"#/components/schemas/ScoreRound"}}},"required":["judge_id","judge_name","total_a","total_b","winner_fighter_id","is_draw","scores_known","rounds"],"additionalProperties":false},"Deduction":{"type":"object","properties":{"side":{"type":["string","null"],"enum":["a","b",null]},"fighter_id":{"type":["integer","null"],"description":"`side` resolved to the fighter id."},"points":{"type":["integer","null"]},"round":{"type":["integer","null"]},"reason":{"type":["string","null"],"description":"Null when the commission published no reason."}},"required":["side","fighter_id","points","round","reason"],"additionalProperties":false},"Scorecards":{"type":"object","description":"The official athletic-commission record for one bout.","properties":{"fight_id":{"type":"integer"},"fighter_a_id":{"type":["integer","null"]},"fighter_b_id":{"type":["integer","null"]},"decision_type":{"type":["string","null"],"description":"`unanimous`, `split`, `majority`, … as the commission record states; null when no record exists."},"deductions":{"type":"array","items":{"$ref":"#/components/schemas/Deduction"}},"cards":{"type":"array","items":{"$ref":"#/components/schemas/JudgeCard"},"description":"Empty when no commission record exists for the bout (a finish, or cards not yet published)."},"source":{"type":["string","null"],"description":"Who published the cards: a promotion's own slug when it publishes the record itself (`oktagon-official`, `pfl-official`, `aca-official`), `ufc-official-cards` for the scorecards ufc.com publishes, else `commission-record` (the athletic-commission / officials-body record). Null on the empty record."}},"required":["fight_id","fighter_a_id","fighter_b_id","decision_type","deductions","cards","source"],"additionalProperties":false},"Judge":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"fights":{"type":"integer","description":"Bouts scored in launch scope."},"rounds_scored":{"type":"integer"},"wide_rounds":{"type":"integer","description":"Rounds scored 10-8 or wider."},"split_fights":{"type":"integer","description":"Three-judge cards of theirs where the panel did not agree."},"three_judge_fights":{"type":"integer"},"lone_dissents":{"type":"integer","description":"Three-judge cards where this judge alone picked the other corner."},"first_scored":{"type":["string","null"],"format":"date"},"last_scored":{"type":["string","null"],"format":"date"},"orgs":{"type":"array","items":{"type":"string"}}},"required":["id","name","fights","rounds_scored","wide_rounds","split_fights","three_judge_fights","lone_dissents","first_scored","last_scored","orgs"],"additionalProperties":false},"JudgeLeague":{"type":"object","description":"The whole directory's baseline (never the filtered subset), so a judge's rates read against the league.","properties":{"judges":{"type":"integer"},"fights":{"type":"integer","description":"Judge-cards (one per judge per bout), the same unit as a directory row."},"rounds_scored":{"type":"integer"},"wide_round_rate":{"type":["number","null"],"description":"wide rounds / rounds scored, pooled."},"split_rate":{"type":["number","null"],"description":"split / three-judge cards, pooled."},"lone_dissent_rate":{"type":["number","null"],"description":"lone dissents / three-judge cards, pooled."}},"required":["judges","fights","rounds_scored","wide_round_rate","split_rate","lone_dissent_rate"],"additionalProperties":false},"Colleague":{"type":"object","description":"Another judge's card on the same bout, totals and verdict only.","properties":{"judge_id":{"type":["integer","null"]},"judge_name":{"type":["string","null"]},"total_a":{"type":["integer","null"]},"total_b":{"type":["integer","null"]},"winner_fighter_id":{"type":["integer","null"]},"is_draw":{"type":"boolean"}},"required":["judge_id","judge_name","total_a","total_b","winner_fighter_id","is_draw"],"additionalProperties":false},"JudgeScorecardEntry":{"type":"object","description":"One bout as scored by ONE judge (the full panel is on `/v1/fights/{id}/scorecards`).","properties":{"fight_id":{"type":"integer"},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"fighter_a_id":{"type":["integer","null"]},"fighter_b_id":{"type":["integer","null"]},"decision_type":{"type":["string","null"]},"card":{"oneOf":[{"$ref":"#/components/schemas/JudgeCard"},{"type":"null"}]},"lone_dissent":{"type":["boolean","null"],"description":"true = three known verdicts and this judge alone differs from both others; null = not a three-judge panel, or a verdict is unknown."},"split":{"type":["boolean","null"],"description":"true = three known verdicts that do not all agree; null as above."},"colleagues":{"type":"array","items":{"$ref":"#/components/schemas/Colleague"}}},"required":["fight_id","event","fighter_a_id","fighter_b_id","decision_type","card","lone_dissent","split","colleagues"],"additionalProperties":false},"DissentingJudge":{"type":"object","properties":{"judge_id":{"type":["integer","null"]},"judge_name":{"type":["string","null"]},"total_a":{"type":["integer","null"]},"total_b":{"type":["integer","null"]},"winner_fighter_id":{"type":["integer","null"]},"is_draw":{"type":"boolean"},"scores_known":{"type":"boolean","description":"false = an outcome-only card; still a readable verdict, flagged."}},"required":["judge_id","judge_name","total_a","total_b","winner_fighter_id","is_draw","scores_known"],"additionalProperties":false},"SplitDecision":{"type":"object","description":"A bout the judges decided on a split or majority — the bout, its event, every card and the dissenters.","properties":{"id":{"type":"integer"},"ordering":{"type":["integer","null"],"description":"1 = the headliner; ascends down the card."},"card_section":{"oneOf":[{"$ref":"#/components/schemas/CardSection"},{"type":"null"}]},"sport":{"$ref":"#/components/schemas/Sport"},"weight_class":{"type":["string","null"],"description":"Source spelling (`Featherweight`, `Catchweight 150 lbs`)."},"division_slug":{"type":["string","null"],"description":"Slug twin in the rankings vocabulary (`womens-strawweight`, `catchweight`); null when the text matches no division."},"is_title":{"type":"boolean"},"is_main":{"type":"boolean"},"scheduled_rounds":{"type":["integer","null"]},"status":{"oneOf":[{"$ref":"#/components/schemas/FightStatus"},{"type":"null"}]},"fighter_a":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"fighter_b":{"oneOf":[{"$ref":"#/components/schemas/FighterRef"},{"type":"null"}]},"result":{"oneOf":[{"$ref":"#/components/schemas/FightResult"},{"type":"null"}]},"referee":{"type":["string","null"]},"bonus":{"type":["string","null"],"description":"Post-fight bonus label when awarded (`Performance of the Night`, `Fight of the Night`)."},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"decision_type":{"type":"string","description":"`split`, `majority`, `split draw`, `majority draw`, … as the commission record states."},"official_winner_fighter_id":{"type":["integer","null"],"description":"Null on a draw."},"cards":{"type":"array","items":{"$ref":"#/components/schemas/JudgeCard"}},"dissenting_judges":{"type":"array","items":{"$ref":"#/components/schemas/DissentingJudge"},"description":"Cards that disagree with the official result."}},"required":["id","ordering","card_section","sport","weight_class","division_slug","is_title","is_main","scheduled_rounds","status","fighter_a","fighter_b","result","referee","bonus","event","decision_type","official_winner_fighter_id","cards","dissenting_judges"],"additionalProperties":false},"FighterListItem":{"type":"object","description":"Roster-search row: identity only (the bio lives on the detail route).","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nickname":{"type":["string","null"]},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it (e.g. `United States`)."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`; null when the name is unknown to our table."},"second_nationality":{"type":["string","null"],"description":"A second nationality NAME when the source lists one."}},"required":["id","slug","name","nickname","nationality","country_code","second_nationality"],"additionalProperties":false},"RecordEntry":{"type":"object","description":"Structured twins of `value` are null when the string does not parse.","properties":{"value":{"type":"string","description":"`W-L-D`, optionally ` (n NC)`."},"wins":{"type":["integer","null"]},"losses":{"type":["integer","null"]},"draws":{"type":["integer","null"]},"no_contests":{"type":["integer","null"]},"source":{"type":"string","description":"Who published the record: `ufc-stats` (ufcstats.com), a promotion's own site (`ufc-official`, `bkfc-official`, `one-official`, `oktagon-official`, …), `ufcalendar` (derived by UFCalendar), or `public-records` (the complete multi-promotion career record compiled from public records)."},"scope":{"type":"string","description":"The `career_stats` scope this came from (`pro-mma`, `ufc-only`, …)."}},"required":["value","wins","losses","draws","no_contests","source","scope"],"additionalProperties":false},"StatsBasis":{"type":"object","properties":{"bouts":{"type":"integer","description":"How many settled bouts the panel averages over."},"orgs":{"type":"array","items":{"type":"string"},"description":"Org slugs those bouts span."},"source":{"type":"string","description":"`ufcalendar` for the every-promotion panel, else the `ufc-only` row's source. Both are computed by UFCalendar from per-fight totals."},"scope":{"type":"string","description":"`pro-mma` (every settled bout with per-fight totals, any promotion) or `ufc-only` (UFC bouts only, Contender Series excluded)."}},"required":["bouts","orgs","source","scope"],"additionalProperties":false},"StatsPanel":{"type":"object","description":"ONE per-minute panel: the widest sample UFCalendar holds for the fighter.","properties":{"slpm":{"type":["string","null"],"description":"Significant strikes landed per minute. Display string (`\"1.34\"`, `\"42%\"`)."},"str_acc":{"type":["string","null"],"description":"Significant-strike accuracy. Display string (`\"1.34\"`, `\"42%\"`)."},"sapm":{"type":["string","null"],"description":"Significant strikes absorbed per minute. Display string (`\"1.34\"`, `\"42%\"`)."},"str_def":{"type":["string","null"],"description":"Significant-strike defence. Display string (`\"1.34\"`, `\"42%\"`)."},"td_avg":{"type":["string","null"],"description":"Takedowns landed per 15 minutes. Display string (`\"1.34\"`, `\"42%\"`)."},"td_acc":{"type":["string","null"],"description":"Takedown accuracy. Display string (`\"1.34\"`, `\"42%\"`)."},"td_def":{"type":["string","null"],"description":"Takedown defence. Display string (`\"1.34\"`, `\"42%\"`)."},"sub_avg":{"type":["string","null"],"description":"Submission attempts per 15 minutes. Display string (`\"1.34\"`, `\"42%\"`)."},"values":{"type":"object","description":"Numeric twins of the strings; percentages as 0–1.","properties":{"slpm":{"type":["number","null"],"description":"Significant strikes landed per minute. Percentages as a 0–1 fraction."},"str_acc":{"type":["number","null"],"description":"Significant-strike accuracy. Percentages as a 0–1 fraction."},"sapm":{"type":["number","null"],"description":"Significant strikes absorbed per minute. Percentages as a 0–1 fraction."},"str_def":{"type":["number","null"],"description":"Significant-strike defence. Percentages as a 0–1 fraction."},"td_avg":{"type":["number","null"],"description":"Takedowns landed per 15 minutes. Percentages as a 0–1 fraction."},"td_acc":{"type":["number","null"],"description":"Takedown accuracy. Percentages as a 0–1 fraction."},"td_def":{"type":["number","null"],"description":"Takedown defence. Percentages as a 0–1 fraction."},"sub_avg":{"type":["number","null"],"description":"Submission attempts per 15 minutes. Percentages as a 0–1 fraction."}},"required":["slpm","str_acc","sapm","str_def","td_avg","td_acc","td_def","sub_avg"],"additionalProperties":false},"basis":{"$ref":"#/components/schemas/StatsBasis"}},"required":["slpm","str_acc","sapm","str_def","td_avg","td_acc","td_def","sub_avg","values","basis"],"additionalProperties":false},"CareerStatRow":{"type":"object","description":"Raw per-source career row, exactly one per scope.","properties":{"scope":{"type":"string","description":"`pro-mma`, `amateur-mma`, `pro-kickboxing`, …, or `ufc-only` / `bkfc-only` / `one-only`."},"source":{"type":"string","description":"Who published the record: `ufc-stats` (ufcstats.com), a promotion's own site (`ufc-official`, `bkfc-official`, `one-official`, `oktagon-official`, …), `ufcalendar` (derived by UFCalendar), or `public-records` (the complete multi-promotion career record compiled from public records)."},"record":{"type":["string","null"]},"slpm":{"type":["string","null"],"description":"Significant strikes landed per minute. Display string (`\"1.34\"`, `\"42%\"`)."},"str_acc":{"type":["string","null"],"description":"Significant-strike accuracy. Display string (`\"1.34\"`, `\"42%\"`)."},"sapm":{"type":["string","null"],"description":"Significant strikes absorbed per minute. Display string (`\"1.34\"`, `\"42%\"`)."},"str_def":{"type":["string","null"],"description":"Significant-strike defence. Display string (`\"1.34\"`, `\"42%\"`)."},"td_avg":{"type":["string","null"],"description":"Takedowns landed per 15 minutes. Display string (`\"1.34\"`, `\"42%\"`)."},"td_acc":{"type":["string","null"],"description":"Takedown accuracy. Display string (`\"1.34\"`, `\"42%\"`)."},"td_def":{"type":["string","null"],"description":"Takedown defence. Display string (`\"1.34\"`, `\"42%\"`)."},"sub_avg":{"type":["string","null"],"description":"Submission attempts per 15 minutes. Display string (`\"1.34\"`, `\"42%\"`)."},"updated_at":{"type":["string","null"],"format":"date-time","description":"Present on `GET /v1/fighters/{idOrSlug}/stats` rows and `/v1/compare` `career_stats` only."}},"required":["scope","source","record","slpm","str_acc","sapm","str_def","td_avg","td_acc","td_def","sub_avg"],"additionalProperties":false},"NativeBout":{"type":"object","description":"A tracked bout from the fighter's side — the `source: \"native\"` row shape of `/history` (`next_fight` / `last_fight`).","properties":{"fight_id":{"type":"integer"},"event_id":{"type":"integer"},"event_title":{"type":"string"},"event_slug":{"type":"string"},"org_slug":{"type":"string"},"date":{"type":["string","null"],"format":"date"},"opponent_id":{"type":["integer","null"]},"opponent_name":{"type":["string","null"]},"opponent_slug":{"type":["string","null"]},"result":{"type":["string","null"],"enum":["win","loss","draw","nc",null],"description":"Always null on `next_fight`."},"method":{"type":["string","null"]},"round":{"type":["integer","null"]},"time":{"type":["string","null"]},"weight_class":{"type":["string","null"]},"is_title":{"type":"boolean"},"sport":{"$ref":"#/components/schemas/Sport"},"source":{"type":"string","const":"native"}},"required":["fight_id","event_id","event_title","event_slug","org_slug","date","opponent_id","opponent_name","opponent_slug","result","method","round","time","weight_class","is_title","sport","source"],"additionalProperties":false},"BonusAward":{"type":"string","enum":["fotn","potn","kotn","sotn"],"description":"Fight / Performance / KO / Submission of the Night."},"BonusLedger":{"type":"object","description":"The UFC post-fight bonus ledger (`?include=bonuses`). Award counts only, no dollar amounts.","properties":{"org":{"type":"string","const":"ufc"},"total":{"type":"integer"},"counts":{"type":"object","properties":{"fotn":{"type":"integer"},"potn":{"type":"integer"},"kotn":{"type":"integer"},"sotn":{"type":"integer"}},"required":["fotn","potn","kotn","sotn"],"additionalProperties":false},"fights":{"type":"array","items":{"type":"object","properties":{"fight_id":{"type":"integer"},"event_slug":{"type":"string"},"date":{"type":["string","null"],"format":"date"},"awards":{"type":"array","items":{"$ref":"#/components/schemas/BonusAward"}}},"required":["fight_id","event_slug","date","awards"],"additionalProperties":false},"description":"Newest first. Fight of the Night is credited to both corners, the rest to the winner only."}},"required":["org","total","counts","fights"],"additionalProperties":false},"CredentialConfidence":{"type":"string","enum":["confirmed","reported"],"description":"`confirmed` = an official body or 2+ independent sources; `reported` = one credible outlet. Unverified claims are never served."},"Credential":{"type":"object","properties":{"kind":{"type":"string","description":"`belt-rank`, `competition-result`, `professional-title`, `national-team`, `base-style`, `training-started`, `athletic-education`, `sports-club`, `award`, `sport-rank`, `record`."},"discipline":{"type":["string","null"]},"competition":{"type":["string","null"]},"placement":{"type":["string","null"]},"rank":{"type":["string","null"]},"year":{"type":["integer","null"]},"detail":{"description":"Kind-specific extras (free JSON), or null."},"note":{"type":["string","null"]},"sources":{"type":"array","items":{"type":"string"},"description":"Public reference URLs behind the claim (Wikipedia, the promotion's own pages, official bodies). May be empty: every served row was sourced and confidence-graded by UFCalendar, but only public references are listed."},"confidence":{"$ref":"#/components/schemas/CredentialConfidence"}},"required":["kind","discipline","competition","placement","rank","year","detail","note","sources","confidence"],"additionalProperties":false},"Affiliation":{"type":"object","properties":{"kind":{"type":"string","description":"`gym`, `coach`, `training-partner`, `manager`."},"name":{"type":"string"},"role":{"type":["string","null"]},"status":{"type":["string","null"],"description":"`current` / `former`."},"is_primary":{"type":"boolean"},"location":{"type":["string","null"]},"gym":{"type":["string","null"]},"discipline":{"type":["string","null"]},"relationship":{"type":["string","null"]},"as_of":{"type":["string","null"]},"period":{"type":["string","null"]},"note":{"type":["string","null"]},"sources":{"type":"array","items":{"type":"string"},"description":"Public reference URLs behind the claim; may be empty (see `Credential.sources`)."},"confidence":{"$ref":"#/components/schemas/CredentialConfidence"}},"required":["kind","name","role","status","is_primary","location","gym","discipline","relationship","as_of","period","note","sources","confidence"],"additionalProperties":false},"FighterCredentials":{"type":"object","description":"Combat-sports background researched by UFCalendar (`?include=credentials`). Both lists may be empty.","properties":{"credentials":{"type":"array","items":{"$ref":"#/components/schemas/Credential"}},"affiliations":{"type":"array","items":{"$ref":"#/components/schemas/Affiliation"}}},"required":["credentials","affiliations"],"additionalProperties":false},"PowerIndexSummary":{"type":"object","properties":{"rating":{"type":"number"},"peak":{"type":"number"},"peak_at":{"type":["string","null"],"format":"date-time"},"peak_date":{"type":["string","null"],"format":"date","description":"`peak_at` as YYYY-MM-DD (the board endpoint speaks dates)."},"fights_rated":{"type":"integer"},"last_fought_at":{"type":["string","null"],"format":"date-time"},"last_fought_date":{"type":["string","null"],"format":"date"}},"required":["rating","peak","peak_at","peak_date","fights_rated","last_fought_at","last_fought_date"],"additionalProperties":false},"FighterImage":{"type":"object","properties":{"url":{"type":"string"},"width":{"type":["integer","null"]},"height":{"type":["integer","null"]},"license":{"type":["string","null"],"description":"Short licence name (`CC BY-SA 4.0`, `Public domain`). Displaying it with `artist` is a licence requirement."},"license_url":{"type":["string","null"]},"artist":{"type":["string","null"]},"source_page":{"type":["string","null"],"description":"Wikimedia Commons file page."}},"required":["url","width","height","license","license_url","artist","source_page"],"additionalProperties":false},"Fighter":{"type":"object","description":"`bonuses` / `credentials` are present only when asked for with `?include=`.","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nickname":{"type":["string","null"]},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it (e.g. `United States`)."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`; null when the name is unknown to our table."},"second_nationality":{"type":["string","null"]},"height_inches":{"type":["number","null"]},"weight_lbs":{"type":["number","null"]},"reach_inches":{"type":["number","null"]},"stance":{"type":["string","null"]},"dob":{"type":["string","null"],"format":"date"},"team":{"type":["string","null"]},"birthplace":{"type":["string","null"]},"records":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/RecordEntry"},"description":"Keyed `pro_mma`, `amateur_mma`, `pro_kickboxing`, … and the org slug (`ufc`, `one`, `bkfc`) for in-promotion records."},"stats":{"oneOf":[{"$ref":"#/components/schemas/StatsPanel"},{"type":"null"}]},"career_stats":{"type":"array","items":{"$ref":"#/components/schemas/CareerStatRow"}},"power_index":{"oneOf":[{"$ref":"#/components/schemas/PowerIndexSummary"},{"type":"null"}]},"images":{"type":"array","items":{"$ref":"#/components/schemas/FighterImage"},"description":"Wikimedia Commons / CC images only. Credit is mandatory."},"next_fight":{"oneOf":[{"$ref":"#/components/schemas/NativeBout"},{"type":"null"}]},"last_fight":{"oneOf":[{"$ref":"#/components/schemas/NativeBout"},{"type":"null"}]},"bonuses":{"$ref":"#/components/schemas/BonusLedger"},"credentials":{"$ref":"#/components/schemas/FighterCredentials"}},"required":["id","slug","name","nickname","nationality","country_code","second_nationality","height_inches","weight_lbs","reach_inches","stance","dob","team","birthplace","records","stats","career_stats","power_index","images","next_fight","last_fight"],"additionalProperties":false},"CompareFighter":{"type":"object","description":"The bio half of a fighter profile plus `age` (`/v1/compare`).","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nickname":{"type":["string","null"]},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it (e.g. `United States`)."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`; null when the name is unknown to our table."},"second_nationality":{"type":["string","null"]},"height_inches":{"type":["number","null"]},"weight_lbs":{"type":["number","null"]},"reach_inches":{"type":["number","null"]},"stance":{"type":["string","null"]},"dob":{"type":["string","null"],"format":"date"},"team":{"type":["string","null"]},"birthplace":{"type":["string","null"]},"age":{"type":["integer","null"],"description":"Whole years from `dob`; null when unknown."}},"required":["id","slug","name","nickname","nationality","country_code","second_nationality","height_inches","weight_lbs","reach_inches","stance","dob","team","birthplace","age"],"additionalProperties":false},"CompareAggregates":{"type":"object","properties":{"fights_analyzed":{"type":"integer","description":"Completed bouts with per-fight totals; 0 ⇒ every other field is null."},"avg_sig_strikes":{"type":["number","null"]},"avg_takedowns":{"type":["number","null"]},"avg_control_time_sec":{"type":["integer","null"]},"max_sig_strikes":{"type":["integer","null"]},"max_takedowns":{"type":["integer","null"]},"location_pct":{"oneOf":[{"type":"object","properties":{"head":{"type":"integer"},"body":{"type":"integer"},"leg":{"type":"integer"}},"required":["head","body","leg"],"additionalProperties":false},{"type":"null"}],"description":"Significant-strike target mix, whole percents."},"position_pct":{"oneOf":[{"type":"object","properties":{"distance":{"type":"integer"},"clinch":{"type":"integer"},"ground":{"type":"integer"}},"required":["distance","clinch","ground"],"additionalProperties":false},{"type":"null"}],"description":"Significant-strike position mix, whole percents."}},"required":["fights_analyzed","avg_sig_strikes","avg_takedowns","avg_control_time_sec","max_sig_strikes","max_takedowns","location_pct","position_pct"],"additionalProperties":false},"CompletedFightRef":{"type":"object","description":"One completed bout from one fighter's side (`head_to_head`, `common_opponents`).","properties":{"fight_id":{"type":"integer"},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"starts_at":{"type":"string","format":"date-time"}},"required":["id","slug","title","starts_at"],"additionalProperties":false},"weight_class":{"type":["string","null"]},"is_title":{"type":"boolean"},"is_main":{"type":"boolean"},"opponent":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}]},"outcome":{"type":"string","enum":["win","loss","draw","nc"],"description":"From THIS fighter's side."},"winner_fighter_id":{"type":["integer","null"]},"method":{"type":["string","null"]},"round":{"type":["integer","null"]},"time":{"type":["string","null"]}},"required":["fight_id","event","weight_class","is_title","is_main","opponent","outcome","winner_fighter_id","method","round","time"],"additionalProperties":false},"ComparePowerIndex":{"type":"object","properties":{"rating":{"type":"integer","description":"Rounded."},"peak":{"type":"integer","description":"Rounded."},"peak_at":{"type":["string","null"],"format":"date"},"fights_rated":{"type":"integer"},"last_fought_at":{"type":["string","null"],"format":"date"}},"required":["rating","peak","peak_at","fights_rated","last_fought_at"],"additionalProperties":false},"Compare":{"type":"object","properties":{"a":{"$ref":"#/components/schemas/CompareFighter"},"b":{"$ref":"#/components/schemas/CompareFighter"},"career_stats":{"type":"object","properties":{"a":{"type":"array","items":{"$ref":"#/components/schemas/CareerStatRow"}},"b":{"type":"array","items":{"$ref":"#/components/schemas/CareerStatRow"}}},"required":["a","b"],"additionalProperties":false},"aggregates":{"type":"object","properties":{"a":{"$ref":"#/components/schemas/CompareAggregates"},"b":{"$ref":"#/components/schemas/CompareAggregates"}},"required":["a","b"],"additionalProperties":false},"recent_form":{"type":"object","description":"The last five SETTLED entries of each merged timeline.","properties":{"a":{"type":"array","items":{"$ref":"#/components/schemas/HistoryEntry"}},"b":{"type":"array","items":{"$ref":"#/components/schemas/HistoryEntry"}}},"required":["a","b"],"additionalProperties":false},"win_streak":{"type":"object","properties":{"a":{"type":"integer"},"b":{"type":"integer"}},"required":["a","b"],"additionalProperties":false},"head_to_head":{"type":"array","items":{"$ref":"#/components/schemas/CompletedFightRef"},"description":"Previous meetings, from `a`'s side."},"common_opponents":{"type":"array","items":{"type":"object","properties":{"opponent":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},"a_fight":{"$ref":"#/components/schemas/CompletedFightRef"},"b_fight":{"$ref":"#/components/schemas/CompletedFightRef"}},"required":["opponent","a_fight","b_fight"],"additionalProperties":false},"description":"Up to 5."},"booked_bout":{"oneOf":[{"type":"object","properties":{"fight_id":{"type":"integer"},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"weight_class":{"type":["string","null"]},"is_title":{"type":"boolean"},"fighter_a_id":{"type":"integer","description":"Stored corner order — not necessarily `a`."},"fighter_b_id":{"type":"integer"}},"required":["fight_id","event","weight_class","is_title","fighter_a_id","fighter_b_id"],"additionalProperties":false},{"type":"null"}]},"prediction":{"oneOf":[{"type":"object","properties":{"win_probability_a":{"type":"number","description":"Oriented to compare's `a`."},"win_probability_b":{"type":"number"},"model_version":{"type":["string","null"]},"generated_at":{"type":["string","null"],"format":"date-time"}},"required":["win_probability_a","win_probability_b","model_version","generated_at"],"additionalProperties":false},{"type":"null"}],"description":"UFC only, and only while the stored corner stamp matches the booked bout."},"power_index":{"type":"object","properties":{"a":{"oneOf":[{"$ref":"#/components/schemas/ComparePowerIndex"},{"type":"null"}]},"b":{"oneOf":[{"$ref":"#/components/schemas/ComparePowerIndex"},{"type":"null"}]},"win_probability_a":{"type":["number","null"],"description":"From the two ratings; null when either is missing."}},"required":["a","b","win_probability_a"],"additionalProperties":false}},"required":["a","b","career_stats","aggregates","recent_form","win_streak","head_to_head","common_opponents","booked_bout","prediction","power_index"],"additionalProperties":false},"HistoryOpponent":{"type":"object","properties":{"id":{"type":["integer","null"]},"slug":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","slug","name"],"additionalProperties":false},"HistoryEntry":{"type":"object","description":"One career-timeline row. Every key is present on every row (null when unknown).","properties":{"source":{"type":"string","enum":["native","history"],"description":"`native` = a bout UFCalendar tracks (richest data); `history` = a career row from the wider multi-promotion record."},"fight_id":{"type":["integer","null"]},"event_id":{"type":["integer","null"]},"event_title":{"type":["string","null"]},"event_name":{"type":["string","null"],"description":"Same as `event_title`."},"event_slug":{"type":["string","null"]},"org_slug":{"type":["string","null"]},"date":{"type":["string","null"],"format":"date"},"opponent_id":{"type":["integer","null"]},"opponent_name":{"type":["string","null"]},"opponent_slug":{"type":["string","null"]},"opponent":{"oneOf":[{"$ref":"#/components/schemas/HistoryOpponent"},{"type":"null"}]},"result":{"type":["string","null"],"description":"Raw result (`win`, `loss`, `draw`, `nc`, `no_contest`, `cancelled`, …). Prefer `status`."},"status":{"$ref":"#/components/schemas/HistoryStatus"},"method":{"type":["string","null"]},"method_normalized":{"oneOf":[{"$ref":"#/components/schemas/MethodNormalized"},{"type":"null"}]},"round":{"type":["integer","null"]},"time":{"type":["string","null"]},"time_seconds":{"type":["integer","null"]},"weight_class":{"type":["string","null"]},"is_title":{"type":["boolean","null"]},"sport":{"type":["string","null"]},"competition_level":{"type":["string","null"],"description":"`pro`, `amateur`, … (native rows are `pro`)."},"source_slug":{"type":["string","null"],"description":"Who published the row: `ufcalendar` for native bouts; on history rows an official publisher's slug (`ufc-official`, `wikipedia`, a promotion's `*-official`), else `public-records`."}},"required":["source","fight_id","event_id","event_title","event_name","event_slug","org_slug","date","opponent_id","opponent_name","opponent_slug","opponent","result","status","method","method_normalized","round","time","time_seconds","weight_class","is_title","sport","competition_level","source_slug"],"additionalProperties":false},"FighterRankingRow":{"type":"object","properties":{"org":{"type":"string"},"board":{"$ref":"#/components/schemas/RankingsBoard"},"division":{"type":"string","description":"Division slug (`lightweight`, `womens-strawweight`, `mens-pound-for-pound`)."},"snapshot_date":{"type":"string","format":"date"},"rank":{"type":"integer","description":"0 = champion."},"is_champion":{"type":"boolean"}},"required":["org","board","division","snapshot_date","rank","is_champion"],"additionalProperties":false},"PowerIndexPoint":{"type":"object","properties":{"fought_at":{"type":"string","format":"date"},"rating_pre":{"type":"number"},"rating_post":{"type":"number"},"win_prob":{"type":["number","null"],"description":"Model win probability going in (0–1)."},"outcome":{"type":["number","null"],"description":"1 win, 0 loss, 0.5 draw."},"result":{"type":["string","null"],"enum":["win","loss","draw",null],"description":"Word twin of `outcome`."},"opponent_fighter_id":{"type":["integer","null"]},"fight_id":{"type":["integer","null"]}},"required":["fought_at","rating_pre","rating_post","win_prob","outcome","result","opponent_fighter_id","fight_id"],"additionalProperties":false},"RankedFighterRef":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"RankingEntry":{"type":"object","description":"One board row with movement against the previous snapshot.","properties":{"rank":{"type":"integer","description":"0 = champion."},"is_champion":{"type":"boolean"},"fighter_id":{"type":["integer","null"]},"fighter_slug":{"type":["string","null"]},"name":{"type":"string"},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`."},"fighter":{"oneOf":[{"$ref":"#/components/schemas/RankedFighterRef"},{"type":"null"}]},"movement":{"type":["integer","null"],"description":"Previous rank minus current rank: positive = moved up, 0 = held, null = not on the previous board (or no previous snapshot)."},"is_new":{"type":"boolean","description":"true when a previous snapshot exists and this fighter was not ranked in this division on it."}},"required":["rank","is_champion","fighter_id","fighter_slug","name","nationality","country_code","fighter","movement","is_new"],"additionalProperties":false},"RankingsDivision":{"type":"object","properties":{"division":{"type":"string","description":"Division slug."},"entries":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}}},"required":["division","entries"],"additionalProperties":false},"RankingsBoardSnapshot":{"type":"object","properties":{"org":{"type":"string"},"board":{"$ref":"#/components/schemas/RankingsBoard"},"snapshot_date":{"type":"string","format":"date","description":"The snapshot in force on the requested date."},"divisions":{"type":"array","items":{"$ref":"#/components/schemas/RankingsDivision"}}},"required":["org","board","snapshot_date","divisions"],"additionalProperties":false},"DivisionRankings":{"type":"object","properties":{"org":{"type":"string"},"board":{"$ref":"#/components/schemas/RankingsBoard"},"snapshot_date":{"type":"string","format":"date"},"division":{"type":"string"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}}},"required":["org","board","snapshot_date","division","entries"],"additionalProperties":false},"Champion":{"type":"object","description":"A rank-0 row of the latest board (no `movement` / `is_new` — the neighbour snapshot is not read here).","properties":{"org":{"type":"string"},"division":{"type":"string"},"snapshot_date":{"type":"string","format":"date"},"rank":{"type":"integer","description":"0 = champion."},"is_champion":{"type":"boolean"},"fighter_id":{"type":["integer","null"]},"fighter_slug":{"type":["string","null"]},"name":{"type":"string"},"nationality":{"type":["string","null"],"description":"Country NAME as the source spells it."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 derived from `nationality`."},"fighter":{"oneOf":[{"$ref":"#/components/schemas/RankedFighterRef"},{"type":"null"}]}},"required":["org","division","snapshot_date","rank","is_champion","fighter_id","fighter_slug","name","nationality","country_code","fighter"],"additionalProperties":false},"PowerIndexView":{"type":"string","enum":["current","movers","peaks"],"description":"Which board view a row belongs to."},"PowerIndexBoardRow":{"type":"object","description":"`view=current` / `view=peaks` row.","properties":{"position":{"type":"integer"},"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nationality":{"type":["string","null"]},"country_code":{"type":["string","null"]}},"required":["id","slug","name","nationality","country_code"],"additionalProperties":false},"rating":{"type":"integer","description":"Rounded."},"peak":{"type":"integer","description":"Rounded."},"peak_at":{"type":["string","null"],"format":"date"},"last_fought_at":{"type":["string","null"],"format":"date"},"fights_rated":{"type":"integer"},"division":{"type":["string","null"],"description":"Division slug from the fighter's latest bout; null for a catchweight."}},"required":["position","fighter","rating","peak","peak_at","last_fought_at","fights_rated","division"],"additionalProperties":false},"PowerIndexMoverRow":{"type":"object","description":"`view=movers` row.","properties":{"position":{"type":"integer"},"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nationality":{"type":["string","null"]},"country_code":{"type":["string","null"],"description":"ISO-2 derived from `nationality`."}},"required":["id","slug","name","nationality","country_code"],"additionalProperties":false},"rating":{"type":"integer","description":"Rating at the end of the window, rounded."},"start_rating":{"type":"integer","description":"Rating going into the window, rounded."},"delta":{"type":"integer","description":"`rating` − `start_rating`."},"fights_in_window":{"type":"integer"},"division":{"type":["string","null"]}},"required":["position","fighter","rating","start_rating","delta","fights_in_window","division"],"additionalProperties":false},"Division":{"type":"object","description":"One weight class in one promotion.","properties":{"org":{"type":"string"},"division":{"type":"object","properties":{"slug":{"type":"string","enum":["strawweight","flyweight","bantamweight","featherweight","lightweight","welterweight","super-welterweight","middleweight","light-heavyweight","heavyweight","super-heavyweight","womens-strawweight","womens-flyweight","womens-bantamweight","womens-featherweight","atomweight","ironweight"],"description":"API division slug."},"name":{"type":"string","description":"Canonical weight-class name."},"weight_limit_lbs":{"type":["integer","null"],"description":"Null where no standard limit applies."}},"required":["slug","name","weight_limit_lbs"],"additionalProperties":false},"rankings":{"oneOf":[{"$ref":"#/components/schemas/DivisionRankings"},{"type":"null"}]},"upcoming":{"type":"array","items":{"$ref":"#/components/schemas/FightDetail"},"description":"Up to 50 bouts booked at this weight, soonest first."},"recent":{"type":"array","items":{"$ref":"#/components/schemas/FightDetail"},"description":"The 15 latest completed or no-contest bouts, newest first."},"roster":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nickname":{"type":["string","null"]},"nationality":{"type":["string","null"]},"country_code":{"type":["string","null"],"description":"ISO-2 derived from `nationality`."},"last_fought_at":{"type":["string","null"],"format":"date-time","description":"Start of their latest bout at this weight (never a future booking)."}},"required":["id","slug","name","nickname","nationality","country_code","last_fought_at"],"additionalProperties":false},"description":"Up to 30 fighters who have fought at this weight, most recent first."}},"required":["org","division","rankings","upcoming","recent","roster"],"additionalProperties":false},"MatchmakerCorner":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nationality":{"type":["string","null"]},"rank":{"type":["integer","null"],"description":"Official rank: 0 = champion, null = unranked."},"power_index":{"type":["integer","null"],"description":"Rounded Power Index rating; null when unrated."},"streak":{"type":"integer","description":"Signed: +3 = three straight wins, -2 = two straight losses."},"booked":{"type":"boolean","description":"Already booked against someone else on an upcoming card."}},"required":["id","slug","name","nationality","rank","power_index","streak","booked"],"additionalProperties":false},"MatchmakerTag":{"type":"object","properties":{"kind":{"type":"string","enum":["title","eliminator","coinFlip","bothStreaking","finishers","trilogyDecider","unfinishedBusiness","rematch","booked","unrankedGem","bounceBack","steppingUp","bothDue","styleClash"],"description":"Tag vocabulary; `styleClash` never fires on the API (no Fight DNA)."},"a":{"type":"integer","description":"`bothStreaking`: corner a's streak."},"b":{"type":"integer","description":"`bothStreaking`: corner b's streak."},"pct":{"type":"integer","description":"`finishers`: average recent finish rate, whole percent."},"wins":{"type":"integer","description":"`trilogyDecider`: wins each."},"aWins":{"type":"integer","description":"`rematch`: a's wins in the series."},"bWins":{"type":"integer","description":"`rematch`: b's wins in the series."}},"required":["kind"],"additionalProperties":false},"Matchup":{"type":"object","properties":{"key":{"type":"string","description":"`lo-hi` fighter ids."},"division":{"type":"string"},"a":{"$ref":"#/components/schemas/MatchmakerCorner"},"b":{"$ref":"#/components/schemas/MatchmakerCorner"},"score":{"type":"number","description":"0–100."},"win_probability_a":{"type":"number","description":"From the two Power Index ratings."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/MatchmakerTag"}}},"required":["key","division","a","b","score","win_probability_a","tags"],"additionalProperties":false},"WhosNext":{"type":"object","properties":{"subject":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"nationality":{"type":["string","null"]},"rank":{"type":["integer","null"]},"power_index":{"type":["integer","null"]},"streak":{"type":"integer"},"booked":{"type":"boolean"},"days_since_last":{"type":["integer","null"],"description":"Days since their last rated bout; null when unrated."}},"required":["id","slug","name","nationality","rank","power_index","streak","booked","days_since_last"],"additionalProperties":false},"org":{"type":"string"},"division":{"type":"string"},"suggestions":{"type":"array","items":{"type":"object","properties":{"opponent":{"$ref":"#/components/schemas/MatchmakerCorner"},"win_probability_subject":{"type":"number"},"score":{"type":"number","description":"0–100."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/MatchmakerTag"}}},"required":["opponent","win_probability_subject","score","tags"],"additionalProperties":false},"description":"Best first."},"booked_next":{"oneOf":[{"type":"object","properties":{"opponent":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false}},"required":["opponent","event"],"additionalProperties":false},{"type":"null"}],"description":"The bout already booked for the subject, or null."},"rankings_date":{"type":["string","null"],"format":"date","description":"The ladder snapshot used; null when the promotion has no current ladder."}},"required":["subject","org","division","suggestions","booked_next","rankings_date"],"additionalProperties":false},"MetricScope":{"type":"string","enum":["career","single_fight","round","division","event"],"description":"What a board row is: `career` = a fighter, `single_fight` / `round` = a performance, `event` = a card, `division` = a weight class."},"MetricCategory":{"type":"string","enum":["fights","time","striking","grappling","records"],"description":"Record Book category."},"MetricUnit":{"type":"string","enum":["count","seconds","minutes","rate","per_minute","per_15_minutes"],"description":"`rate` is a 0–1 fraction."},"Population":{"type":"string","enum":["all","active"],"description":"`active` = a bout in the last ~18 months."},"MetricMeta":{"type":"object","properties":{"slug":{"type":"string","enum":["total_fights","wins","decision_wins","title_fight_wins","bonuses","finishes","win_streak","total_fight_seconds","avg_fight_seconds_short","avg_fight_seconds_long","control_time_sec","control_time_pct","sig_strikes_landed","total_strikes_landed","slpm","sapm","striking_differential","sig_strike_accuracy","sig_strike_defense","knockdowns","knockdowns_per_15","knockouts","takedowns_landed","td_avg","takedown_accuracy","takedown_defense","submission_attempts","sub_avg_per_15","submissions","fastest_finish","fastest_knockout","fastest_submission","longest_fight_seconds","most_sig_strikes_fight","most_takedowns_fight","most_knockdowns_fight","longest_control_fight","most_sig_strikes_round","most_takedowns_round","most_knockdowns_round","most_finishes_event","most_knockouts_event","shortest_card_seconds","finish_rate","ko_rate","sub_rate","decision_rate","avg_fight_seconds"],"description":"Board metric slug."},"scope":{"$ref":"#/components/schemas/MetricScope"},"category":{"$ref":"#/components/schemas/MetricCategory"},"direction":{"type":"string","enum":["asc","desc"],"description":"Ranking order, not a verdict."},"unit":{"$ref":"#/components/schemas/MetricUnit"},"has_secondary":{"type":"boolean"},"secondary":{"oneOf":[{"type":"object","properties":{"unit":{"$ref":"#/components/schemas/MetricUnit"},"label":{"type":"string","description":"snake_case name of what `value_secondary` holds (`attempted`, `round`, `fights`, …)."}},"required":["unit","label"],"additionalProperties":false},{"type":"null"}]}},"required":["slug","scope","category","direction","unit","has_secondary","secondary"],"additionalProperties":false},"LeaderboardRow":{"type":"object","properties":{"rank":{"type":"integer","description":"The rollup's own position."},"value":{"type":"number","description":"In `meta.metric.unit`."},"value_secondary":{"type":["number","null"],"description":"Denominator or context named by `meta.metric.secondary`."},"sample_n":{"type":"integer","description":"Bouts (or fighters) behind the value."},"fighter":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":["string","null"]},"nationality":{"type":["string","null"]}},"required":["id","slug","name","nationality"],"additionalProperties":false},{"type":"null"}],"description":"Null on `event` and `division` boards."},"division":{"type":["string","null"],"description":"Set on `division` boards and on any board narrowed with `division=`."},"round_number":{"type":["integer","null"],"description":"`round` boards only."},"fight":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"event":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"title":{"type":["string","null"]},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","starts_at"],"additionalProperties":false},{"type":"null"}]},"opponent":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]}},"required":["id","event","opponent"],"additionalProperties":false},{"type":"null"}],"description":"`single_fight` / `round` boards: the performance's bout."},"event":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"title":{"type":["string","null"]},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","starts_at"],"additionalProperties":false},{"type":"null"}],"description":"`event` boards: the card."},"display_rank":{"type":"integer","description":"First rank of the tie group."},"tied":{"type":"boolean"}},"required":["rank","value","value_secondary","sample_n","fighter","division","round_number","fight","event","display_rank","tied"],"additionalProperties":false},"RecordBookSection":{"type":"object","properties":{"category":{"$ref":"#/components/schemas/MetricCategory"},"boards":{"type":"array","items":{"type":"object","properties":{"metric":{"$ref":"#/components/schemas/MetricMeta"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardRow"}}},"required":["metric","rows"],"additionalProperties":false}}},"required":["category","boards"],"additionalProperties":false},"YearStats":{"type":"object","properties":{"year":{"type":"integer"},"orgs_scope":{"type":"array","items":{"type":"string"},"description":"Promotions counted."},"events_completed":{"type":"integer"},"title_fights":{"type":"integer"},"methods":{"type":"object","properties":{"ko":{"type":"integer"},"sub":{"type":"integer"},"dec":{"type":"integer"},"other":{"type":"integer"},"total":{"type":"integer"}},"required":["ko","sub","dec","other","total"],"additionalProperties":false},"divisions":{"type":"array","items":{"type":"object","properties":{"weight_class":{"type":"string"},"fights":{"type":"integer"},"ko":{"type":"integer"},"sub":{"type":"integer"}},"required":["weight_class","fights","ko","sub"],"additionalProperties":false},"description":"Weight classes with 10+ bouts, highest finish rate first, up to 14."},"fastest_finishes":{"type":"array","items":{"type":"object","properties":{"fight_id":{"type":"integer"},"seconds":{"type":"integer"},"time":{"type":"string"},"method":{"type":["string","null"]},"event":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["slug","title","starts_at"],"additionalProperties":false},"winner":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},"loser":{"type":"object","properties":{"id":{"type":["integer","null"]},"name":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false}},"required":["fight_id","seconds","time","method","event","winner","loser"],"additionalProperties":false},"description":"Up to 8 round-1 KO/TKO/submissions."},"upsets":{"type":"array","items":{"type":"object","properties":{"fight_id":{"type":"integer"},"win_probability":{"type":"number","description":"The winner's pre-fight Power Index probability."},"winner":{"oneOf":[{"type":"object","description":"Fighter link on the year-in-review blocks (`name` is `\"\"` when unknown).","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}]},"opponent":{"oneOf":[{"type":"object","description":"Fighter link on the year-in-review blocks (`name` is `\"\"` when unknown).","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}]},"event":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["slug","title","starts_at"],"additionalProperties":false}},"required":["fight_id","win_probability","winner","opponent","event"],"additionalProperties":false},"description":"Up to 8."},"climbers":{"type":"array","items":{"type":"object","properties":{"fighter":{"oneOf":[{"type":"object","description":"Fighter link on the year-in-review blocks (`name` is `\"\"` when unknown).","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}]},"fights":{"type":"integer"},"gain":{"type":"integer","description":"Power Index points gained over the year."}},"required":["fighter","fights","gain"],"additionalProperties":false},"description":"Up to 8."},"busiest":{"type":"array","items":{"type":"object","properties":{"fighter":{"oneOf":[{"type":"object","description":"Fighter link on the year-in-review blocks (`name` is `\"\"` when unknown).","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}]},"fights":{"type":"integer"},"wins":{"type":"integer"}},"required":["fighter","fights","wins"],"additionalProperties":false},"description":"Up to 8."},"orgs":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer"},"fights":{"type":"integer"}},"required":["slug","name","events","fights"],"additionalProperties":false}},"countries":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"events":{"type":"integer"}},"required":["country","events"],"additionalProperties":false},"description":"Host countries by events, up to 12."},"judges":{"type":"array","items":{"type":"object","properties":{"judge_id":{"type":"integer"},"name":{"type":"string"},"fights":{"type":"integer"}},"required":["judge_id","name","fights"],"additionalProperties":false},"description":"The 5 judges on the most commission-scored bouts."}},"required":["year","orgs_scope","events_completed","title_fights","methods","divisions","fastest_finishes","upsets","climbers","busiest","orgs","countries","judges"],"additionalProperties":false},"RightsSeries":{"type":"string","enum":["dwcs","rtufc"],"description":"UFC sub-series with their own rights grid: Dana White's Contender Series, Road to UFC."},"WatchProvider":{"type":"object","properties":{"provider":{"type":"string"},"kind":{"$ref":"#/components/schemas/BroadcastKind"},"url":{"type":["string","null"],"description":"Raw link, no affiliate wrapping."},"note_key":{"type":["string","null"],"description":"Short machine key for a caveat (e.g. `mainCardPpv`); null when none."},"event_confirmed":{"type":"boolean","description":"true = the event's own listing names this provider."},"rank":{"type":"integer","description":"Lower = primary; -1 for an event-confirmed row."}},"required":["provider","kind","url","note_key","event_confirmed","rank"],"additionalProperties":false},"WatchCountry":{"type":"object","properties":{"country":{"type":"string","description":"ISO-2 or `WORLD`."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/WatchProvider"}}},"required":["country","providers"],"additionalProperties":false},"EventWatch":{"type":"object","properties":{"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"main_card_at":{"type":["string","null"],"format":"date-time"},"prelims_at":{"type":["string","null"],"format":"date-time"},"early_prelims_at":{"type":["string","null"],"format":"date-time"},"tz":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/EventStatus"},"is_ppv":{"type":"boolean"}},"required":["id","slug","title","org","starts_at","main_card_at","prelims_at","early_prelims_at","tz","status","is_ppv"],"additionalProperties":false},"series":{"oneOf":[{"$ref":"#/components/schemas/RightsSeries"},{"type":"null"}]},"countries":{"type":"array","items":{"$ref":"#/components/schemas/WatchCountry"},"description":"`WORLD` first, then ISO order."}},"required":["event","series","countries"],"additionalProperties":false},"StorylineEvent":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/EventStatus"}},"required":["id","slug","title","org","starts_at","status"],"additionalProperties":false},"ProbabilitySource":{"type":"string","enum":["model","power_index"],"description":"`model` = UFCalendar model output (UFC bouts, corner-guarded); `power_index` = the Power Index curve."},"StorylineCorner":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"rank":{"type":["integer","null"],"description":"On the promotion's official board on the event date; 0 = champion, null = unranked."},"streak":{"type":"integer","description":"Signed: positive = consecutive wins, negative = consecutive losses."}},"required":["id","slug","name","rank","streak"],"additionalProperties":false},"StorylineTag":{"type":"object","properties":{"kind":{"type":"string","enum":["title","eliminator","coin_flip","both_streaking","finishers","trilogy_decider","rematch"],"description":"Tag vocabulary."},"a":{"type":"integer","description":"`both_streaking`."},"b":{"type":"integer","description":"`both_streaking`."},"pct":{"type":"integer","description":"`finishers`: whole percent."},"wins":{"type":"integer","description":"`trilogy_decider`: wins each."},"a_wins":{"type":"integer","description":"`rematch`."},"b_wins":{"type":"integer","description":"`rematch`."}},"required":["kind"],"additionalProperties":false},"StorylineFight":{"type":"object","properties":{"fight_id":{"type":"integer"},"ordering":{"type":["integer","null"]},"card_section":{"oneOf":[{"$ref":"#/components/schemas/CardSection"},{"type":"null"}]},"weight_class":{"type":["string","null"]},"is_title":{"type":"boolean"},"is_main":{"type":"boolean"},"fighter_a":{"$ref":"#/components/schemas/StorylineCorner"},"fighter_b":{"$ref":"#/components/schemas/StorylineCorner"},"win_probability_a":{"type":["number","null"]},"probability_source":{"oneOf":[{"$ref":"#/components/schemas/ProbabilitySource"},{"type":"null"}]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/StorylineTag"}}},"required":["fight_id","ordering","card_section","weight_class","is_title","is_main","fighter_a","fighter_b","win_probability_a","probability_source","tags"],"additionalProperties":false},"EventStorylines":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/StorylineEvent"},"summary":{"type":"object","properties":{"title_fights":{"type":"integer"},"ranked_fighters":{"type":"integer"},"champions":{"type":"integer"},"closest_bout":{"oneOf":[{"type":"object","properties":{"fight_id":{"type":"integer"},"win_probability_a":{"type":["number","null"]},"probability_source":{"oneOf":[{"$ref":"#/components/schemas/ProbabilitySource"},{"type":"null"}]}},"required":["fight_id","win_probability_a","probability_source"],"additionalProperties":false},{"type":"null"}]}},"required":["title_fights","ranked_fighters","champions","closest_bout"],"additionalProperties":false},"fights":{"type":"array","items":{"$ref":"#/components/schemas/StorylineFight"},"description":"Non-cancelled bouts in card order."},"card":{"type":"object","properties":{"avg_age":{"type":["number","null"],"description":"Needs 4+ known ages."},"tallest":{"oneOf":[{"type":"object","properties":{"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"height_inches":{"type":"number"}},"required":["fighter","height_inches"],"additionalProperties":false},{"type":"null"}]},"longest_reach":{"oneOf":[{"type":"object","properties":{"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"reach_inches":{"type":"number"}},"required":["fighter","reach_inches"],"additionalProperties":false},{"type":"null"}]},"nations":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"count":{"type":"integer"}},"required":["country","count"],"additionalProperties":false}},"streak_leaders":{"type":"array","items":{"type":"object","properties":{"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"streak":{"type":"integer"}},"required":["fighter","streak"],"additionalProperties":false},"description":"3+ wins, top 3."},"debuts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"description":"First bout in this promotion."},"returns":{"type":"array","items":{"type":"object","properties":{"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"months":{"type":"integer"}},"required":["fighter","months"],"additionalProperties":false},"description":"365+ days out, top 3."},"fastest_finish":{"oneOf":[{"type":"object","properties":{"fighter":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"time":{"type":"string","description":"`m:ss` into round 1."}},"required":["fighter","time"],"additionalProperties":false},{"type":"null"}]}},"required":["avg_age","tallest","longest_reach","nations","streak_leaders","debuts","returns","fastest_finish"],"additionalProperties":false}},"required":["event","summary","fights","card"],"additionalProperties":false},"PickemSplit":{"type":"object","properties":{"fight_id":{"type":"integer"},"fighter_a":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"fighter_b":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"picks_a":{"type":"integer"},"picks_b":{"type":"integer"},"total":{"type":"integer"},"pct_a":{"type":["number","null"],"description":"0–100 with one decimal; null when nobody has picked."}},"required":["fight_id","fighter_a","fighter_b","picks_a","picks_b","total","pct_a"],"additionalProperties":false},"EventPickem":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/StorylineEvent"},"fights":{"type":"array","items":{"$ref":"#/components/schemas/PickemSplit"},"description":"Non-cancelled bouts in card order."}},"required":["event","fights"],"additionalProperties":false},"OddsLine":{"type":"object","description":"One corner's side of a consensus point.","properties":{"american":{"type":"integer","description":"American moneyline (`-152`, `+131`)."},"decimal":{"type":"number","description":"Decimal odds, 3 places."},"implied_probability":{"type":"number","description":"Raw implied probability (market margin included), 4 places."}},"required":["american","decimal","implied_probability"],"additionalProperties":false},"OddsPair":{"type":"object","description":"One UFCalendar consensus point: the mean, in decimal space, across the sportsbooks we track, converted back to American. Information only, not betting advice.","properties":{"a":{"$ref":"#/components/schemas/OddsLine"},"b":{"$ref":"#/components/schemas/OddsLine"},"favourite":{"type":["string","null"],"enum":["a","b",null],"description":"The corner the market prices as more likely; null on an even pair."},"fair_probability_a":{"type":"number","description":"Probability of corner a with the market margin removed (pA / (pA + pB)), 4 places."},"sources":{"type":"integer","description":"How many sportsbooks backed this consensus point. Book identities are never exposed."},"recorded_at":{"type":"string","format":"date-time","description":"When this consensus point was recorded."}},"required":["a","b","favourite","fair_probability_a","sources","recorded_at"],"additionalProperties":false},"OddsMovement":{"type":"object","properties":{"delta_points_a":{"type":"number","description":"Implied-probability points on corner a, opening → consensus (2 places). Positive = the market moved toward a."},"direction":{"type":["string","null"],"enum":["a","b",null],"description":"Which corner the market moved toward; null when it did not move."},"since":{"type":"string","format":"date-time","description":"When the opening point was recorded."}},"required":["delta_points_a","direction","since"],"additionalProperties":false},"PropLine":{"type":"object","description":"One prop market's consensus price: the mean, in decimal space, across the sportsbooks we track, converted back to American.","properties":{"yes":{"$ref":"#/components/schemas/OddsLine"},"no":{"oneOf":[{"$ref":"#/components/schemas/OddsLine"},{"type":"null"}],"description":"Null when fewer than two sportsbooks quote the \"no\" side (method-of-victory props are mostly quoted \"yes\" only)."},"fair_probability":{"type":["number","null"],"description":"The \"yes\" outcome with the market margin removed, 4 places: from the yes/no pair, or for method of victory its share of all six outcomes (both corners × KO/TKO, submission, decision) when all six are priced. Null otherwise."},"sources":{"type":"integer","description":"How many sportsbooks backed this price. Book identities are never exposed."},"recorded_at":{"type":"string","format":"date-time","description":"When this price was recorded (the last move)."}},"required":["yes","no","fair_probability","sources","recorded_at"],"additionalProperties":false},"PropTotalRounds":{"type":"object","properties":{"line":{"type":"number","description":"Rounds line (0.5, 1.5, 2.5, 3.5 or 4.5)."},"over":{"$ref":"#/components/schemas/OddsLine"},"under":{"oneOf":[{"$ref":"#/components/schemas/OddsLine"},{"type":"null"}],"description":"Null when fewer than two sportsbooks quote the under."},"fair_probability_over":{"type":["number","null"],"description":"Over with the market margin removed (from the over/under pair), 4 places; null without an under."},"sources":{"type":"integer","description":"How many sportsbooks backed the over."},"recorded_at":{"type":"string","format":"date-time"}},"required":["line","over","under","fair_probability_over","sources","recorded_at"],"additionalProperties":false},"PropMethodCorner":{"type":"object","properties":{"ko":{"oneOf":[{"$ref":"#/components/schemas/PropLine"},{"type":"null"}],"description":"This corner wins by KO/TKO."},"sub":{"oneOf":[{"$ref":"#/components/schemas/PropLine"},{"type":"null"}],"description":"This corner wins by submission."},"dec":{"oneOf":[{"$ref":"#/components/schemas/PropLine"},{"type":"null"}],"description":"This corner wins by decision."}},"required":["ko","sub","dec"],"additionalProperties":false},"FightProps":{"type":"object","description":"Prop-market consensus for one bout. Prediction markets and exchanges are excluded and a book far from the rest is dropped; a market needs at least two sportsbooks. Prices are recorded until the event starts. Information only, not betting advice.","properties":{"method":{"type":"object","description":"Method of victory per corner (oriented to the bout's `fighter_a` / `fighter_b`).","properties":{"a":{"$ref":"#/components/schemas/PropMethodCorner"},"b":{"$ref":"#/components/schemas/PropMethodCorner"}},"required":["a","b"],"additionalProperties":false},"total_rounds":{"type":"array","items":{"$ref":"#/components/schemas/PropTotalRounds"},"description":"Over/under per rounds line, ascending. The line with the most `sources` is the main one."},"distance":{"oneOf":[{"$ref":"#/components/schemas/PropLine"},{"type":"null"}],"description":"The fight goes the distance (yes) or ends inside it (no)."},"closing":{"type":"boolean","description":"True once the bout is settled: every price is the last one before the event start."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When any market here last moved."}},"required":["method","total_rounds","distance","closing","updated_at"],"additionalProperties":false},"FightOdds":{"type":"object","description":"The consensus line of one bout: current, opening, closing (settled bouts) and the movement between opening and the current line (the close once settled), plus the prop markets.","properties":{"fight_id":{"type":"integer"},"status":{"oneOf":[{"$ref":"#/components/schemas/FightStatus"},{"type":"null"}]},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":["string","null"],"format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"fighter_a":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"fighter_b":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"consensus":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The current consensus line: the latest point while the bout is upcoming, the closing line once it is settled (a finished bout never reports a post-bell price). Null when the bout was never priced."},"opening":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The first consensus point we recorded."},"closing":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"Settled bouts only (`completed` / `no_contest`): the last point at or before the event start. Null until then."},"movement":{"oneOf":[{"$ref":"#/components/schemas/OddsMovement"},{"type":"null"}]},"points":{"type":"integer","description":"Stored consensus points (0 = never priced). The full series is `/v1/fights/{id}/odds/history` (Pro+)."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When the line last moved (= `consensus.recorded_at`)."},"props":{"oneOf":[{"$ref":"#/components/schemas/FightProps"},{"type":"null"}],"description":"Prop-market consensus (method of victory, total rounds, goes the distance); null when no sportsbooks price props for the bout."}},"required":["fight_id","status","event","fighter_a","fighter_b","consensus","opening","closing","movement","points","updated_at","props"],"additionalProperties":false},"EventOddsRow":{"type":"object","description":"One bout of a card with its consensus line and prop markets. Unpriced bouts stay on the list with nulls and `points: 0`.","properties":{"fight_id":{"type":"integer"},"status":{"oneOf":[{"$ref":"#/components/schemas/FightStatus"},{"type":"null"}]},"fighter_a":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"fighter_b":{"oneOf":[{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},{"type":"null"}]},"consensus":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The current consensus line: the latest point while the bout is upcoming, the closing line once it is settled (a finished bout never reports a post-bell price). Null when the bout was never priced."},"opening":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"The first consensus point we recorded."},"closing":{"oneOf":[{"$ref":"#/components/schemas/OddsPair"},{"type":"null"}],"description":"Settled bouts only (`completed` / `no_contest`): the last point at or before the event start. Null until then."},"movement":{"oneOf":[{"$ref":"#/components/schemas/OddsMovement"},{"type":"null"}]},"points":{"type":"integer","description":"Stored consensus points (0 = never priced). The full series is `/v1/fights/{id}/odds/history` (Pro+)."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When the line last moved (= `consensus.recorded_at`)."},"props":{"oneOf":[{"$ref":"#/components/schemas/FightProps"},{"type":"null"}],"description":"Prop-market consensus (method of victory, total rounds, goes the distance); null when no sportsbooks price props for the bout."}},"required":["fight_id","status","fighter_a","fighter_b","consensus","opening","closing","movement","points","updated_at","props"],"additionalProperties":false},"EventOdds":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/StorylineEvent"},"fights":{"type":"array","items":{"$ref":"#/components/schemas/EventOddsRow"},"description":"Non-cancelled bouts in card order."}},"required":["event","fights"],"additionalProperties":false},"OddsHistoryPoint":{"type":"object","description":"One stored consensus point. A point is stored only when the consensus changes.","properties":{"id":{"type":"integer","description":"Point id (the cursor unit)."},"a":{"$ref":"#/components/schemas/OddsLine"},"b":{"$ref":"#/components/schemas/OddsLine"},"favourite":{"type":["string","null"],"enum":["a","b",null],"description":"The corner the market prices as more likely; null on an even pair."},"fair_probability_a":{"type":"number","description":"Probability of corner a with the market margin removed (pA / (pA + pB)), 4 places."},"sources":{"type":"integer","description":"How many sportsbooks backed this consensus point. Book identities are never exposed."},"recorded_at":{"type":"string","format":"date-time","description":"When this consensus point was recorded."}},"required":["id","a","b","favourite","fair_probability_a","sources","recorded_at"],"additionalProperties":false},"ChangeFeedEntry":{"type":"object","description":"A per-event change entry plus its event (`/v1/changes`).","properties":{"id":{"type":"integer"},"kind":{"$ref":"#/components/schemas/ChangeKind"},"before":{"type":["object","null"],"additionalProperties":true},"after":{"type":["object","null"],"additionalProperties":true},"observed_at":{"type":"string","format":"date-time"},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":"string","format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false}},"required":["id","kind","before","after","observed_at","event"],"additionalProperties":false},"FightSearchMethod":{"type":"string","enum":["ko","sub","dec","finish","any"],"description":"`ko` = KO/TKO, `sub` = submission, `dec` = any decision, `finish` = KO/TKO or submission, `any` = no filter."},"FightSearchFilters":{"type":"object","description":"Echo of the filters applied.","properties":{"org":{"type":["string","null"]},"title_only":{"type":"boolean"},"method":{"$ref":"#/components/schemas/FightSearchMethod"},"division":{"type":["string","null"],"description":"The canonical name (slug input) or the fragment, as applied."},"fighter":{"type":["string","null"],"description":"As passed."},"winner":{"type":["string","null"],"description":"As passed."},"from":{"type":["string","null"],"format":"date"},"to":{"type":["string","null"],"format":"date"},"main_events_only":{"type":"boolean"}},"required":["org","title_only","method","division","fighter","winner","from","to","main_events_only"],"additionalProperties":false},"PredictedCorner":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"win_probability":{"type":"number","description":"0–1, rounded to 4 places."}},"required":["id","slug","name","win_probability"],"additionalProperties":false},"Prediction":{"type":"object","properties":{"fight_id":{"type":"integer"},"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":"string","format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"fighter_a":{"$ref":"#/components/schemas/PredictedCorner"},"fighter_b":{"$ref":"#/components/schemas/PredictedCorner"},"model_version":{"type":["string","null"]},"generated_at":{"type":["string","null"],"format":"date-time"}},"required":["fight_id","event","fighter_a","fighter_b","model_version","generated_at"],"additionalProperties":false},"BroadcastRight":{"type":"object","description":"`series` is null on org-wide rows; a sub-series grid replaces the org-wide one for those cards.","properties":{"country":{"type":"string","description":"ISO-2 or `WORLD`."},"provider":{"type":"string"},"kind":{"$ref":"#/components/schemas/BroadcastKind"},"url":{"type":["string","null"]},"rank":{"type":["integer","null"],"description":"Lower = primary."},"series":{"oneOf":[{"$ref":"#/components/schemas/RightsSeries"},{"type":"null"}]}},"required":["country","provider","kind","url","rank","series"],"additionalProperties":false},"Venue":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":"string"},"city":{"type":["string","null"]},"region":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"capacity":{"type":["integer","null"]},"tz":{"type":["string","null"]}},"required":["id","slug","name","city","region","country","country_code","lat","lng","capacity","tz"],"additionalProperties":false},"VenueListItem":{"type":"object","description":"Search-row venue (no coordinates, no `country_code` — those are on `GET /v1/venues/{id}`).","properties":{"id":{"type":"integer"},"slug":{"type":["string","null"]},"name":{"type":"string"},"city":{"type":["string","null"]},"region":{"type":["string","null"]},"country":{"type":["string","null"]},"tz":{"type":["string","null"]},"capacity":{"type":["integer","null"]}},"required":["id","slug","name","city","region","country","tz","capacity"],"additionalProperties":false},"SearchEvent":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"org":{"type":"string"},"starts_at":{"type":"string","format":"date-time"}},"required":["id","slug","title","org","starts_at"],"additionalProperties":false},"SearchResults":{"type":"object","properties":{"fighters":{"type":"array","items":{"$ref":"#/components/schemas/FighterRef"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/SearchEvent"}}},"required":["fighters","events"],"additionalProperties":false},"ArticleLocale":{"type":"string","enum":["en","es","pt","de","fr","tr","ru","ka","ja","ko","pl","sr","zh"],"description":"The 13 site languages."},"ArticleListItem":{"type":"object","description":"`locale` is the language actually served (English when no translation exists).","properties":{"slug":{"type":"string"},"url":{"type":"string","description":"The canonical page in the requested language."},"title":{"type":"string"},"description":{"type":"string"},"author_name":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"published_at":{"type":["string","null"],"format":"date-time"},"locale":{"$ref":"#/components/schemas/ArticleLocale"}},"required":["slug","url","title","description","author_name","tags","published_at","locale"],"additionalProperties":false},"Article":{"type":"object","properties":{"slug":{"type":"string"},"url":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"author_name":{"type":"string"},"author_slug":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"published_at":{"type":["string","null"],"format":"date-time"},"body_md":{"type":"string","description":"Markdown; client-only widgets and licensed embeds removed."},"locale":{"$ref":"#/components/schemas/ArticleLocale"},"served_locale":{"$ref":"#/components/schemas/ArticleLocale"}},"required":["slug","url","title","description","author_name","author_slug","tags","published_at","body_md","locale","served_locale"],"additionalProperties":false},"Usage":{"type":"object","properties":{"tier":{"$ref":"#/components/schemas/Tier"},"month":{"type":"string","description":"`YYYYMM` (legacy; see `period`)."},"requests_used":{"type":"integer"},"requests_limit":{"type":"integer"},"rpm_limit":{"type":"integer"},"reset":{"type":"integer","description":"Unix seconds of the next monthly reset (legacy; see `reset_at`)."},"period":{"type":"string","description":"`YYYY-MM`."},"reset_at":{"type":"string","format":"date-time"},"trial_ends_at":{"type":["string","null"],"format":"date-time","description":"Trial plans only: when the trial ends and access stops — usually well before `reset_at`. Null on a paid plan."}},"required":["tier","month","requests_used","requests_limit","rpm_limit","reset","period","reset_at","trial_ends_at"],"additionalProperties":false},"Plan":{"type":"object","properties":{"key":{"$ref":"#/components/schemas/Tier"},"name":{"type":"string"},"price_monthly_usd":{"type":"number"},"price_yearly_usd":{"type":"number"},"requests_per_month":{"type":"integer"},"rpm":{"type":"integer"},"key_limit":{"type":"integer"},"features":{"type":"array","items":{"type":"string"}},"checkout_url":{"type":["string","null"]}},"required":["key","name","price_monthly_usd","price_yearly_usd","requests_per_month","rpm","key_limit","features","checkout_url"],"additionalProperties":false},"Plans":{"type":"object","properties":{"currency":{"type":"string"},"plans":{"type":"array","items":{"$ref":"#/components/schemas/Plan"}},"trial":{"type":"object","properties":{"hours":{"type":"integer"},"requests":{"type":"integer"},"card_required":{"type":"boolean"},"per_account":{"type":"integer"},"start_url":{"type":"string"}},"required":["hours","requests","card_required","per_account","start_url"],"additionalProperties":false},"mcp":{"type":"object","properties":{"url":{"type":"string"},"transport":{"type":"string"},"auth":{"type":"array","items":{"type":"string"}},"oauth_metadata":{"type":"string"},"protected_resource_metadata":{"type":"string"}},"required":["url","transport","auth","oauth_metadata","protected_resource_metadata"],"additionalProperties":false},"links":{"type":"object","properties":{"docs":{"type":"string"},"openapi":{"type":"string"},"llms":{"type":"string"},"llms_full":{"type":"string"},"agents_page":{"type":"string"},"terms":{"type":"string"},"privacy":{"type":"string"}},"required":["docs","openapi","llms","llms_full","agents_page","terms","privacy"],"additionalProperties":false}},"required":["currency","plans","trial","mcp","links"],"additionalProperties":false},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookKind"}},"active":{"type":"boolean"},"failure_count":{"type":"integer","description":"Consecutive failures; 20 auto-disables the endpoint."},"created_at":{"type":"string","format":"date-time"}},"required":["id","url","events","active","failure_count","created_at"],"additionalProperties":false},"WebhookEndpointCreated":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookKind"}},"secret":{"type":"string","description":"`whsec_…` — shown ONCE. HMAC-SHA256 key for `X-UFCalendar-Signature`."}},"required":["id","url","events","secret"],"additionalProperties":false},"WebhookEndpointDeleted":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"WebhookDelivery":{"type":"object","description":"The JSON body of a webhook delivery (POSTed to your endpoint, signed).","properties":{"id":{"type":"string","description":"Delivery id (stable across retries — deduplicate on it)."},"type":{"$ref":"#/components/schemas/WebhookKind"},"data":{"type":"object","additionalProperties":true,"description":"`event.announced` / `event.completed`: `{event}` (the list-shape event); `fight.result`: the bout with `event`, `result`, `revision` and `corrected` — `revision` 1 is the first delivery; if the winner, method, round, time or status changes within 72 h of the result, the bout is re-sent as the next revision with `corrected: true` and the `previous` result it replaces (upsert on `fight_id`, keep the highest `revision`); `card.changed`: `{event, change}`; `odds.moved`: `{fight_id, event, fighter_a, fighter_b, odds: {consensus, opening, movement, updated_at}, previous, delta_points_a, direction, favourite_flipped, moved_at}` (UFCalendar consensus line, information only, not betting advice)."},"sent_at":{"type":"string","format":"date-time"}},"required":["id","type","data","sent_at"],"additionalProperties":false},"PlansResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Plans"},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["generated_at"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"OrgsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Org"}},"meta":{"type":"object","properties":{"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":[],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"OrgResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Org"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"DivisionResponse":{"type":"object","description":"`meta.note` is set only when every list is empty.","properties":{"data":{"$ref":"#/components/schemas/Division"},"meta":{"type":"object","properties":{"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":[],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventsPageResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EventDetail"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"EventChangesResponse":{"type":"object","description":"Newest first, at most 200 entries.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventChange"}},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"ChangesFeedResponse":{"type":"object","description":"Newest first across every launch promotion.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChangeFeedEntry"}},"meta":{"type":"object","properties":{"since":{"type":"string","format":"date-time","description":"The window start applied (default: 90 days ago)."},"kinds":{"type":"array","items":{"$ref":"#/components/schemas/ChangeKind"},"description":"The kinds included."},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["since","kinds","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventWatchResponse":{"type":"object","description":"`meta.note` is set on a sub-series card.","properties":{"data":{"$ref":"#/components/schemas/EventWatch"},"meta":{"type":"object","properties":{"country":{"type":["string","null"],"description":"The `country=` filter applied, upper-cased; null without one."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["country"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventStorylinesResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EventStorylines"},"meta":{"type":"object","properties":{"note":{"type":"string","description":"Always present — the model-output disclaimer (prefixed with \"No bouts on this card yet.\" on an empty card)."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventPickemResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EventPickem"},"meta":{"type":"object","properties":{"note":{"type":"string","description":"Always present — crowd sentiment, not a market."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightSearchResponse":{"type":"object","description":"`meta.note` explains an empty page or the 10-page depth cap.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FightDetail"}},"meta":{"type":"object","properties":{"order":{"type":"string","enum":["newest","oldest"]},"filters":{"$ref":"#/components/schemas/FightSearchFilters"},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["order","filters","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"SplitDecisionsResponse":{"type":"object","description":"Newest first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SplitDecision"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/CursorPagination"},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination","note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FightDetail"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"FightOddsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FightOdds"},"meta":{"type":"object","properties":{"note":{"type":"string","description":"Always present: consensus across the sportsbooks we track, information only, not betting advice."},"checked_at":{"type":["string","null"],"format":"date-time","description":"When we last checked the market (the last successful odds refresh), whether or not the line moved."},"history":{"type":"string","description":"Path of the movement series (Pro+)."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note","checked_at","history"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"EventOddsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EventOdds"},"meta":{"type":"object","properties":{"note":{"type":"string","description":"Always present: consensus across the sportsbooks we track, information only, not betting advice."},"checked_at":{"type":["string","null"],"format":"date-time","description":"When we last checked the market."},"priced":{"type":"integer","description":"Bouts on the list with a consensus line."},"unpriced":{"type":"integer","description":"Bouts on the list without one."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note","checked_at","priced","unpriced"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightOddsHistoryResponse":{"type":"object","description":"Oldest first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OddsHistoryPoint"}},"meta":{"type":"object","properties":{"fight_id":{"type":"integer"},"note":{"type":"string"},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["fight_id","note","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightStatsResponse":{"type":"object","description":"One line per corner (`corner` a then b). Empty when the source has no totals.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FightStatLine"}},"meta":{"type":"object","properties":{"fight_id":{"type":"integer"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["fight_id"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightRoundsResponse":{"type":"object","description":"Ordered by round, then corner.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RoundStatLine"}},"meta":{"type":"object","properties":{"fight_id":{"type":"integer"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["fight_id"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightScorecardsResponse":{"type":"object","description":"`cards` is empty (and `meta.note` explains) when no commission record exists; 404 only for an unknown fight.","properties":{"data":{"$ref":"#/components/schemas/Scorecards"},"meta":{"type":"object","properties":{"fight_id":{"type":"integer"},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["fight_id"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"JudgesPageResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Judge"}},"meta":{"type":"object","properties":{"total":{"type":"integer","description":"Judges matching the filters."},"league":{"$ref":"#/components/schemas/JudgeLeague"},"pagination":{"$ref":"#/components/schemas/Pagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["total","league","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"JudgeResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Judge"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"JudgeScorecardsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/JudgeScorecardEntry"}},"meta":{"type":"object","properties":{"judge":{"$ref":"#/components/schemas/Judge"},"pagination":{"$ref":"#/components/schemas/Pagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["judge","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FightersPageResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FighterListItem"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FighterResponse":{"type":"object","description":"`meta.note` is present only with `?include=credentials` (verify before republishing).","properties":{"data":{"$ref":"#/components/schemas/Fighter"},"meta":{"type":"object","properties":{"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":[],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"CompareResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Compare"},"meta":{"type":"object","properties":{"note":{"type":"string"},"resolved":{"type":"object","description":"Present when `a` or `b` was a retired slug that was followed.","properties":{"a":{"type":"object","properties":{"requested":{"type":"string"},"slug":{"type":"string"}},"required":["requested","slug"],"additionalProperties":false},"b":{"type":"object","properties":{"requested":{"type":"string"},"slug":{"type":"string"}},"required":["requested","slug"],"additionalProperties":false}},"required":[],"additionalProperties":false},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FighterHistoryResponse":{"type":"object","description":"Newest first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HistoryEntry"}},"meta":{"type":"object","properties":{"truncated":{"type":"boolean","description":"true when the history rows hit their 500-row cap."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["truncated"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FighterStatsResponse":{"type":"object","description":"Raw rows in `data`; the readable split rides in `meta`.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CareerStatRow"}},"meta":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/RecordEntry"}},"stats":{"oneOf":[{"$ref":"#/components/schemas/StatsPanel"},{"type":"null"}]},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["records","stats"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FighterRankingsResponse":{"type":"object","description":"Newest snapshot first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FighterRankingRow"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"FighterPowerIndexResponse":{"type":"object","description":"The newest 500 points, oldest first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PowerIndexPoint"}},"meta":{"type":"object","properties":{"truncated":{"type":"boolean","description":"true when the career exceeds 500 rated bouts (the OLDEST are dropped)."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["truncated"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"RankingsBoardResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RankingsBoardSnapshot"},"meta":{"type":"object","properties":{"previous_snapshot_date":{"type":["string","null"],"format":"date","description":"The snapshot before this one on the same board; null at the start of history."},"next_snapshot_date":{"type":["string","null"],"format":"date","description":"The snapshot after this one; null when this is the current board."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["previous_snapshot_date","next_snapshot_date"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"DivisionRankingsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DivisionRankings"},"meta":{"type":"object","properties":{"previous_snapshot_date":{"type":["string","null"],"format":"date","description":"The snapshot before this one on the same board; null at the start of history."},"next_snapshot_date":{"type":["string","null"],"format":"date","description":"The snapshot after this one; null when this is the current board."},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["previous_snapshot_date","next_snapshot_date"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"ChampionsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Champion"}},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"PowerIndexBoardResponse":{"type":"object","description":"Row shape follows `meta.view`: `current` / `peaks` rows carry peak fields, `movers` rows carry `start_rating` / `delta` / `fights_in_window`.","properties":{"data":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/PowerIndexBoardRow"},{"$ref":"#/components/schemas/PowerIndexMoverRow"}]}},"meta":{"type":"object","properties":{"org":{"type":"string"},"view":{"$ref":"#/components/schemas/PowerIndexView"},"division":{"type":["string","null"],"description":"The `division=` filter applied."},"days":{"type":"integer","description":"`view=movers` only: the window actually used (snapped to 30/90/180/365/730/1825/3650)."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","view","division","note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"MatchmakerBoardResponse":{"type":"object","description":"Best first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Matchup"}},"meta":{"type":"object","properties":{"org":{"type":"string"},"division":{"type":["string","null"],"description":"The `division=` filter applied."},"rankings_date":{"type":["string","null"],"format":"date","description":"The ladder snapshot used; null when the promotion has no current ladder."},"divisions":{"type":"array","items":{"type":"string"},"description":"The promotion's divisions (the `division=` vocabulary)."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","division","rankings_date","divisions","note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"WhosNextResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WhosNext"},"meta":{"type":"object","properties":{"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"LeaderboardResponse":{"type":"object","description":"Best first (`meta.metric.direction`). `meta.note` explains non-fighter rows.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardRow"}},"meta":{"type":"object","properties":{"org":{"type":"string"},"metric":{"$ref":"#/components/schemas/MetricMeta"},"division":{"type":["string","null"],"description":"API division slug as passed."},"population":{"$ref":"#/components/schemas/Population"},"country":{"type":["string","null"]},"computed_at":{"type":["string","null"],"format":"date-time","description":"When the rollup was built."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","metric","division","population","country","computed_at"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"RecordBookResponse":{"type":"object","description":"Grouped by category in registry order; `[]` with `meta.note` on an empty slice.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RecordBookSection"}},"meta":{"type":"object","properties":{"org":{"type":"string"},"division":{"type":["string","null"]},"population":{"$ref":"#/components/schemas/Population"},"country":{"type":["string","null"]},"scope":{"oneOf":[{"$ref":"#/components/schemas/MetricScope"},{"type":"null"}]},"top":{"type":"integer","description":"Rows per board."},"computed_at":{"type":["string","null"],"format":"date-time","description":"Null when the slice is empty."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","division","population","country","scope","top","computed_at","note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"YearStatsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/YearStats"},"meta":{"type":"object","properties":{"org":{"type":["string","null"],"description":"The `org=` filter, null for every covered promotion."},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"PredictionsResponse":{"type":"object","description":"`meta.event` names the card when `event=` was passed.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Prediction"}},"meta":{"type":"object","properties":{"event":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"title":{"type":"string"},"status":{"$ref":"#/components/schemas/EventStatus"}},"required":["id","slug","title","status"],"additionalProperties":false},"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":[],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"BroadcastRightsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BroadcastRight"}},"meta":{"type":"object","properties":{"org":{"type":"string"},"series":{"oneOf":[{"$ref":"#/components/schemas/RightsSeries"},{"type":"null"}]},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["org","series"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"VenuesPageResponse":{"type":"object","description":"Alphabetical by name.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VenueListItem"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/CursorPagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"VenueEventsResponse":{"type":"object","description":"Newest first unless `order=asc`.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"meta":{"type":"object","properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"venue":{"$ref":"#/components/schemas/VenueListItem"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["pagination","venue"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"VenueResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Venue"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"ArticlesPageResponse":{"type":"object","description":"Newest first.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ArticleListItem"}},"meta":{"type":"object","properties":{"locale":{"$ref":"#/components/schemas/ArticleLocale"},"note":{"type":"string"},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["locale","note","pagination"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"ArticleResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Article"},"meta":{"type":"object","properties":{"note":{"type":"string"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique."}},"required":["note"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"SearchResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchResults"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"UsageResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Usage"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"WebhookEndpointsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"WebhookEndpointCreatedResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpointCreated"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false},"WebhookEndpointDeletedResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpointDeleted"},"meta":{"$ref":"#/components/schemas/EmptyMeta"}},"required":["data","meta"],"additionalProperties":false}}},"tags":[{"name":"Orgs"},{"name":"Events"},{"name":"Fights"},{"name":"Fighters"},{"name":"Rankings"},{"name":"Scorecards"},{"name":"Odds","description":"The UFCalendar consensus line: one anonymised line per corner across the sportsbooks we track. Information only, not betting advice."},{"name":"Power Index"},{"name":"Matchmaker","description":"UFCalendar's matchmaker — the fights worth making, scored by our own engine. Not a list of bookings."},{"name":"Stats","description":"The Record Book (statistical leaderboards per promotion) and the year in review."},{"name":"Predictions"},{"name":"Broadcast"},{"name":"Search"},{"name":"Articles","description":"UFCalendar's own editorial archive — previews, recaps, investigations."},{"name":"Account"},{"name":"Discovery","description":"Open endpoints that need no credential."}],"paths":{"/v1/plans":{"get":{"tags":["Discovery"],"summary":"Plans, quotas and how to connect (no key required)","description":"The only endpoint that answers without a credential. Returns every plan with its monthly request quota, per-minute limit, key limit and a `checkout_url`; the terms of the free 1-day trial and the URL that starts it; the MCP endpoint with both of its auth doors; and the documentation links. Static per deploy and cached an hour — poll it never, read it once.","security":[],"parameters":[],"responses":{"200":{"description":"Plans, trial rule, MCP endpoint and links","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlansResponse"},"example":{"data":{"currency":"USD","plans":[{"key":"hobby","name":"Hobby","price_monthly_usd":19,"price_yearly_usd":190,"requests_per_month":30000,"rpm":60,"key_limit":5,"features":[],"checkout_url":"https://www.ufcalendar.com/account/api?plan=hobby"}],"trial":{"hours":24,"requests":100,"card_required":false,"per_account":1,"start_url":"https://www.ufcalendar.com/account/api?trial=1"},"mcp":{"url":"https://api.ufcalendar.com/mcp","transport":"streamable-http","auth":["bearer_api_key","oauth"],"oauth_metadata":"https://www.ufcalendar.com/.well-known/oauth-authorization-server","protected_resource_metadata":"https://api.ufcalendar.com/.well-known/oauth-protected-resource"},"links":{"docs":"https://api.ufcalendar.com/docs","openapi":"https://api.ufcalendar.com/openapi.json","llms":"https://api.ufcalendar.com/llms.txt","llms_full":"https://api.ufcalendar.com/llms-full.txt","agents_page":"https://www.ufcalendar.com/developers/agents","terms":"https://www.ufcalendar.com/developers/terms","privacy":"https://www.ufcalendar.com/privacy"}},"meta":{"generated_at":"2026-09-19T00:00:00.000Z"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/plans\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.plans()"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.plans();"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/orgs":{"get":{"tags":["Orgs"],"summary":"List launch orgs with capability flags","description":"Each org carries flags (`stats`, `rounds`, `rankings`, `broadcasts`, `predictions`, `scorecards`, `odds`) so clients discover coverage programmatically — plus `sport` (`mma`, `bare-knuckle-boxing`) and `country_code` (ISO-2). Staged orgs (ONE, KSW, ACA) appear the day they clear the reliability bar. RIZIN publishes no official board, so its `rankings` flag is false. `scorecards` is true for UFC, PFL, OKTAGON and RIZIN; no commission covers bare-knuckle, so BKFC is false.","parameters":[],"responses":{"200":{"description":"Launch orgs","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgsResponse"},"example":{"data":[{"id":1,"slug":"ufc","name":"Ultimate Fighting Championship","short_name":"UFC","country":"US","country_code":"US","website":"https://www.ufc.com","sport":"mma","capabilities":{"stats":true,"rounds":true,"rankings":true,"broadcasts":true,"predictions":true,"scorecards":true,"odds":true}}],"meta":{"note":"Staged orgs (ONE, KSW, ACA) appear here the day they clear the reliability bar."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/orgs\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.orgs()"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.orgs();"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_orgs\",\n    \"arguments\": {}\n  }\n}"}],"x-mcp-tool":"list_orgs","x-mcp-tools":["list_orgs"]}},"/v1/orgs/{slug}":{"get":{"tags":["Orgs"],"summary":"One org","description":"Single org by slug. Same shape as a list row.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Org","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/orgs/ufc\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.org(\"ufc\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.org(\"ufc\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_org\",\n    \"arguments\": {\n      \"org\": \"ufc\"\n    }\n  }\n}"}],"x-mcp-tool":"get_org","x-mcp-tools":["get_org"]}},"/v1/orgs/{slug}/divisions/{division}":{"get":{"tags":["Orgs"],"summary":"One division in one promotion","description":"One weight class in one promotion, in one call: `division` (`slug`, canonical `name`, `weight_limit_lbs` — `null` where no standard limit applies), `rankings` (the promotion's current official board for this division — same object as `/v1/rankings/{org}?division=` — or `null` when it publishes none), `upcoming` (up to 50 bouts booked at this weight, soonest first), `recent` (the 15 latest completed or no-contest bouts, newest first) and `roster` (up to 30 fighters who have fought at this weight, most recent first, each with `last_fought_at`). Bouts are the `/v1/fights/{id}` shape plus their `event` (`id`, `slug`, `title`, `org`, `starts_at`); a bout is matched on its recorded weight class, so catchweights are not counted. When every list is empty `meta.note` says so. An unknown org or division 404s; the division 404 lists the allowed slugs.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]},"description":"Launch org slug."},{"name":"division","in":"path","required":true,"schema":{"type":"string","enum":["strawweight","flyweight","bantamweight","featherweight","lightweight","welterweight","super-welterweight","middleweight","light-heavyweight","heavyweight","super-heavyweight","womens-strawweight","womens-flyweight","womens-bantamweight","womens-featherweight","atomweight","ironweight"]},"description":"Division slug."}],"responses":{"200":{"description":"The division","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DivisionResponse"},"example":{"data":{"org":"ufc","division":{"slug":"lightweight","name":"Lightweight","weight_limit_lbs":155},"rankings":{"org":"ufc","board":"official","snapshot_date":"2026-07-15","division":"lightweight","entries":[{"rank":0,"is_champion":true,"fighter_id":100,"fighter_slug":"justin-gaethje","name":"Justin Gaethje","nationality":"United States","country_code":"US","fighter":{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje"},"movement":0,"is_new":false}]},"upcoming":[],"recent":[{"id":185,"ordering":1,"card_section":"main","sport":"mma","weight_class":"Lightweight","division_slug":"lightweight","is_title":true,"is_main":true,"scheduled_rounds":5,"status":"completed","fighter_a":{"id":99,"slug":"ilia-topuria","name":"Ilia Topuria","nickname":"El Matador","nationality":"Spain","country_code":"ES"},"fighter_b":{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje","nickname":"The Highlight","nationality":"United States","country_code":"US"},"result":{"winner_fighter_id":100,"method":"KO/TKO","method_normalized":"ko_tko","finish_detail":null,"round":4,"time":"5:00","time_seconds":300,"details":null},"referee":"Herb Dean","bonus":null,"event":{"id":9,"slug":"ufc-326-2026-06-13","title":"UFC 326","org":"ufc","starts_at":"2026-06-14T02:00:00.000Z"}}],"roster":[{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje","nickname":"The Highlight","nationality":"United States","country_code":"US","last_fought_at":"2026-06-14T02:00:00.000Z"}]},"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/orgs/ufc/divisions/lightweight\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.org_division(\"ufc\", \"lightweight\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.orgDivision(\"ufc\", \"lightweight\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_division\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"division\": \"lightweight\"\n    }\n  }\n}"}],"x-mcp-tool":"get_division","x-mcp-tools":["get_division"]}},"/v1/events":{"get":{"tags":["Events"],"summary":"List events (schedule + results)","description":"A bare listing is the upcoming calendar: events from the last ~6h onward, soonest first. Ordering defaults: explicit `order` always wins; else `from=` or a forward status (`announced|scheduled|live|upcoming`) → `asc`; else (`completed|cancelled|postponed|to=`) → `desc`, newest first. `order=desc` with no filters browses the full archive newest-first. Live results land within ≤5 minutes (UFC ≤2). Rows are the list shape (no card) — `short_title`, `numbering` and the three section clocks (`main_card_at`, `prelims_at`, `early_prelims_at`, null when the org publishes no split) ride along.","parameters":[{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/EventStatusFilter"},"description":"Filter on lifecycle status; `postponed` is accepted (2026-09-24). `upcoming` = everything not yet over (announced, scheduled or live), soonest first."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Inclusive `YYYY-MM-DD`; must be a real calendar day."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Inclusive `YYYY-MM-DD`; must be a real calendar day."},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]},"description":"Sort by start time. Defaults are contextual — see endpoint description."},{"name":"is_title_card","in":"query","required":false,"schema":{"type":"boolean"},"description":"`true` = only cards with a title bout, `false` = only cards without one."},{"name":"is_ppv","in":"query","required":false,"schema":{"type":"boolean"},"description":"`true` = only pay-per-view cards, `false` = only non-PPV cards."},{"name":"include","in":"query","required":false,"schema":{"type":"string","enum":["headline"]},"description":"`headline` adds each event's main event: `{ fight_id, fighter_a, fighter_b, weight_class, is_title, winner_fighter_id, method, round, time }` (corners are `{ id, slug, name }`), or `null` when the card has no main-event bout. A replaced main event is skipped in favour of the active one. One extra query per page. Unknown values 400 `invalid_include`."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Events page","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsPageResponse"},"example":{"data":[{"id":8,"slug":"ufc-2026-06-14","title":"UFC Freedom 250","short_title":null,"numbering":null,"org":"ufc","sport":"mma","starts_at":"2026-06-15T00:00:00.000Z","main_card_at":"2026-06-15T00:00:00.000Z","prelims_at":null,"early_prelims_at":null,"tz":"America/New_York","status":"completed","is_ppv":false,"is_title_card":true,"headline":{"fight_id":185,"fighter_a":{"id":99,"slug":"ilia-topuria","name":"Ilia Topuria"},"fighter_b":{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje"},"weight_class":"Lightweight","is_title":true,"winner_fighter_id":100,"method":"KO/TKO","round":4,"time":"5:00"}}],"meta":{"pagination":{"next_cursor":"eyJpZCI6ODEyfQ","has_more":true,"limit":25}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_status`, `invalid_date`, `invalid_order`, `invalid_boolean`, `invalid_include`, `invalid_cursor`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events?org=ufc&status=completed&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.events(org=\"ufc\", status=\"completed\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.events({ org: \"ufc\", status: \"completed\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_events\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"limit\": 3\n    }\n  }\n}"}],"x-mcp-tool":"list_events","x-mcp-tools":["list_events","get_next_event"]}},"/v1/events/{idOrSlug}":{"get":{"tags":["Events"],"summary":"Event with full card","description":"Full fight card (both corners, results when completed), venue and event-scoped broadcast rows. Every event and card entry carries `sport` (e.g. `mma`, `bare-knuckle-boxing`). Renamed events 308-redirect from stale slugs.\n\n`include=eta` adds `eta` (ISO timestamp or `null`) to every card entry: the estimated start of that bout, by the same rule the website's event page uses. These are estimates, not a schedule — each card section anchors on its declared start, and every completed bout re-anchors the rest of its section on its real finish. Cancelled bouts get `null`.\n\n`include=odds` adds `odds` to every card entry: the current UFCalendar consensus line (`a`, `b`, `favourite`, `fair_probability_a`, `sources`, `recorded_at`), or `null` when the bout is unpriced. Information only, not betting advice; the opening/closing lines and movement are on `/v1/events/{idOrSlug}/odds`.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."},{"name":"include","in":"query","required":false,"schema":{"type":"string","enum":["eta","odds"]},"description":"`eta` = per-bout estimated start times (estimates, not a schedule; re-anchored on each completed bout). `odds` = each card entry gains `odds`, the current UFCalendar consensus line (`OddsPair`, or null when unpriced; one extra query for the whole card). Comma-separate to ask for both (`eta,odds`). Unknown values 400 `invalid_include`."}],"responses":{"200":{"description":"Event detail","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetailResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"400":{"description":"Invalid input (`invalid_include`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-320\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event(\"ufc-320\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.event(\"ufc-320\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_event_card\",\n    \"arguments\": {\n      \"event\": \"ufc-320\"\n    }\n  }\n}"}],"x-mcp-tool":"get_event_card","x-mcp-tools":["get_event_card"]}},"/v1/events/{idOrSlug}/changes":{"get":{"tags":["Events"],"summary":"Card-change log","description":"The diff log behind \"card updated\": fight added/removed, opponent swapped, card order or date moved, or a fighter profile merged (`fighter-merged`: two of our fighter ids turned out to be one athlete, so a live bout now carries the surviving id — same humans, new ids). Each entry has `id`, `kind`, `before`, `after`, `observed_at`, newest first. No-op rows and flaps (a bout scratched and reinstated within 48 h, a start time moved and moved back within 72 h) are filtered out — the same rule the website and the `card.changed` webhook apply. `/v1/changes` is the same log across every event.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Change entries","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventChangesResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-320/changes\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event_changes(\"ufc-320\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.eventChanges(\"ufc-320\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_event_changes\",\n    \"arguments\": {\n      \"event\": \"ufc-320\"\n    }\n  }\n}"}],"x-mcp-tool":"get_event_changes","x-mcp-tools":["get_event_changes"]}},"/v1/events/{idOrSlug}/watch":{"get":{"tags":["Broadcast"],"summary":"How to watch one event","description":"Who airs one event, country by country: the promotion's standing rights deals merged with the event's own confirmed broadcast listings. Series-aware — a Dana White's Contender Series or Road to UFC card gets its own grid (`series`: `dwcs` / `rtufc`), never the numbered-card deals; `null` for an ordinary card. Each country is `{ country, providers: [{ provider, kind, url, note_key, event_confirmed, rank }] }`, `WORLD` first then ISO order. `event_confirmed: true` means the event's own listing names that provider (those rows win on a collision and sort first, `rank: -1`); `note_key` is a short machine key for a caveat (e.g. main card on PPV). Pass `country=` (two letters) for that market plus worldwide; anything else 400s `invalid_country`. Links are raw. On a sub-series card `meta.note` says an empty grid means no deal is known.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z]{2}$"},"description":"ISO-3166 alpha-2 code; adds the worldwide row."}],"responses":{"200":{"description":"Watch grid","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventWatchResponse"},"example":{"data":{"event":{"id":7602,"slug":"ufc-2025-08-26","title":"DWCS 9.3","org":"ufc","starts_at":"2025-08-26T22:00:00.000Z","main_card_at":null,"prelims_at":null,"early_prelims_at":null,"tz":"America/Los_Angeles","status":"completed","is_ppv":false},"series":"dwcs","countries":[{"country":"WORLD","providers":[{"provider":"UFC Fight Pass","kind":"sub","url":"https://ufcfightpass.com","note_key":"dwcsFightPassWorld","event_confirmed":false,"rank":9}]},{"country":"GB","providers":[{"provider":"UFC Fight Pass","kind":"sub","url":"https://ufcfightpass.com","note_key":"dwcsAllEpisodes","event_confirmed":false,"rank":0}]}]},"meta":{"country":"GB","note":"Sub-series card: only dwcs rights apply; an empty grid means no deal is known."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"400":{"description":"Invalid input (`invalid_country`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-320/watch?country=US\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event_watch(\"ufc-320\", country=\"US\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.eventWatch(\"ufc-320\", { country: \"US\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"how_to_watch\",\n    \"arguments\": {\n      \"event\": \"ufc-320\",\n      \"country\": \"US\"\n    }\n  }\n}"}],"x-mcp-tool":"how_to_watch","x-mcp-tools":["how_to_watch"]}},"/v1/events/{idOrSlug}/storylines":{"get":{"tags":["Events"],"summary":"Storylines of one card","description":"The talking points of one card, computed from the record — the pre-fight read, as of the card's start (a completed card reads as it did walking in). `summary`: `title_fights`, `ranked_fighters`, `champions` and `closest_bout` (the bout nearest 50/50). `fights[]`: each non-cancelled bout with both corners (`id`, `slug`, `name`, `rank` on the promotion's official board on the event date — 0 = champion, null = unranked — and `streak`, signed: positive = consecutive wins, negative = consecutive losses), `win_probability_a` with `probability_source` (`model` = UFCalendar model output, UFC bouts only, corner-guarded; `power_index` = the UFCalendar Power Index curve; null when neither exists) and `tags[]`: `title`, `eliminator` (both corners ranked #1–#4), `coin_flip` (within 6 points of 50/50), `both_streaking` (`a`, `b` ≥ 2), `finishers` (`pct`, average recent finish rate ≥ 60%), `rematch` (`a_wins`, `b_wins`) or `trilogy_decider` (`wins`, level after two or more meetings). `card`: `avg_age` (4+ known ages), `tallest`, `longest_reach`, `nations` (`country`, `count`), `streak_leaders` (3+ wins, top 3), `debuts` (first bout in this promotion), `returns` (365+ days out, `months`, top 3) and `fastest_finish` (the quickest career round-1 KO/TKO/submission among the fighters). No fan picks, no combined record. Win probabilities are not betting advice.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Storylines","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventStorylinesResponse"},"example":{"data":{"event":{"id":16,"slug":"ufc-322-2025-11-15","title":"UFC 322: Della Maddalena vs Makhachev","org":"ufc","starts_at":"2025-11-15T23:00:00.000Z","status":"completed"},"summary":{"title_fights":2,"ranked_fighters":11,"champions":2,"closest_bout":{"fight_id":591,"win_probability_a":0.5,"probability_source":"power_index"}},"fights":[{"fight_id":583,"ordering":2,"card_section":"main","weight_class":"Women's Flyweight","is_title":true,"is_main":false,"fighter_a":{"id":410,"slug":"valentina-shevchenko","name":"Valentina Shevchenko","rank":0,"streak":3},"fighter_b":{"id":194,"slug":"zhang-weili","name":"Zhang Weili","rank":null,"streak":1},"win_probability_a":0.4928,"probability_source":"power_index","tags":[{"kind":"title"},{"kind":"coin_flip"}]}],"card":{"avg_age":32.6,"tallest":{"fighter":{"id":213,"slug":"gregory-rodrigues","name":"Gregory Rodrigues"},"height_inches":75},"longest_reach":{"fighter":{"id":425,"slug":"michael-morales","name":"Michael Morales"},"reach_inches":79},"nations":[{"country":"United States","count":4},{"country":"Poland","count":3}],"streak_leaders":[{"fighter":{"id":425,"slug":"michael-morales","name":"Michael Morales"},"streak":7}],"debuts":[{"id":622,"slug":"ethyn-ewing","name":"Ethyn Ewing"}],"returns":[],"fastest_finish":{"fighter":{"id":298,"slug":"leon-edwards","name":"Leon Edwards"},"time":"0:08"}}},"meta":{"note":"win_probability_a is UFCalendar model output for information only, not betting advice …"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-322-2025-11-15/storylines\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event_storylines(\"ufc-322-2025-11-15\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.eventStorylines(\"ufc-322-2025-11-15\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_event_storylines\",\n    \"arguments\": {\n      \"event\": \"ufc-322-2025-11-15\"\n    }\n  }\n}"}],"x-mcp-tool":"get_event_storylines","x-mcp-tools":["get_event_storylines"]}},"/v1/events/{idOrSlug}/pickem":{"get":{"tags":["Events"],"summary":"Pick'em splits for one card","description":"How the UFCalendar community is picking each bout on one card, from the site's own pick'em game: `fights[]` in card order (non-cancelled bouts), each with `fight_id`, both corners (`fighter_a`, `fighter_b`: `id`, `slug`, `name`), `picks_a`, `picks_b`, `total` and `pct_a` (the percentage of picks on corner a, 0–100 with one decimal; null when nobody has picked the bout). Counts only — never who picked. Crowd sentiment, not a market and not a forecast. An unknown event 404s.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Pick'em splits","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPickemResponse"},"example":{"data":{"event":{"id":16,"slug":"ufc-322-2025-11-15","title":"UFC 322: Della Maddalena vs Makhachev","org":"ufc","starts_at":"2025-11-15T23:00:00.000Z","status":"completed"},"fights":[{"fight_id":591,"fighter_a":{"id":152,"slug":"islam-makhachev","name":"Islam Makhachev"},"fighter_b":{"id":88,"slug":"jack-della-maddalena","name":"Jack Della Maddalena"},"picks_a":412,"picks_b":137,"total":549,"pct_a":75}]},"meta":{"note":"UFCalendar community pick'em picks — crowd sentiment, not a market and not a forecast."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-322-2025-11-15/pickem\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event_pickem(\"ufc-322-2025-11-15\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.eventPickem(\"ufc-322-2025-11-15\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_pickem_splits\",\n    \"arguments\": {\n      \"event\": \"ufc-322-2025-11-15\"\n    }\n  }\n}"}],"x-mcp-tool":"get_pickem_splits","x-mcp-tools":["get_pickem_splits"]}},"/v1/events/{idOrSlug}/odds":{"get":{"tags":["Odds"],"summary":"Consensus odds for one card","description":"The UFCalendar consensus line for every non-cancelled bout on one card, in card order: `fights[]`, each with `fight_id`, `status`, both corners (`fighter_a`, `fighter_b`: `id`, `slug`, `name`), `consensus` (the latest point; the closing line once the bout is settled), `opening` (the first point we recorded), `closing` (settled bouts only: the last point at or before the event start), `movement` (opening → consensus in implied-probability points on corner a, with the `direction` the market moved), `points` and `updated_at`. Every point is `a` / `b` (`american`, `decimal`, raw `implied_probability`), `favourite`, `fair_probability_a` (margin removed), `sources` (how many sportsbooks backed it) and `recorded_at`. A bout nobody has priced stays on the list with nulls and `points: 0`; `meta.priced` / `meta.unpriced` count both. `meta.checked_at` is when we last checked the market, whether or not the line moved. Consensus is the mean across the sportsbooks we track, refreshed every 30 minutes in the 48 hours before a card and every 2 hours otherwise; book identities are never exposed. Each bout also carries `props` — method of victory per corner, total rounds over/under per line and goes the distance (`FightProps`, or null), described on `/v1/fights/{id}/odds`. Information only, not betting advice. An unknown event 404s.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the event. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Consensus odds for the card","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventOddsResponse"},"example":{"data":{"event":{"id":782,"slug":"ufc-2025-11-15","title":"VeChain UFC 322: Della Maddalena vs Makhachev","org":"ufc","starts_at":"2025-11-16T03:00:00.000Z","status":"completed"},"fights":[{"fight_id":38195,"status":"completed","fighter_a":{"id":396,"slug":"jack-della-maddalena","name":"Jack Della Maddalena"},"fighter_b":{"id":397,"slug":"islam-makhachev","name":"Islam Makhachev"},"consensus":{"a":{"american":376,"decimal":4.76,"implied_probability":0.2101},"b":{"american":-355,"decimal":1.282,"implied_probability":0.7802},"favourite":"b","fair_probability_a":0.2121,"sources":20,"recorded_at":"2025-11-15T23:00:00.000Z"},"opening":{"a":{"american":376,"decimal":4.76,"implied_probability":0.2101},"b":{"american":-355,"decimal":1.282,"implied_probability":0.7802},"favourite":"b","fair_probability_a":0.2121,"sources":20,"recorded_at":"2025-11-15T23:00:00.000Z"},"closing":{"a":{"american":376,"decimal":4.76,"implied_probability":0.2101},"b":{"american":-355,"decimal":1.282,"implied_probability":0.7802},"favourite":"b","fair_probability_a":0.2121,"sources":20,"recorded_at":"2025-11-15T23:00:00.000Z"},"movement":{"delta_points_a":0,"direction":null,"since":"2025-11-15T23:00:00.000Z"},"points":1,"updated_at":"2025-11-15T23:00:00.000Z","props":null}]},"meta":{"note":"UFCalendar consensus line across the sportsbooks we track (book identities are not exposed). Information only, not betting advice.","checked_at":"2026-09-24T20:52:06.032Z","priced":13,"unpriced":1}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/events/ufc-322-2025-11-15/odds\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.event_odds(\"ufc-322-2025-11-15\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.eventOdds(\"ufc-322-2025-11-15\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_event_odds\",\n    \"arguments\": {\n      \"event\": \"ufc-322-2025-11-15\"\n    }\n  }\n}"}],"x-mcp-tool":"get_event_odds","x-mcp-tools":["get_event_odds"]}},"/v1/changes":{"get":{"tags":["Events"],"summary":"Card-change feed across events","description":"Every card change across the launch promotions (or one of them), newest first — the same audit trail the `card.changed` webhook delivers, for callers that poll instead. Kinds: `fight-added`, `fight-cancelled`, `fight-reinstated`, `opponent-changed`, `time-changed`, `venue-changed`, `fighter-merged`. Each entry carries `id`, `kind`, `before`, `after`, `observed_at` and its `event` (`id`, `slug`, `title`, `org`, `starts_at`). No-op rows and flaps (a bout scratched and reinstated within 48 h, a start time moved and moved back within 72 h) are filtered out, exactly as on the per-event log and the webhook. `since` defaults to 90 days ago. Unknown `kind` 400s `invalid_kind`; a bad `since` 400s `invalid_date`.","parameters":[{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"since","in":"query","required":false,"schema":{"type":"string"},"description":"Only changes observed at or after this point: `YYYY-MM-DD` (UTC midnight) or an ISO-8601 datetime. Default: 90 days ago."},{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["fight-added","fight-cancelled","fight-reinstated","opponent-changed","time-changed","venue-changed","fighter-merged"]},"description":"Narrow to one change kind."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Change entries, newest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangesFeedResponse"},"example":{"data":[{"id":813,"kind":"fighter-merged","before":{"fight_id":17044,"fighter_a_id":19423,"fighter_a":"Esteban Rodriguez","fighter_b_id":19691,"fighter_b":"Stephen Townsel","weight_class":"Ironweight","card_section":"main"},"after":{"fight_id":17044,"fighter_a_id":19423,"fighter_a":"Esteban Rodriguez","fighter_b_id":19389,"fighter_b":"Stephen Townsel","weight_class":"Ironweight","card_section":"main","merged_from_id":19691,"merged_into_id":19389},"observed_at":"2026-09-08T08:36:43.626Z","event":{"id":8169,"slug":"bkfc-93-2026-09-11","title":"BKFC 93 Hollywood: Perdomo vs Garrett","org":"bkfc","starts_at":"2026-09-11T23:00:00.000Z"}}],"meta":{"since":"2026-06-26T00:00:00.000Z","kinds":["fight-added","fight-cancelled","fight-reinstated","opponent-changed","time-changed","venue-changed","fighter-merged"],"pagination":{"next_cursor":"eyJpZCI6ODEzfQ","has_more":true}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_date`, `invalid_kind`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/changes?org=ufc&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.changes(org=\"ufc\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.changes({ org: \"ufc\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_changes\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"limit\": 10\n    }\n  }\n}"}],"x-mcp-tool":"list_changes","x-mcp-tools":["list_changes"]}},"/v1/fights/search":{"get":{"tags":["Fights"],"summary":"Search completed bouts (filtered)","description":"Completed bouts with a winner across the launch promotions, filtered — the one-call answer to \"the last title fight to end by knockout\" or \"every submission win for this fighter\". **At least one narrowing filter is required** (`title_only`, `method`, `division`, `fighter`, `winner`, `from`, `to`, `main_events_only`; `org`, `order`, `limit` and `cursor` do not count) — a bare call 400s `filter_required`, because the whole table is not sold as a list or a bulk export on any plan. Newest first by default (`order=oldest` reverses it); inside one card the main event comes first, then card order. Up to 25 rows per page and at most 10 pages deep (`page_depth_exceeded` past that — narrow the filters). Each row is the bout (same shape as `/v1/fights/{id}`) plus its `event` (`id`, `slug`, `title`, `org`, `starts_at`); `meta.filters` echoes the filters applied. `fighter`/`winner` take a slug or id (404 when not on the roster).","parameters":[{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"title_only","in":"query","required":false,"schema":{"type":"boolean"},"description":"`true` = title bouts only."},{"name":"method","in":"query","required":false,"schema":{"type":"string","enum":["ko","sub","dec","finish","any"]},"description":"`ko` = KO/TKO, `sub` = submission, `dec` = any decision, `finish` = KO/TKO or submission, `any` (default) = no method filter."},{"name":"division","in":"query","required":false,"schema":{"type":"string","maxLength":40},"description":"Division slug (`lightweight`, `womens-strawweight`, …) for an exact match, or a name fragment (≤40 characters) matched anywhere in the weight class."},{"name":"fighter","in":"query","required":false,"schema":{"type":"string"},"description":"Fighter slug or id — bouts this fighter was in, either corner."},{"name":"winner","in":"query","required":false,"schema":{"type":"string"},"description":"Fighter slug or id — bouts this fighter won."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Earliest event date, YYYY-MM-DD."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Latest event date, YYYY-MM-DD."},{"name":"main_events_only","in":"query","required":false,"schema":{"type":"boolean"},"description":"`true` = main events only."},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["newest","oldest"],"default":"newest"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`; an unreadable cursor restarts at the first page."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":25,"default":10}}],"responses":{"200":{"description":"Matching bouts","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightSearchResponse"},"example":{"data":[{"id":185,"ordering":1,"card_section":"main","sport":"mma","weight_class":"Lightweight","division_slug":"lightweight","is_title":true,"is_main":true,"scheduled_rounds":5,"status":"completed","fighter_a":{"id":99,"slug":"ilia-topuria","name":"Ilia Topuria","nickname":"El Matador","nationality":"Spain","country_code":"ES"},"fighter_b":{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje","nickname":"The Highlight","nationality":"United States","country_code":"US"},"result":{"winner_fighter_id":100,"method":"KO/TKO","method_normalized":"ko_tko","finish_detail":null,"round":4,"time":"5:00","time_seconds":300,"details":null},"referee":"Marc Goddard","bonus":null,"event":{"id":8,"slug":"ufc-2026-06-14","title":"UFC Freedom 250","org":"ufc","starts_at":"2026-06-15T00:00:00.000Z"}}],"meta":{"order":"newest","filters":{"org":"ufc","title_only":true,"method":"ko","division":null,"fighter":null,"winner":null,"from":null,"to":null,"main_events_only":false},"pagination":{"next_cursor":"eyJpZCI6MTg1LCJwIjoxfQ","has_more":true}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`filter_required`, `invalid_org`, `invalid_boolean`, `invalid_method`, `invalid_division`, `invalid_date`, `invalid_order`, `page_depth_exceeded`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/search?org=ufc&method=ko&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.find_fights(org=\"ufc\", method=\"ko\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.findFights({ org: \"ufc\", method: \"ko\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"find_fights\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"title_only\": true,\n      \"method\": \"ko\",\n      \"limit\": 5\n    }\n  }\n}"}],"x-mcp-tool":"find_fights","x-mcp-tools":["find_fights"]}},"/v1/fights/{id}":{"get":{"tags":["Fights"],"summary":"One bout","description":"Bout with corners (`FighterRef` with `country_code`), `sport` (bout override, else the org sport), `weight_class` + `division_slug`, result (raw `method` plus `method_normalized` / `finish_detail` / `round` / `time` / `time_seconds` / referee) and bonus flags, plus a compact `event`. `include=odds` adds `odds`: the current UFCalendar consensus line (`OddsPair`), or `null` when the bout is unpriced — information only, not betting advice; opening, closing and movement are on `/v1/fights/{id}/odds`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"include","in":"query","required":false,"schema":{"type":"string","enum":["odds"]},"description":"`odds` = the current consensus line (the closing line once the bout is settled) on the bout. Unknown values 400 `invalid_include`."}],"responses":{"200":{"description":"Fight","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightResponse"},"example":{"data":{"id":83379,"ordering":9,"card_section":"prelims","sport":"mma","weight_class":"Featherweight","division_slug":"featherweight","is_title":false,"is_main":false,"scheduled_rounds":3,"status":"completed","fighter_a":{"id":213,"slug":"jack-jenkins","name":"Jack Jenkins","nickname":"Phar","nationality":"Australia","country_code":"AU"},"fighter_b":{"id":1120,"slug":"sean-woodson","name":"Sean Woodson","nickname":"The Sniper","nationality":"United States","country_code":"US"},"result":{"winner_fighter_id":1120,"method":"Decision - Split","method_normalized":"decision_split","finish_detail":"Split","round":3,"time":"5:00","time_seconds":300,"details":"28 - 29. 29 - 28. 28 - 29."},"referee":"Marc Goddard","bonus":null,"event":{"id":2507,"slug":"ufc-fight-night-2026-08-29","title":"UFC Fight Night: Nurmagomedov vs Song","org":"ufc","starts_at":"2026-08-29T07:00:00.000Z"},"odds":{"a":{"american":131,"decimal":2.31,"implied_probability":0.4329},"b":{"american":-152,"decimal":1.658,"implied_probability":0.6032},"favourite":"b","fair_probability_a":0.4178,"sources":24,"recorded_at":"2026-08-29T10:50:34.350Z"}},"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_include`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fight(83379)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fight(83379);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_fight\",\n    \"arguments\": {\n      \"fight_id\": \"83379\",\n      \"include\": [\n        \"stats\",\n        \"scorecards\",\n        \"odds\"\n      ]\n    }\n  }\n}"}],"x-mcp-tool":"get_fight","x-mcp-tools":["get_fight"]}},"/v1/fights/{id}/stats":{"get":{"tags":["Fights"],"summary":"Per-fight totals","description":"Both corners: knockdowns, significant/total strikes, takedowns, submission attempts, reversals, control time, and target/position splits (head/body/leg, distance/clinch/ground) where the source provides them. Each line carries `corner` (`a` = the bout's `fighter_a`, `b` = `fighter_b`) beside the stored `fighter_position` (1/2). `distance_time_sec`, `clinch_time_sec`, `ground_time_sec` (integers, nullable) are seconds spent at distance / in the clinch / on the ground, and can appear alongside official strike counts on any org (position time is filled in even where the rest of the row comes from the official stats).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Stat lines","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightStatsResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379/stats\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fight_stats(83379)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fightStats(83379);"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fights/{id}/rounds":{"get":{"tags":["Fights"],"summary":"Round-by-round stats","description":"Per-round stat lines for both corners — each with `round` (and the stored `round_number` twin) and `corner` — including target/position splits (head/body/leg, distance/clinch/ground) where they are logged per round (BKFC for head/body/distance/clinch; other orgs may additionally carry leg/ground). `distance_time_sec`, `clinch_time_sec`, `ground_time_sec` (integers, nullable) are seconds spent at distance / in the clinch / on the ground, per round.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Round lines","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightRoundsResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379/rounds\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fight_rounds(83379)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fightRounds(83379);"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fights/{id}/scorecards":{"get":{"tags":["Scorecards"],"summary":"Judges' scorecards for a bout","description":"The official athletic-commission record: every judge, their score for each round, their card total, the decision type and any point deductions. UFC back to 1995, PFL to 2018, OKTAGON to 2025, RIZIN from March 2026 (Japan has no athletic commission — the record is the one published by the officials body that judges RIZIN). UFC cards are cross-checked against the official scorecards ufc.com publishes (Dana White's Contender Series and Road to UFC included, from March 2022), which also fill bouts the commission record does not cover. `source` says who published the cards: `commission-record`, `ufc-official-cards`, or a promotion's own slug (`oktagon-official`, `pfl-official`, `aca-official`).\n\n`total_a`/`total_b` and every round are oriented to the bout's `fighter_a_id`/`fighter_b_id`, which are repeated on the payload so you never have to fetch the fight to read a card. `winner_fighter_id` is who THAT judge gave it to.\n\n**Check `scores_known` before charting totals.** When it is false the commission published only the outcome, and `total_a`/`total_b` are a 1-0 / 1-1 / 0-0 placeholder rather than a score (66 fights, nearly all pre-2005); `rounds` is empty on those cards.\n\n**A bout with no commission record answers 200, not 404** (2026-09-24): `cards: []`, `decision_type: null`, and `meta.note` says why (a finish, or cards not yet published). 404 is reserved for an unknown fight, so a client can tell the two apart.\n\n**Some cards carry no judge identity.** PFL's US events have no published commission scorecard, so those bouts are served from PFL's own results post: three cards with `judge_id`/`judge_name` null, `total_a`/`total_b` set and `rounds` empty. `scores_known` is still true — the totals are real. Europe/UAE PFL cards and every other org carry the named, round-by-round record.\n\nMedia-member and fan scorecards are not part of this dataset.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Scorecards","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightScorecardsResponse"},"example":{"data":{"fight_id":83379,"fighter_a_id":213,"fighter_b_id":1120,"source":"commission-record","decision_type":"split","deductions":[],"cards":[{"judge_id":36,"judge_name":"Vito Paolillo","total_a":28,"total_b":29,"winner_fighter_id":1120,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":9,"b":10},{"round":2,"a":10,"b":9},{"round":3,"a":9,"b":10}]},{"judge_id":34,"judge_name":"Clemens Werner","total_a":29,"total_b":28,"winner_fighter_id":213,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":9,"b":10},{"round":2,"a":10,"b":9},{"round":3,"a":10,"b":9}]},{"judge_id":17,"judge_name":"Cezary Wojciechowski","total_a":28,"total_b":29,"winner_fighter_id":1120,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":9,"b":10},{"round":2,"a":10,"b":9},{"round":3,"a":9,"b":10}]}]},"meta":{"fight_id":83379}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379/scorecards\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fight_scorecards(83379)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fightScorecards(83379);"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fights/{id}/odds":{"get":{"tags":["Odds"],"summary":"Consensus odds for one bout","description":"The UFCalendar consensus line for one bout: `consensus` (the latest point; the closing line once the bout is settled), `opening` (the first point we recorded), `closing` (settled bouts only, `completed` or `no_contest`: the last point at or before the event start; null until then), `movement` (opening → consensus: `delta_points_a` in implied-probability points on corner a, `direction` = the corner the market moved toward, `since`), `points` (stored points) and `updated_at` (when the line last moved). Every point is `a` / `b` (`american`, `decimal`, raw `implied_probability`), `favourite`, `fair_probability_a` (margin removed) and `sources` (how many sportsbooks backed it). Consensus is the mean across the sportsbooks we track, in decimal space; book identities are never exposed. `meta.checked_at` is when we last checked the market, whether or not the line moved; `meta.history` is the movement series (Pro+). A bout nobody priced answers 200 with nulls and `points: 0`; 404 is reserved for an unknown fight.\n\n`props` carries the prop markets (`FightProps`, or null when no sportsbooks price them): `method` (per corner `a` / `b`: `ko`, `sub`, `dec` — each `yes` / `no` prices, `fair_probability` = its share of all six outcomes when all six are priced, `sources`), `total_rounds` (over/under per rounds line, ascending) and `distance` (goes the distance yes / no). Same consensus rule as the moneyline (the sportsbook mean; prediction markets excluded, a book far from the rest dropped, two sportsbooks minimum); prices are recorded until the event starts, so a settled bout carries its closing props (`closing: true`). Books post props in fight week. Information only, not betting advice.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Consensus odds","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightOddsResponse"},"example":{"data":{"fight_id":83379,"status":"completed","event":{"id":2507,"slug":"ufc-fight-night-2026-08-29","title":"UFC Fight Night: Nurmagomedov vs Song","org":"ufc","starts_at":"2026-08-29T07:00:00.000Z"},"fighter_a":{"id":213,"slug":"jack-jenkins","name":"Jack Jenkins"},"fighter_b":{"id":1120,"slug":"sean-woodson","name":"Sean Woodson"},"consensus":{"a":{"american":131,"decimal":2.31,"implied_probability":0.4329},"b":{"american":-152,"decimal":1.658,"implied_probability":0.6032},"favourite":"b","fair_probability_a":0.4178,"sources":24,"recorded_at":"2026-08-29T10:50:34.350Z"},"opening":{"a":{"american":194,"decimal":2.94,"implied_probability":0.3401},"b":{"american":-567,"decimal":1.176,"implied_probability":0.8501},"favourite":"b","fair_probability_a":0.2858,"sources":1,"recorded_at":"2026-08-18T22:50:43.418Z"},"closing":{"a":{"american":125,"decimal":2.25,"implied_probability":0.4444},"b":{"american":-144,"decimal":1.694,"implied_probability":0.5902},"favourite":"b","fair_probability_a":0.4296,"sources":24,"recorded_at":"2026-08-29T04:20:33.768Z"},"movement":{"delta_points_a":9.28,"direction":"a","since":"2026-08-18T22:50:43.418Z"},"points":57,"updated_at":"2026-08-29T10:50:34.350Z","props":{"method":{"a":{"ko":{"yes":{"american":411,"decimal":5.11,"implied_probability":0.1957},"no":null,"fair_probability":0.1649,"sources":12,"recorded_at":"2026-08-29T07:00:00.000Z"},"sub":{"yes":{"american":1322,"decimal":14.22,"implied_probability":0.0703},"no":null,"fair_probability":0.0593,"sources":12,"recorded_at":"2026-08-29T07:00:00.000Z"},"dec":{"yes":{"american":290,"decimal":3.9,"implied_probability":0.2564},"no":{"american":-425,"decimal":1.235,"implied_probability":0.8095},"fair_probability":0.216,"sources":11,"recorded_at":"2026-08-29T07:00:00.000Z"}},"b":{"ko":{"yes":{"american":462,"decimal":5.62,"implied_probability":0.1779},"no":null,"fair_probability":0.1499,"sources":12,"recorded_at":"2026-08-29T07:00:00.000Z"},"sub":{"yes":{"american":1078,"decimal":11.78,"implied_probability":0.0849},"no":null,"fair_probability":0.0715,"sources":12,"recorded_at":"2026-08-29T07:00:00.000Z"},"dec":{"yes":{"american":149,"decimal":2.49,"implied_probability":0.4016},"no":null,"fair_probability":0.3384,"sources":11,"recorded_at":"2026-08-29T07:00:00.000Z"}}},"total_rounds":[{"line":1.5,"over":{"american":-386,"decimal":1.259,"implied_probability":0.7942},"under":{"american":258,"decimal":3.58,"implied_probability":0.2793},"fair_probability_over":0.7398,"sources":4,"recorded_at":"2026-08-29T07:00:00.000Z"},{"line":2.5,"over":{"american":-193,"decimal":1.518,"implied_probability":0.6587},"under":{"american":153,"decimal":2.53,"implied_probability":0.3953},"fair_probability_over":0.625,"sources":17,"recorded_at":"2026-08-29T07:00:00.000Z"}],"distance":{"yes":{"american":-160,"decimal":1.625,"implied_probability":0.6154},"no":{"american":123,"decimal":2.23,"implied_probability":0.4484},"fair_probability":0.5785,"sources":11,"recorded_at":"2026-08-29T07:00:00.000Z"},"closing":true,"updated_at":"2026-08-29T07:00:00.000Z"}},"meta":{"note":"UFCalendar consensus line across the sportsbooks we track (book identities are not exposed). Information only, not betting advice.","checked_at":"2026-09-24T20:52:06.032Z","history":"/v1/fights/83379/odds/history"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379/odds\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fight_odds(83379)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fightOdds(83379);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_fight_odds\",\n    \"arguments\": {\n      \"fight_id\": \"83379\"\n    }\n  }\n}"}],"x-mcp-tool":"get_fight_odds","x-mcp-tools":["get_fight_odds"]}},"/v1/fights/{id}/odds/history":{"get":{"tags":["Odds"],"summary":"Consensus line movement (Pro+)","description":"Every stored consensus point for one bout, oldest first: the line-movement series. A point is stored only when the consensus changes, so the timestamps follow real market moves, not our refresh cadence. Each point: `id`, `a` / `b` (`american`, `decimal`, raw `implied_probability`), `favourite`, `fair_probability_a` (margin removed), `sources` (how many sportsbooks backed it) and `recorded_at`. `from` / `to` (inclusive `YYYY-MM-DD`) narrow the window; `limit` 1 to 500 (default 100); pass `meta.pagination.next_cursor` back as `cursor` for the next page. Requires Pro or higher (403 `tier_required`, answered before the fight is looked up). Book identities are never exposed. Information only, not betting advice.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Earliest recorded day, inclusive `YYYY-MM-DD`."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Latest recorded day, inclusive `YYYY-MM-DD`; must not precede `from`."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Consensus points, oldest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightOddsHistoryResponse"},"example":{"data":[{"id":338130,"a":{"american":194,"decimal":2.94,"implied_probability":0.3401},"b":{"american":-567,"decimal":1.176,"implied_probability":0.8501},"favourite":"b","fair_probability_a":0.2858,"sources":1,"recorded_at":"2026-08-18T22:50:43.418Z"},{"id":338555,"a":{"american":-107,"decimal":1.935,"implied_probability":0.5169},"b":{"american":-155,"decimal":1.645,"implied_probability":0.6078},"favourite":"b","fair_probability_a":0.4596,"sources":4,"recorded_at":"2026-08-20T16:50:41.335Z"}],"meta":{"fight_id":83379,"note":"UFCalendar consensus line across the sportsbooks we track (book identities are not exposed). Information only, not betting advice.","pagination":{"next_cursor":"eyJpZCI6MzM4NTU1fQ","has_more":true}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_cursor`, `invalid_date`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Requires Pro or above (`tier_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fights/83379/odds/history?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.fight_odds_history(83379):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.fightOddsHistory(83379)) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_odds_history\",\n    \"arguments\": {\n      \"fight_id\": \"83379\",\n      \"limit\": 50\n    }\n  }\n}"}],"x-mcp-tool":"get_odds_history","x-mcp-tools":["get_odds_history"]}},"/v1/scorecards/splits":{"get":{"tags":["Scorecards"],"summary":"Split and majority decisions","description":"Completed bouts the judges decided on a split or majority (including majority and split draws), newest first, across the launch promotions or one of them, optionally in a date range. Each row is the bout (same shape as `/v1/fights/{id}`) plus its `event`, the `decision_type`, `official_winner_fighter_id` (`null` on a draw), every judge's card (`cards`, same objects as `/v1/fights/{id}/scorecards`) and `dissenting_judges` — the cards that disagree with the official result (`judge_id`, `judge_name`, `total_a`, `total_b`, `winner_fighter_id`, `is_draw`, `scores_known`). A card with no readable verdict is not counted as a dissent; an outcome-only card (`scores_known: false`) is, flagged. Commission records only — facts as filed, no verdict of our own; sources that publish no decision type are not listed. Up to 50 rows a page.","parameters":[{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Earliest event date, YYYY-MM-DD."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Latest event date, YYYY-MM-DD."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25}}],"responses":{"200":{"description":"Split and majority decisions, newest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitDecisionsResponse"},"example":{"data":[{"id":184,"ordering":11,"card_section":"main","sport":"mma","weight_class":"Women's Flyweight","division_slug":"womens-flyweight","is_title":false,"is_main":false,"scheduled_rounds":3,"status":"completed","fighter_a":{"id":97,"slug":"jeisla-chaves","name":"Jeisla Chaves","nickname":"A Braba","nationality":"Brazil","country_code":"BR"},"fighter_b":{"id":98,"slug":"yuneisy-duben","name":"Yuneisy Duben","nickname":null,"nationality":"Cuba","country_code":"CU"},"result":{"winner_fighter_id":97,"method":"Decision - Split","method_normalized":"decision_split","finish_detail":"Split","round":3,"time":"5:00","time_seconds":300,"details":null},"referee":"Dan Miragliotta","bonus":null,"event":{"id":9,"slug":"ufc-fight-night-2026-06-06","title":"UFC Fight Night: Muhammad vs Bonfim","org":"ufc","starts_at":"2026-06-06T21:00:00.000Z"},"decision_type":"split","official_winner_fighter_id":97,"cards":[{"judge_id":42,"judge_name":"Ron McCarthy","total_a":29,"total_b":28,"winner_fighter_id":97,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":10,"b":9},{"round":2,"a":10,"b":9},{"round":3,"a":9,"b":10}]},{"judge_id":35,"judge_name":"Tony Weeks","total_a":28,"total_b":29,"winner_fighter_id":98,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":9,"b":10},{"round":2,"a":10,"b":9},{"round":3,"a":9,"b":10}]},{"judge_id":29,"judge_name":"Clemens Werner","total_a":29,"total_b":28,"winner_fighter_id":97,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":10,"b":9},{"round":2,"a":10,"b":9},{"round":3,"a":9,"b":10}]}],"dissenting_judges":[{"judge_id":35,"judge_name":"Tony Weeks","total_a":28,"total_b":29,"winner_fighter_id":98,"is_draw":false,"scores_known":true}]}],"meta":{"pagination":{"next_cursor":"eyJpZCI6MTg0fQ","has_more":true},"note":"Commission cards only; sources that publish no decision type are not listed here."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_date`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/scorecards/splits?org=ufc&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.split_decisions(org=\"ufc\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.splitDecisions({ org: \"ufc\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_split_decisions\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"limit\": 5\n    }\n  }\n}"}],"x-mcp-tool":"list_split_decisions","x-mcp-tools":["list_split_decisions"]}},"/v1/judges":{"get":{"tags":["Scorecards"],"summary":"Judge directory","description":"Every official who has scored a launch-org bout (~550), busiest first, with their career shape: fights, rounds scored, rounds scored 10-8 or wider, three-judge cards that came back split, and `lone_dissents` — cards where this judge alone picked the other corner.\n\nFilter with `q` (name), `org`, and `min_fights` (the rates mean little below ~10 fights).\n\n`meta.league` is the whole directory's baseline, never the filtered subset: `judges`, `fights` (judge-cards), `rounds_scored`, and the pooled rates `wide_round_rate` (wide rounds / rounds), `split_rate` (split / three-judge cards) and `lone_dissent_rate` (lone dissents / three-judge cards).","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Name substring, case-insensitive."},{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"min_fights","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Only judges with at least this many scored fights."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Judges page","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgesPageResponse"},"example":{"data":[{"id":5,"name":"Sal D'Amato","fights":1096,"rounds_scored":3598,"wide_rounds":146,"split_fights":242,"three_judge_fights":1095,"lone_dissents":118,"first_scored":"2009-04-01","last_scored":"2026-08-15","orgs":["pfl","ufc"]}],"meta":{"total":550,"league":{"judges":550,"fights":107000,"rounds_scored":318000,"wide_round_rate":0.0412,"split_rate":0.2011,"lone_dissent_rate":0.1023},"pagination":{"next_cursor":"eyJpZCI6NX0","has_more":true,"limit":25}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_cursor`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/judges?org=ufc&min_fights=10&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.judges(org=\"ufc\", min_fights=10):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.judges({ org: \"ufc\", minFights: 10 })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_judges\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"min_fights\": 10\n    }\n  }\n}"}],"x-mcp-tool":"list_judges","x-mcp-tools":["list_judges"]}},"/v1/judges/{id}":{"get":{"tags":["Scorecards"],"summary":"One judge","description":"A single official's career aggregates. Same shape as a directory row.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Judge","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgeResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/judges/5\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.judge(5)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.judge(5);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_judge\",\n    \"arguments\": {\n      \"judge_id\": \"5\"\n    }\n  }\n}"}],"x-mcp-tool":"get_judge","x-mcp-tools":["get_judge"]}},"/v1/judges/{id}/scorecards":{"get":{"tags":["Scorecards"],"summary":"Everything a judge has scored","description":"This judge's card for every launch-org bout they worked, newest first — the bout, its event, the decision type, and their own card, with where it sat on the panel: `lone_dissent` (three known verdicts and this judge alone differs from both others), `split` (three known verdicts that do not all agree) — both `null` when the panel is not three judges or a verdict is unknown — and `colleagues`, the other judges' totals and verdicts (the full round-by-round panel is on `/v1/fights/{id}/scorecards`). Cursor-paginated.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Cards, newest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgeScorecardsResponse"},"example":{"data":[{"fight_id":83379,"event":{"id":2507,"slug":"ufc-fight-night-2026-08-29","title":"UFC Fight Night: Nurmagomedov vs Song","org":"ufc","starts_at":"2026-08-29T07:00:00.000Z"},"fighter_a_id":213,"fighter_b_id":1120,"decision_type":"split","card":{"judge_id":36,"judge_name":"Vito Paolillo","total_a":28,"total_b":29,"winner_fighter_id":1120,"is_draw":false,"scores_known":true,"rounds":[{"round":1,"a":9,"b":10}]},"lone_dissent":false,"split":true,"colleagues":[{"judge_id":34,"judge_name":"Clemens Werner","total_a":29,"total_b":28,"winner_fighter_id":213,"is_draw":false},{"judge_id":17,"judge_name":"Cezary Wojciechowski","total_a":28,"total_b":29,"winner_fighter_id":1120,"is_draw":false}]}],"meta":{"judge":{"id":36,"name":"Vito Paolillo","fights":412,"rounds_scored":1290,"wide_rounds":40,"split_fights":88,"three_judge_fights":410,"lone_dissents":31,"first_scored":"2014-05-31","last_scored":"2026-08-29","orgs":["oktagon","ufc"]},"pagination":{"next_cursor":null,"has_more":false,"limit":25}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_cursor`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/judges/5/scorecards?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.judge_scorecards(5):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.judgeScorecards(5)) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_judge_scorecards\",\n    \"arguments\": {\n      \"judge_id\": \"5\",\n      \"limit\": 3\n    }\n  }\n}"}],"x-mcp-tool":"get_judge_scorecards","x-mcp-tools":["get_judge_scorecards"]}},"/v1/fighters":{"get":{"tags":["Fighters"],"summary":"Roster search","description":"Fighters with at least one launch-org fight (~4.5k). `q` is accent-insensitive. Rows are identity only (`FighterRef` plus `second_nationality`); `country_code` is ISO-2 derived from `nationality`. `country` accepts an ISO-2 code (matched against every name that maps to it) or a country name.","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"ISO-2 code (`US`, `GE`) or country name; matches either nationality."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Fighters page","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FightersPageResponse"},"example":{"data":[{"id":373,"slug":"aleksandre-topuria","name":"Aleksandre Topuria","nickname":"El Conquistador","nationality":"Georgia","country_code":"GE","second_nationality":"Spain"}],"meta":{"pagination":{"next_cursor":null,"has_more":false,"limit":25}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_cursor`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters?q=makhachev&org=ufc&country=DE&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.fighters(q=\"makhachev\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.fighters({ q: \"makhachev\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"search_fighters\",\n    \"arguments\": {\n      \"q\": \"makhachev\",\n      \"limit\": 3\n    }\n  }\n}"}],"x-mcp-tool":"search_fighters","x-mcp-tools":["search_fighters"]}},"/v1/fighters/{idOrSlug}":{"get":{"tags":["Fighters"],"summary":"Fighter profile","description":"Bio, records, stats, UFCalendar Power Index summary, and CC-licensed images with attribution metadata (displaying the credit is a license requirement). **Read `records` and `stats`** (added 2026-09-24): `records` is a map keyed by a clean name — `pro_mma` (the career MMA record), `amateur_mma`, `pro_kickboxing`, …, and the org slug for a record INSIDE one promotion (`ufc`, `one`, `bkfc`) — each `{ value, source, scope }`; `stats` is ONE per-minute panel (SLpM, striking accuracy/defense, SApM, takedown average/accuracy/defense, submission average), always the widest sample UFCalendar holds (the `pro-mma` panel: every promotion; `tracked` for a fighter with no MMA career, e.g. a Muay Thai athlete), with `basis: { bouts, orgs, source, scope }` stating exactly which bouts it averages over (e.g. 7 UFC bouts, or 18 across UFC + Oktagon); `null` when no real panel exists. `career_stats` is the raw per-source row list these are built from and stays unchanged for existing integrations.\n\n`next_fight` is the fighter's next booked bout (not completed or cancelled, on an event that has not been cancelled and started no more than ~6h ago; `result` is always null) and `last_fight` their most recent completed or no-contest bout — both in the same shape as a `source: \"native\"` row of `/history`, or `null`.\n\n`?include=bonuses` adds `bonuses`: the UFC post-fight bonus ledger — `counts` of Fight / Performance / KO / Submission of the Night (`fotn`, `potn`, `kotn`, `sotn`), their `total`, and the `fights` that earned them, newest first. Fight of the Night is credited to both corners, the other awards to the winner only. Award counts only, no dollar amounts.\n\n`?include=credentials` adds `credentials`: the fighter's combat-sports background, researched by UFCalendar from public sources — `credentials[]` (`kind`: belt-rank, competition-result, professional-title, national-team, base-style, training-started, athletic-education, sports-club, award, sport-rank, record; `discipline`, `competition`, `placement`, `rank`, `year`, `detail` (kind-specific extras), `note`) and `affiliations[]` (`kind`: gym, coach, training-partner, manager; `name`, `role`, `status` current/former, `is_primary`, `location`, `gym`, `discipline`, `relationship`, `as_of`, `period`, `note`). EVERY row carries `sources` (the public reference URLs behind the claim — Wikipedia, the promotion's own pages, official bodies; may be empty, since only public references are listed) and `confidence` (`confirmed` = an official body or 2+ independent sources, `reported` = one credible outlet); unverified claims are never served. `meta.note` asks you to verify before republishing. Both lists may be empty.\n\nComma-separate to combine (`include=bonuses,credentials`). An unknown `include` value is 400 `invalid_include`.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the fighter. Stale slugs 308-redirect to the canonical URL."},{"name":"include","in":"query","required":false,"schema":{"type":"string","enum":["bonuses","credentials"]},"description":"Comma-separated extra blocks. `bonuses` = the UFC bonus ledger; `credentials` = grappling and wrestling pedigree, gyms and coaches (sourced, confidence-graded)."}],"responses":{"200":{"description":"Fighter detail","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FighterResponse"},"example":{"data":{"id":2215,"slug":"charles-oliveira-3","name":"Charles Oliveira","nickname":"do Bronx","nationality":"Brazil","country_code":"BR","second_nationality":null,"height_inches":70,"weight_lbs":155,"reach_inches":74,"stance":"Orthodox","dob":"1989-10-17","team":"Chute Boxe Diego Lima","birthplace":"Guarujá, Brazil","records":{"pro_mma":{"value":"37-11-0 (1 NC)","wins":37,"losses":11,"draws":0,"no_contests":1,"source":"public-records","scope":"pro-mma"},"ufc":{"value":"25-11-0 (1 NC)","wins":25,"losses":11,"draws":0,"no_contests":1,"source":"ufc-stats","scope":"ufc-only"}},"stats":{"slpm":"3.23","str_acc":"55%","sapm":"3.05","str_def":null,"td_avg":"2.29","td_acc":"39%","td_def":"54%","sub_avg":null,"values":{"slpm":3.23,"str_acc":0.55,"sapm":3.05,"str_def":null,"td_avg":2.29,"td_acc":0.39,"td_def":0.54,"sub_avg":null},"basis":{"bouts":36,"orgs":["ufc"],"source":"ufcalendar","scope":"pro-mma"}},"career_stats":[{"scope":"pro-mma","source":"public-records","record":"37-11-0 (1 NC)","slpm":"3.23","str_acc":"55%","sapm":"3.05","str_def":null,"td_avg":"2.29","td_acc":"39%","td_def":"54%","sub_avg":null},{"scope":"ufc-only","source":"ufc-stats","record":"25-11-0 (1 NC)","slpm":"3.23","str_acc":"55%","sapm":"3.05","str_def":null,"td_avg":"2.29","td_acc":"39%","td_def":"54%","sub_avg":null}],"power_index":null,"images":[],"next_fight":null,"last_fight":{"fight_id":5696,"event_id":71,"event_title":"UFC 326: Holloway vs Oliveira 2","event_slug":"ufc-326-2026-03-08","org_slug":"ufc","date":"2026-03-07","opponent_id":1604,"opponent_name":"Max Holloway","opponent_slug":"max-holloway-3","result":"win","method":"Decision - Unanimous","round":5,"time":"5:00","weight_class":"Lightweight","is_title":false,"sport":"mma","source":"native"},"bonuses":{"org":"ufc","total":6,"counts":{"fotn":3,"potn":3,"kotn":0,"sotn":0},"fights":[{"fight_id":5696,"event_slug":"ufc-326-2026-03-08","date":"2026-03-07","awards":["fotn"]},{"fight_id":4054,"event_slug":"ufc-274-2022-05-07","date":"2022-05-07","awards":["potn","fotn"]}]},"credentials":{"credentials":[{"kind":"belt-rank","discipline":"bjj","competition":null,"placement":null,"rank":"black-belt","year":2013,"detail":{"awarded_by":"Luiz Dorea"},"note":null,"sources":["https://en.wikipedia.org/wiki/Charles_Oliveira"],"confidence":"confirmed"}],"affiliations":[{"kind":"gym","name":"Chute Boxe Diego Lima","role":null,"status":"current","is_primary":true,"location":"São Paulo, Brazil","gym":null,"discipline":null,"relationship":null,"as_of":"2025-06","period":null,"note":null,"sources":["https://en.wikipedia.org/wiki/Charles_Oliveira"],"confidence":"reported"}]}},"meta":{"note":"Researched by UFCalendar from public sources and graded by confidence — verify before republishing."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"400":{"description":"Invalid input (`invalid_include`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters/islam-makhachev\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fighter(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fighter(\"islam-makhachev\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_fighter\",\n    \"arguments\": {\n      \"fighter\": \"islam-makhachev\",\n      \"include\": [\n        \"history\"\n      ],\n      \"history_limit\": 5\n    }\n  }\n}"}],"x-mcp-tool":"get_fighter","x-mcp-tools":["get_fighter"]}},"/v1/fighters/{idOrSlug}/history":{"get":{"tags":["Fighters"],"summary":"Complete career timeline","description":"The fighter's FULL multi-promotion career: native tracked bouts (richest data, `source: \"native\"`) merged with the wider multi-promotion career record (`source: \"history\"`). Spans every promotion they fought in — not just launch orgs. **Every key is present on every row** (null when unknown), and each row carries `status` (one vocabulary across both sources: `win`, `loss`, `draw`, `no_contest`, `cancelled`, `upcoming`, `unknown`), `method_normalized`, `time_seconds` and an `opponent` object (`{id, slug, name}`, ids only on native rows) beside the raw `result` / `method` / `time` strings. Newest first; `meta.truncated` is true when the history rows hit their 500-row cap. `source_slug` names the publisher: `ufcalendar` on native rows; on history rows an official publisher (`ufc-official`, `wikipedia`, a promotion's `*-official`), else `public-records`.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the fighter. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Timeline entries, newest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FighterHistoryResponse"},"example":{"data":[{"fight_id":60381,"event_id":719,"event_title":"UFC 309: Jones vs Miocic","event_name":"UFC 309: Jones vs Miocic","event_slug":"ufc-309-2024-11-16","org_slug":"ufc","opponent_id":1946,"opponent_slug":"stipe-miocic","is_title":true,"competition_level":"pro","source_slug":"ufcalendar","date":"2024-11-17","opponent_name":"Stipe Miocic","result":"win","method":"KO/TKO","round":3,"time":"4:29","weight_class":"Heavyweight","sport":"mma","source":"native","status":"win","method_normalized":"ko_tko","time_seconds":269,"opponent":{"id":1946,"slug":"stipe-miocic","name":"Stipe Miocic"}}],"meta":{"truncated":false}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters/islam-makhachev/history\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fighter_history(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fighterHistory(\"islam-makhachev\");"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fighters/{idOrSlug}/stats":{"get":{"tags":["Fighters"],"summary":"Career statistics","description":"Raw per-source career rows, plus the readable split in `meta.records` / `meta.stats` (the same objects the fighter profile carries — read those unless you need the per-source rows). `data`: per-scope career stats (`pro-mma`, `amateur-mma`, …): record, strikes landed/absorbed per minute, accuracy/defense, takedown and submission averages, and `updated_at` (this route only). Exactly ONE row per scope; `source` names the publisher it came from: `public-records` (the complete multi-promotion career record) is preferred, then the promotion's own site (`ufc-stats`, `bkfc-official`, `one-official`, …), then `ufcalendar`. A `public-records` record is a point-in-time snapshot advanced by every settled bout UFCalendar tracked after it, so it matches the record on ufcalendar.com. A row's record and its stats cover the same bouts. `pro-mma` = the career record plus striking/grappling averages UFCalendar computes over EVERY settled bout it holds per-fight totals for, in any promotion (Contender Series included); its stats are null when no such bout exists. Org-scoped rows (`ufc-only`, `bkfc-only`, `one-only`) are the fighter's record INSIDE that promotion, not a career record: `ufc-only` carries a record AND averages UFCalendar derives from the fighter's tracked UFC bouts only (Contender Series excluded, `W-L-D` plus ` (n NC)`; both null until a UFC bout is settled — a Contender-Series-only fighter has no UFC stats), while `bkfc-only` / `one-only` carry the promotion's own published record. A fighter whose records show no MMA career at all (a ONE Muay Thai or kickboxing athlete) carries the every-promotion averages on a `tracked` row (null record) instead of `pro-mma`, because those bouts are not MMA. ufcstats', OKTAGON's and ACA's header records are CAREER records and ship under `pro-mma` (the `public-records` row wins the scope when present, unless ufcstats counts more bouts).","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the fighter. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Career stat rows","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FighterStatsResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters/islam-makhachev/stats\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fighter_stats(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fighterStats(\"islam-makhachev\");"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fighters/{idOrSlug}/rankings":{"get":{"tags":["Fighters"],"summary":"Ranking history","description":"Official-board rows over time (`org`, `board` in the public vocabulary — `official` / `meta` — `division` slug, `snapshot_date`, `rank`, `is_champion`), newest snapshot first. Rank 0 = champion; a snapshot is valid until superseded. Cursor-paginated since 2026-09-24 (`limit` 1–500, default 100) — long careers exceed the old silent 500-row cap.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the fighter. Stale slugs 308-redirect to the canonical URL."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Ranking rows","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FighterRankingsResponse"},"example":{"data":[{"org":"ufc","board":"official","division":"heavyweight","snapshot_date":"2025-06-17","rank":0,"is_champion":true}],"meta":{"note":"rank 0 = champion; a snapshot is valid until superseded","pagination":{"next_cursor":"eyJpZCI6MTAwfQ","has_more":true,"limit":100}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"400":{"description":"Invalid input (`invalid_cursor`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters/islam-makhachev/rankings?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fighter_rankings(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fighterRankings(\"islam-makhachev\");"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/fighters/{idOrSlug}/power-index":{"get":{"tags":["Fighters"],"summary":"Power Index trajectory","description":"Per-bout rating history from the UFCalendar Power Index engine (rating before/after, model win probability, `outcome` 1 / 0 / 0.5 and its word twin `result`). The NEWEST 500 points, served oldest-first; `meta.truncated` is true when an older tail was dropped.","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or slug of the fighter. Stale slugs 308-redirect to the canonical URL."}],"responses":{"200":{"description":"Rating points","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FighterPowerIndexResponse"},"example":{"data":[{"fought_at":"2008-04-12","rating_pre":1500,"rating_post":1536,"win_prob":0.5535,"outcome":1,"result":"win","opponent_fighter_id":17571,"fight_id":null}],"meta":{"truncated":false}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/fighters/islam-makhachev/power-index\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.fighter_power_index(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.fighterPowerIndex(\"islam-makhachev\");"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/compare":{"get":{"tags":["Fighters"],"summary":"Compare two fighters","description":"The tale of the tape in one call. `a` and `b` are fighter slugs or ids (a renamed slug is followed and named in `meta.resolved`); both are required and must differ (400 `invalid_query`), and each must be on the roster (404 `not_found`). Returns both bios (the `/v1/fighters/{idOrSlug}` bio fields plus `age`), `career_stats` (the `/v1/fighters/{idOrSlug}/stats` rows), `aggregates` per fighter over every completed bout with per-fight totals (`fights_analyzed`, average and best significant strikes and takedowns, average control time in seconds, and the strike mix: `location_pct` head/body/leg and `position_pct` distance/clinch/ground, whole percents, null when nothing was logged), `recent_form` (the last five settled entries of the merged multi-promotion timeline, `/v1/fighters/{idOrSlug}/history` rows), `win_streak`, `head_to_head` (their previous meetings, from `a`'s side), `common_opponents` (up to 5: the shared opponent with each fighter's most recent bout against them), `booked_bout` (the upcoming or live bout between them in a covered promotion, in its stored corner order, or null), `prediction` (UFCalendar model win probability for that booked bout, oriented to `a` — UFC only, served only while its corner stamp matches the bout, else null) and `power_index` (each fighter's UFCalendar Power Index rating, peak and fights rated, and `win_probability_a` from the two ratings). Model output is information, not betting advice.","parameters":[{"name":"a","in":"query","required":true,"schema":{"type":"string"},"description":"First fighter: slug (preferred) or numeric id."},{"name":"b","in":"query","required":true,"schema":{"type":"string"},"description":"Second fighter: slug (preferred) or numeric id."}],"responses":{"200":{"description":"Side-by-side comparison","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareResponse"},"example":{"data":{"a":{"id":152,"slug":"islam-makhachev","name":"Islam Makhachev","nickname":null,"nationality":"Russia","country_code":"RU","second_nationality":null,"height_inches":70,"weight_lbs":170,"reach_inches":70,"stance":"Southpaw","dob":"1991-10-27","team":null,"birthplace":null,"age":34},"b":{"id":493,"slug":"charles-oliveira","name":"Charles Oliveira","nickname":"do Bronx","nationality":"Brazil","country_code":"BR","second_nationality":null,"height_inches":70,"weight_lbs":155,"reach_inches":74,"stance":"Orthodox","dob":"1989-10-17","team":null,"birthplace":null,"age":36},"career_stats":{"a":[],"b":[]},"aggregates":{"a":{"fights_analyzed":18,"avg_sig_strikes":26.94,"avg_takedowns":2.28,"avg_control_time_sec":338,"max_sig_strikes":88,"max_takedowns":5,"location_pct":{"head":71,"body":24,"leg":6},"position_pct":{"distance":57,"clinch":18,"ground":24}},"b":{"fights_analyzed":0,"avg_sig_strikes":null,"avg_takedowns":null,"avg_control_time_sec":null,"max_sig_strikes":null,"max_takedowns":null,"location_pct":null,"position_pct":null}},"recent_form":{"a":[],"b":[]},"win_streak":{"a":16,"b":1},"head_to_head":[{"fight_id":7034,"event":{"id":833,"slug":"ufc-280-2022-10-22","title":"UFC 280: Oliveira vs Makhachev","starts_at":"2022-10-22T14:30:00.000Z"},"weight_class":"Lightweight","is_title":true,"is_main":true,"opponent":{"id":493,"name":"Charles Oliveira","slug":"charles-oliveira"},"outcome":"win","winner_fighter_id":152,"method":"Submission","round":2,"time":"3:16"}],"common_opponents":[],"booked_bout":null,"prediction":null,"power_index":{"a":{"rating":1874,"peak":1874,"peak_at":"2025-11-15","fights_rated":18,"last_fought_at":"2025-11-15"},"b":{"rating":1702,"peak":1790,"peak_at":"2022-05-07","fights_rated":36,"last_fought_at":"2025-10-11"},"win_probability_a":0.7298}},"meta":{"note":"UFCalendar model output for information only, not betting advice. …"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_query`). `a` and `b` are both required and must differ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/compare?a=islam-makhachev&b=charles-oliveira\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.compare(\"islam-makhachev\", \"charles-oliveira\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.compare(\"islam-makhachev\", \"charles-oliveira\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"compare_fighters\",\n    \"arguments\": {\n      \"a\": \"islam-makhachev\",\n      \"b\": \"charles-oliveira\"\n    }\n  }\n}"}],"x-mcp-tool":"compare_fighters","x-mcp-tools":["compare_fighters"]}},"/v1/rankings/{org}":{"get":{"tags":["Rankings"],"summary":"Official board (point-in-time)","description":"**The time machine**: pass `?date=YYYY-MM-DD` for the board as it stood on any date (UFC official back to 2013, 543 snapshots). A snapshot is valid until superseded. Rank 0 = champion; P4P has no rank 0.\n\nEvery entry carries `movement` against the previous snapshot of the same board (previous rank minus current rank: positive moved up, 0 held, null when not on the previous board) and `is_new` (true when there was a previous snapshot and the fighter was not ranked in that division on it), plus `nationality` and `country_code` (ISO-3166 alpha-2). Fighters are matched by division + name, so a fighter moving divisions reads as new. `meta.previous_snapshot_date` / `meta.next_snapshot_date` name the neighbouring snapshots (null at either end) — pass one as `date` to step through history.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc"]}},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"A real calendar day; the snapshot in force on that date is returned."},{"name":"board","in":"query","required":false,"schema":{"$ref":"#/components/schemas/RankingsBoard"},"description":"Default `official` (for UFC that is the media-panel vote ufc.com publishes). UFC additionally has `meta`."}],"responses":{"200":{"description":"Board grouped by division","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RankingsBoardResponse"},"example":{"data":{"org":"ufc","board":"official","snapshot_date":"2016-11-07","divisions":[{"division":"lightweight","entries":[{"rank":0,"is_champion":true,"fighter_id":1270,"fighter_slug":"eddie-alvarez","name":"Eddie Alvarez","nationality":"United States","country_code":"US","fighter":{"id":1270,"slug":"eddie-alvarez","name":"Eddie Alvarez"},"movement":0,"is_new":false},{"rank":1,"is_champion":false,"fighter_id":1257,"fighter_slug":"tony-ferguson","name":"Tony Ferguson","nationality":"United States","country_code":"US","fighter":{"id":1257,"slug":"tony-ferguson","name":"Tony Ferguson"},"movement":2,"is_new":false},{"rank":2,"is_champion":false,"fighter_id":1313,"fighter_slug":"khabib-nurmagomedov","name":"Khabib Nurmagomedov","nationality":"Russia","country_code":"RU","fighter":{"id":1313,"slug":"khabib-nurmagomedov","name":"Khabib Nurmagomedov"},"movement":-1,"is_new":false}]}]},"meta":{"previous_snapshot_date":"2016-10-12","next_snapshot_date":"2016-11-16"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_date`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/rankings/ufc?date=2016-11-14\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.rankings(\"ufc\", date=\"2016-11-14\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.rankings(\"ufc\", { date: \"2016-11-14\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_rankings\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"division\": \"lightweight\",\n      \"date\": \"2016-11-14\"\n    }\n  }\n}"}],"x-mcp-tool":"get_rankings","x-mcp-tools":["get_rankings"]}},"/v1/rankings/{org}/{division}":{"get":{"tags":["Rankings"],"summary":"One division","description":"Same as the board endpoint, filtered to a division (`lightweight`, `womens-strawweight`, `pound-for-pound`, …) — entries carry the same `movement` / `is_new` / `nationality` / `country_code`, and `meta` the neighbouring snapshot dates.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"division","in":"path","required":true,"schema":{"type":"string"}},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"A real calendar day."},{"name":"board","in":"query","required":false,"schema":{"$ref":"#/components/schemas/RankingsBoard"},"description":"Default `official`; UFC additionally has `meta`."}],"responses":{"200":{"description":"Division entries","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DivisionRankingsResponse"},"example":{"data":{"org":"ufc","board":"official","snapshot_date":"2026-09-22","division":"lightweight","entries":[{"rank":0,"is_champion":true,"fighter_id":100,"fighter_slug":"justin-gaethje","name":"Justin Gaethje","nationality":"United States","country_code":"US","fighter":{"id":100,"slug":"justin-gaethje","name":"Justin Gaethje"},"movement":0,"is_new":false}]},"meta":{"previous_snapshot_date":"2026-09-15","next_snapshot_date":null}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_date`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/rankings/ufc/lightweight?date=2016-11-14\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.division_rankings(\"ufc\", \"lightweight\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.divisionRankings(\"ufc\", \"lightweight\");"}],"x-mcp-tool":null,"x-mcp-tools":[]}},"/v1/champions":{"get":{"tags":["Rankings"],"summary":"Current champions","description":"Rank-0 rows of each launch org's latest official board, with the champion's `nationality` and `country_code` (ISO-3166 alpha-2). `org=` narrows to one promotion and `division=` to one weight class; an unknown value 400s (`invalid_org` / `invalid_division`) rather than widening the answer.","parameters":[{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Staged orgs 400 until promoted.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"division","in":"query","required":false,"schema":{"type":"string"},"description":"Division slug as the boards carry it (`lightweight`, `womens-strawweight`, BKFC `cruiserweight`, …) or its display form. A division with a vacant title returns an empty list; one no board in scope carries 400s `invalid_division` listing the available ones."}],"responses":{"200":{"description":"Champions","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChampionsResponse"},"example":{"data":[{"org":"ufc","division":"bantamweight","snapshot_date":"2026-07-15","rank":0,"is_champion":true,"fighter_id":2098,"fighter_slug":"petr-yan-3","name":"Petr Yan","nationality":"Russia","country_code":"RU","fighter":{"id":2098,"slug":"petr-yan-3","name":"Petr Yan"}}],"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_division`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/champions?org=ufc\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.champions(org=\"ufc\", division=\"lightweight\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.champions({ org: \"ufc\", division: \"lightweight\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_champions\",\n    \"arguments\": {\n      \"org\": \"ufc\"\n    }\n  }\n}"}],"x-mcp-tool":"get_champions","x-mcp-tools":["get_champions"]}},"/v1/power-index/{org}":{"get":{"tags":["Power Index"],"summary":"Power Index board","description":"The UFCalendar Power Index (our own rating engine, hourly refresh) for one org, in three views:\n\n- `current` (default): top-rated fighters whose latest bout was in this org.\n- `peaks`: the highest ratings ever reached, keyed on the org where the peak was set.\n- `movers`: the biggest rating change over the last `days` (default 365), among fighters with at least two bouts in the window and five rated overall, whose latest bout in the window was in this org. Rows carry `start_rating`, `delta` and `fights_in_window` instead of peak fields.\n\nEvery row carries `division` (slug from the fighter's latest bout, `null` for a catchweight). `division=` narrows any view; the filter runs before `limit`. Unknown `view` 400s `invalid_view`, unknown `division` 400s `invalid_division`.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["current","movers","peaks"],"default":"current"}},{"name":"division","in":"query","required":false,"schema":{"type":"string"},"description":"Division slug, e.g. `lightweight`, `light-heavyweight`, `womens-strawweight`."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":30,"maximum":3650,"default":365},"description":"Window for `view=movers`, default 365; days is snapped to 30/90/180/365/730/1825/3650 (the nearest one), and `meta.days` reports the window actually used."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50}}],"responses":{"200":{"description":"Board rows","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerIndexBoardResponse"},"example":{"data":[{"position":1,"fighter":{"id":152,"slug":"islam-makhachev","name":"Islam Makhachev","nationality":"Russia","country_code":"RU"},"rating":1874,"start_rating":1831,"delta":43,"fights_in_window":2,"division":"welterweight"}],"meta":{"org":"ufc","view":"movers","division":null,"days":365,"note":"UFCalendar Power Index — our own rating engine, hourly refresh. Movers = biggest rating change over the last 365 days, among fighters with at least two bouts in the window and five rated overall, whose latest bout in the window was in this org."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_view`, `invalid_division`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/power-index/ufc?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.power_index(\"ufc\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.powerIndex(\"ufc\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_power_index\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"limit\": 10\n    }\n  }\n}"}],"x-mcp-tool":"get_power_index","x-mcp-tools":["get_power_index"]}},"/v1/matchmaker/{org}":{"get":{"tags":["Matchmaker"],"summary":"Matchmaker board","description":"UFCalendar's matchmaker for one MMA promotion (`ufc`, `pfl`, `oktagon`, `rizin`; `bkfc` 400s `unsupported_org` — the engine runs on the Power Index, which rates MMA only). Every candidate pair inside a division is scored 0–100 for rank proximity, momentum, competitiveness, readiness and story (rematches, trilogy deciders, eliminators): the promotion's official ladder where one exists plus the strongest active unranked Power Index fighters. UFC pairs are scored by UFCalendar's booking model (a ranker trained on every realized UFC booking), weighted by the stakes term; other promotions use the fitted heuristic. Fighters already booked leave the board, pairs already booked are excluded, and one fighter appears in at most two slips per division.\n\nWithout `division` the list is the cross-division top board (at most two slips per division); with it, that division's best pairs. `meta.divisions` lists the promotion's divisions (an unknown one 400s `invalid_division`), `meta.rankings_date` the ladder snapshot used (null when the promotion has no current ladder). Each slip: `key` (`lo-hi` fighter ids), `a` (red corner — the better-credentialed side) and `b` with `rank` (0 = champion, null = unranked), `power_index`, `streak` (signed: +3 = three straight wins) and `booked`; `score`; `win_probability_a` from the two Power Index ratings; `tags` (`title`, `eliminator`, `coinFlip`, `bothStreaking`, `finishers`, `trilogyDecider`, `unfinishedBusiness`, `rematch`, `unrankedGem`, `bounceBack`, `steppingUp`, `bothDue`, `booked`).\n\nComputed WITHOUT the website's style-clash (Fight DNA) factor, so scores can differ slightly from ufcalendar.com. A ranking of fights worth making, not a report of bookings; probabilities are model output for information only. Recomputed at most every 10 minutes.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","enum":["ufc","pfl","oktagon","rizin"]}},{"name":"division","in":"query","required":false,"schema":{"type":"string"},"description":"One division slug from `meta.divisions`, e.g. `lightweight`, `womens-strawweight`. Omit for the cross-division board."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":24,"default":10}}],"responses":{"200":{"description":"Matchups, best first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchmakerBoardResponse"},"example":{"data":[{"key":"152-1257","division":"lightweight","a":{"id":152,"slug":"islam-makhachev","name":"Islam Makhachev","nationality":"Russia","rank":0,"power_index":1874,"streak":16,"booked":false},"b":{"id":1257,"slug":"arman-tsarukyan","name":"Arman Tsarukyan","nationality":"Armenia","rank":1,"power_index":1790,"streak":4,"booked":false},"score":91,"win_probability_a":0.6184,"tags":[{"kind":"title"},{"kind":"bothStreaking","a":16,"b":4},{"kind":"bothDue"}]}],"meta":{"org":"ufc","division":"lightweight","rankings_date":"2026-09-16","divisions":["flyweight","bantamweight","featherweight","lightweight"],"note":"UFCalendar matchmaker output — a ranking of fights worth making, not a report of bookings; computed without the site's style-clash (Fight DNA) factor, so scores can differ slightly from ufcalendar.com. Probabilities are model output for information only."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`unsupported_org`, `invalid_division`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/matchmaker/ufc?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.matchmaker(\"ufc\", division=\"lightweight\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.matchmaker(\"ufc\", { division: \"lightweight\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_matchmaker\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"division\": \"lightweight\",\n      \"limit\": 5\n    }\n  }\n}"}],"x-mcp-tool":"get_matchmaker","x-mcp-tools":["get_matchmaker"]}},"/v1/matchmaker/next/{fighter}":{"get":{"tags":["Matchmaker"],"summary":"Who should this fighter fight next","description":"One fighter's most sensible next opponents by UFCalendar's matchmaker: the same engine and candidate pool as the board (their division's ladder plus the promotion's active Power Index fighters), every pairing scored, best first. The promotion and division come from the fighter's most recent bouts in a covered MMA promotion (404 `not_found` when there is none, or the division has no pool); a renamed slug 308-redirects. The fighter is scored as free even when booked — the question is who comes after that — and `booked_next` names the bout already booked (opponent + event), or null. Opponents already booked against them are left out.\n\n`subject` carries the corner fields plus `days_since_last`; each suggestion has `opponent`, `win_probability_subject` (from the two Power Index ratings), `score` (0–100) and `tags` (same vocabulary as the board). Computed WITHOUT the website's style-clash (Fight DNA) factor, so scores can differ slightly from ufcalendar.com; probabilities are model output for information only.","parameters":[{"name":"fighter","in":"path","required":true,"schema":{"type":"string"},"description":"Fighter slug (preferred) or numeric id."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":10,"default":5}}],"responses":{"200":{"description":"Suggested next opponents","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhosNextResponse"},"example":{"data":{"subject":{"id":152,"slug":"islam-makhachev","name":"Islam Makhachev","nationality":"Russia","rank":0,"power_index":1874,"streak":16,"booked":false,"days_since_last":180},"org":"ufc","division":"welterweight","suggestions":[{"opponent":{"id":2071,"slug":"jack-della-maddalena","name":"Jack Della Maddalena","nationality":"Australia","rank":1,"power_index":1781,"streak":-1,"booked":false},"win_probability_subject":0.6285,"score":88,"tags":[{"kind":"title"}]}],"booked_next":null,"rankings_date":"2026-09-16"},"meta":{"note":"UFCalendar matchmaker output — a ranking of fights worth making, not a report of bookings; computed without the site's style-clash (Fight DNA) factor, so scores can differ slightly from ufcalendar.com. Probabilities are model output for information only."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"308":{"description":"The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.","headers":{"Location":{"description":"Canonical `/v1/...` path.","schema":{"type":"string"}}}},"400":{"description":"Invalid input (`invalid_query`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/matchmaker/next/islam-makhachev?limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.whos_next(\"islam-makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.whosNext(\"islam-makhachev\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"whos_next\",\n    \"arguments\": {\n      \"fighter\": \"islam-makhachev\"\n    }\n  }\n}"}],"x-mcp-tool":"whos_next","x-mcp-tools":["whos_next"]}},"/v1/stats/leaders":{"get":{"tags":["Stats"],"summary":"One stat leaderboard","description":"One board from UFCalendar's Record Book rollup (rebuilt daily) for ONE promotion — `org` is required; there is no cross-promotion board on the API. `metric` picks the board; its `scope` decides what a row is: `career` rows are fighters, `single_fight` and `round` rows are PERFORMANCES (one fighter can hold several; `fight` names the bout and opponent, `round_number` the round), `event` rows are CARDS (`event`, no fighter), `division` rows are WEIGHT CLASSES (`division`, no fighter). `value` is in `meta.metric.unit` (`rate` is a 0–1 fraction; `seconds`, `per_minute`, `per_15_minutes` as named); `value_secondary` is the denominator or context named by `meta.metric.secondary` (e.g. attempts behind an accuracy, the round of a fastest finish); `sample_n` is the bouts (or fighters) behind the value. `direction` is the ranking order, not a verdict. `rank` is the rollup's own position; equal values are a tie — `display_rank` and `tied` say so. Narrow with `division`, `country` (ISO-2, fighters of that nationality; population `all` only — combining it with `population=active` 400s `invalid_filter`) or `population=active` (a bout in the last ~18 months). Boards need a minimum sample, so a narrow slice can 404. Errors: `invalid_org`, `invalid_metric`, `invalid_division`, `invalid_country`, `invalid_population`, `invalid_filter`.","parameters":[{"name":"org","in":"query","required":true,"description":"Launch org slug (required): `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"metric","in":"query","required":true,"schema":{"type":"string","enum":["total_fights","wins","decision_wins","title_fight_wins","bonuses","finishes","win_streak","total_fight_seconds","avg_fight_seconds_short","avg_fight_seconds_long","control_time_sec","control_time_pct","sig_strikes_landed","total_strikes_landed","slpm","sapm","striking_differential","sig_strike_accuracy","sig_strike_defense","knockdowns","knockdowns_per_15","knockouts","takedowns_landed","td_avg","takedown_accuracy","takedown_defense","submission_attempts","sub_avg_per_15","submissions","fastest_finish","fastest_knockout","fastest_submission","longest_fight_seconds","most_sig_strikes_fight","most_takedowns_fight","most_knockdowns_fight","longest_control_fight","most_sig_strikes_round","most_takedowns_round","most_knockdowns_round","most_finishes_event","most_knockouts_event","shortest_card_seconds","finish_rate","ko_rate","sub_rate","decision_rate","avg_fight_seconds"]},"description":"Board metric slug."},{"name":"division","in":"query","required":false,"schema":{"type":"string","enum":["strawweight","flyweight","bantamweight","featherweight","lightweight","welterweight","super-welterweight","middleweight","light-heavyweight","heavyweight","super-heavyweight","womens-strawweight","womens-flyweight","womens-bantamweight","womens-featherweight","atomweight","ironweight"]},"description":"One weight class."},{"name":"population","in":"query","required":false,"schema":{"type":"string","enum":["all","active"],"default":"all"},"description":"`active` = fighters with a bout in the last ~18 months."},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z]{2}$"},"description":"ISO-3166 alpha-2 nationality; population `all` only."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Board rows, best first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"},"example":{"data":[{"rank":1,"value":28,"value_secondary":null,"sample_n":46,"fighter":{"id":17,"slug":"jim-miller","name":"Jim Miller","nationality":"United States"},"division":null,"round_number":null,"fight":null,"event":null,"display_rank":1,"tied":false},{"rank":2,"value":25,"value_secondary":null,"sample_n":36,"fighter":{"id":2215,"slug":"charles-oliveira","name":"Charles Oliveira","nationality":"Brazil"},"division":null,"round_number":null,"fight":null,"event":null,"display_rank":2,"tied":false}],"meta":{"org":"ufc","metric":{"slug":"wins","scope":"career","category":"fights","direction":"desc","unit":"count","has_secondary":false,"secondary":null},"division":null,"population":"all","country":null,"computed_at":"2026-09-24T04:12:00.000Z"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_metric`, `invalid_division`, `invalid_population`, `invalid_country`, `invalid_filter`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/stats/leaders?org=ufc&metric=wins&country=DE&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.leaderboard(\"ufc\", \"wins\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.leaderboard(\"ufc\", \"wins\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_leaderboard\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"metric\": \"wins\"\n    }\n  }\n}"}],"x-mcp-tool":"get_leaderboard","x-mcp-tools":["get_leaderboard"]}},"/v1/stats/record-book":{"get":{"tags":["Stats"],"summary":"The Record Book","description":"Every leaderboard's top rows for ONE promotion in one call — `org` is required — grouped by category (`fights`, `time`, `striking`, `grappling`, `records`): `data` is `[{ category, boards: [{ metric, rows }] }]`, rows exactly as on `/v1/stats/leaders`. `top` rows per board (default 10, max 25). Same `division` / `country` / `population` narrowing as `/v1/stats/leaders`, plus `scope` for one kind of board (`career`, `single_fight`, `round`, `division`, `event`). A board appears only when it has at least 3 rows (or `top`, if smaller); inside one `division`, the division-ranking boards are left out. An empty slice returns `[]` with `meta.note`.","parameters":[{"name":"org","in":"query","required":true,"description":"Launch org slug (required): `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}},{"name":"division","in":"query","required":false,"schema":{"type":"string","enum":["strawweight","flyweight","bantamweight","featherweight","lightweight","welterweight","super-welterweight","middleweight","light-heavyweight","heavyweight","super-heavyweight","womens-strawweight","womens-flyweight","womens-bantamweight","womens-featherweight","atomweight","ironweight"]},"description":"One weight class."},{"name":"population","in":"query","required":false,"schema":{"type":"string","enum":["all","active"],"default":"all"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z]{2}$"},"description":"ISO-3166 alpha-2 nationality; population `all` only."},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["career","single_fight","round","division","event"]},"description":"One kind of board."},{"name":"top","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":25,"default":10},"description":"Rows per board."}],"responses":{"200":{"description":"Boards grouped by category","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordBookResponse"},"example":{"data":[{"category":"records","boards":[{"metric":{"slug":"fastest_knockout","scope":"single_fight","category":"records","direction":"asc","unit":"seconds","has_secondary":true,"secondary":{"unit":"count","label":"round"}},"rows":[{"rank":1,"value":5,"value_secondary":1,"sample_n":1,"fighter":{"id":2329,"slug":"jorge-masvidal","name":"Jorge Masvidal","nationality":"United States"},"division":null,"round_number":null,"fight":{"id":6511,"event":{"id":733,"slug":"ufc-239-2019-07-06","title":"UFC 239: Jones vs Santos","starts_at":"2019-07-07T02:00:00.000Z"},"opponent":{"id":3000,"slug":"ben-askren","name":"Ben Askren"}},"event":null,"display_rank":1,"tied":false}]}]}],"meta":{"org":"ufc","division":null,"population":"all","country":null,"scope":"single_fight","top":1,"computed_at":"2026-09-24T04:12:00.000Z","note":"Single-fight and round boards rank performances, not fighters; event boards rank cards; division boards rank weight classes. A board needs at least 3 rows (or top, if smaller) to appear."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`, `invalid_scope`, `invalid_division`, `invalid_population`, `invalid_country`, `invalid_filter`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/stats/record-book?org=ufc&country=DE\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.record_book(\"ufc\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.recordBook(\"ufc\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_record_book\",\n    \"arguments\": {\n      \"org\": \"ufc\"\n    }\n  }\n}"}],"x-mcp-tool":"get_record_book","x-mcp-tools":["get_record_book"]}},"/v1/stats/years/{year}":{"get":{"tags":["Stats"],"summary":"A year in review","description":"One calendar year (UTC) of one promotion — or, without `org`, of every covered promotion together (never a promotion the API does not cover) — in numbers, over completed bouts of non-cancelled events: `events_completed`, `title_fights`, `methods` (`ko`, `sub`, `dec`, `other`, `total`), `divisions` (weight classes with 10+ bouts, highest finish rate first, up to 14), `fastest_finishes` (up to 8 round-1 KO/TKO/submissions, `seconds` and `time`, winner and loser), `upsets` (up to 8 wins with the lowest pre-fight UFCalendar Power Index probability, `win_probability`), `climbers` (up to 8 fighters with the biggest Power Index gain over the year, `gain` in rating points), `busiest` (up to 8 fighters by bouts, with wins), `orgs` (events and completed bouts per promotion), `countries` (host countries by events, up to 12) and `judges` (the 5 judges on the most commission-scored bouts). `orgs_scope` names the promotions counted. `year` runs from 1993 to the current year; anything else 404s. Unknown `org` 400s `invalid_org`. Refreshed every 10 minutes.","parameters":[{"name":"year","in":"path","required":true,"schema":{"type":"integer","minimum":1993},"description":"Calendar year, 1993 to the current year."},{"name":"org","in":"query","required":false,"description":"Launch org slug: `ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`. Omit for every covered promotion together.","schema":{"type":"string","enum":["ufc","pfl","oktagon","bkfc","rizin"]}}],"responses":{"200":{"description":"The year in numbers","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YearStatsResponse"},"example":{"data":{"year":2025,"orgs_scope":["ufc"],"events_completed":47,"title_fights":27,"methods":{"ko":226,"sub":118,"dec":334,"other":3,"total":681},"divisions":[{"weight_class":"Welterweight","fights":68,"ko":31,"sub":13}],"fastest_finishes":[{"fight_id":586,"seconds":16,"time":"0:16","method":"KO/TKO","event":{"slug":"ufc-322-2025-11-15","title":"UFC 322: Della Maddalena vs Makhachev","starts_at":"2025-11-15T23:00:00.000Z"},"winner":{"id":415,"name":"Benoît Saint Denis","slug":"benoit-saint-denis"},"loser":{"id":497,"name":"Beneil Dariush","slug":"beneil-dariush"}}],"upsets":[{"fight_id":200,"win_probability":0.204,"winner":{"id":263,"name":"Magomed Ankalaev","slug":"magomed-ankalaev"},"opponent":{"id":101,"name":"Alex Pereira","slug":"alex-pereira"},"event":{"slug":"ufc-313-2025-03-08","title":"UFC 313: Pereira vs Ankalaev","starts_at":"2025-03-08T23:30:00.000Z"}}],"climbers":[{"fighter":{"id":154,"name":"Merab Dvalishvili","slug":"merab-dvalishvili"},"fights":4,"gain":111}],"busiest":[{"fighter":{"id":3,"name":"Joshua Van","slug":"joshua-van"},"fights":5,"wins":5}],"orgs":[{"slug":"ufc","name":"UFC","events":47,"fights":681}],"countries":[{"country":"United States","events":30}],"judges":[{"judge_id":24,"name":"Sal D'Amato","fights":7}]},"meta":{"org":"ufc","note":"Completed bouts of non-cancelled events, UTC calendar year. …"}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_org`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/stats/years/2025?org=ufc\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.year_stats(2025, org=\"ufc\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.yearStats(2025, { org: \"ufc\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_year_stats\",\n    \"arguments\": {\n      \"year\": 2025,\n      \"org\": \"ufc\"\n    }\n  }\n}"}],"x-mcp-tool":"get_year_stats","x-mcp-tools":["get_year_stats"]}},"/v1/predictions/upcoming":{"get":{"tags":["Predictions"],"summary":"Model win probabilities (UFC)","description":"UFCalendar model win probabilities for upcoming UFC bouts, published about three weeks ahead of each card and repriced at least weekly. Corner-guarded: a probability is only served while the stored pair matches the bout's current pair — a late opponent swap removes the row and it returns repriced within 30 minutes, rather than mislabeling it. Pass `event=` to narrow to one card (`meta.event` then names it; an unknown event 404s). Not betting advice.","parameters":[{"name":"event","in":"query","required":false,"schema":{"type":"string"},"description":"Event slug or numeric id. Stale slugs are followed."}],"responses":{"200":{"description":"Predictions","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictionsResponse"}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/predictions/upcoming\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.predictions_upcoming()"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.predictionsUpcoming();"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_predictions_upcoming\",\n    \"arguments\": {}\n  }\n}"}],"x-mcp-tool":"get_predictions_upcoming","x-mcp-tools":["get_predictions_upcoming"]}},"/v1/broadcast-rights/{org}":{"get":{"tags":["Broadcast"],"summary":"Who airs it, per country","description":"Org-level standing media rights per country (PFL harvested weekly across 212 countries; UFC ~110 curated). `WORLD` rows apply globally. Without `series` you get the org-wide deals only; UFC sub-series (`dwcs` = Dana White's Contender Series, `rtufc` = Road to UFC) have their OWN grid, which REPLACES the org-wide one for those cards — pass `series=` to read it. Each row carries `series` (`null` for org-wide). For one event, `/v1/events/{idOrSlug}/watch` picks the right grid for you and overlays the event's own listings. An unknown `series` 400s `invalid_series`.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"ISO-2 country code."},{"name":"series","in":"query","required":false,"schema":{"type":"string","enum":["dwcs","rtufc"]},"description":"A sub-series grid instead of the org-wide deals: `dwcs` or `rtufc` (UFC)."}],"responses":{"200":{"description":"Rights rows","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastRightsResponse"},"example":{"data":[{"country":"DE","provider":"DAZN","kind":"sub","url":"https://www.dazn.com","rank":0,"series":null}],"meta":{"org":"ufc","series":null}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_series`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/broadcast-rights/ufc?country=DE\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.broadcast_rights(\"ufc\", country=\"DE\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.broadcastRights(\"ufc\", { country: \"DE\" });"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_broadcast_rights\",\n    \"arguments\": {\n      \"org\": \"ufc\",\n      \"country\": \"DE\"\n    }\n  }\n}"}],"x-mcp-tool":"get_broadcast_rights","x-mcp-tools":["get_broadcast_rights"]}},"/v1/venues":{"get":{"tags":["Events"],"summary":"Search venues","description":"Arenas and venues that have hosted (or have booked) a launch-org event, alphabetical. `q` (at least 2 characters) matches the name or the city, accent-insensitive; `country` takes an ISO-2 code (`US`) or an English country name (`Brazil`). Each row is `id`, `slug`, `name`, `city`, `region`, `country`, `tz`, `capacity` — pass the `id` to `/v1/venues/{id}/events` for what was fought there. A `q` under 2 characters 400s `invalid_query`.","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","minLength":2},"description":"Venue name or city fragment."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"ISO-2 code or English country name."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Venues, alphabetical","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VenuesPageResponse"},"example":{"data":[{"id":5,"slug":"t-mobile-arena-las-vegas","name":"T-Mobile Arena","city":"Las Vegas","region":"Nevada","country":"United States","tz":"America/Los_Angeles","capacity":20000}],"meta":{"pagination":{"next_cursor":null,"has_more":false}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_query`, `invalid_country`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/venues?q=T-Mobile&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.venues(q=\"T-Mobile\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.venues({ q: \"T-Mobile\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"search_venues\",\n    \"arguments\": {\n      \"q\": \"T-Mobile\"\n    }\n  }\n}"}],"x-mcp-tool":"search_venues","x-mcp-tools":["search_venues"]}},"/v1/venues/{id}/events":{"get":{"tags":["Events"],"summary":"Events at a venue","description":"Every launch-org event held (or booked) at one venue, newest first — upcoming cards on top, then the history. Same filters and row shape as `/v1/events` (`status`, `from`, `to`, `order`, cursor pagination); `order=asc` reverses it. `meta.venue` names the venue. An unknown venue, or one with no covered event at this venue (a staged-org-only arena), 404s `not_found`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/EventStatusFilter"},"description":"Same values as `/v1/events`; `upcoming` = the venue's cards not yet over."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Events at the venue","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VenueEventsResponse"},"example":{"data":[{"id":5,"slug":"ufc-329-2026-07-11","title":"UFC 329: McGregor vs Holloway 2","short_title":"329","numbering":"329","org":"ufc","sport":"mma","starts_at":"2026-07-11T21:00:00.000Z","main_card_at":"2026-07-12T01:00:00.000Z","prelims_at":"2026-07-11T23:00:00.000Z","early_prelims_at":"2026-07-11T21:00:00.000Z","tz":"America/Los_Angeles","status":"completed","is_ppv":true,"is_title_card":false}],"meta":{"pagination":{"next_cursor":"eyJpZCI6NX0","has_more":true,"limit":25},"venue":{"id":5,"slug":"t-mobile-arena-las-vegas","name":"T-Mobile Arena","city":"Las Vegas","region":"Nevada","country":"United States","tz":"America/Los_Angeles","capacity":20000}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_status`, `invalid_date`, `invalid_order`, `invalid_cursor`). Dates must be real calendar days (`2026-02-30` is `invalid_date`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/venues/24/events?status=completed&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.venue_events(24):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.venueEvents(24)) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_venue_events\",\n    \"arguments\": {\n      \"venue_id\": \"24\"\n    }\n  }\n}"}],"x-mcp-tool":"get_venue_events","x-mcp-tools":["get_venue_events"]}},"/v1/venues/{id}":{"get":{"tags":["Events"],"summary":"Venue","description":"Venue with city, region, country (+ `country_code`), coordinates, capacity and IANA tz.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Venue","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VenueResponse"},"example":{"data":{"id":7,"slug":"meta-apex-las-vegas","name":"Meta Apex","city":"Las Vegas","region":"Nevada","country":"United States","country_code":"US","lat":null,"lng":null,"capacity":null,"tz":"America/Los_Angeles"},"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/venues/24\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.venue(24)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.venue(24);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_venue\",\n    \"arguments\": {\n      \"venue_id\": \"24\"\n    }\n  }\n}"}],"x-mcp-tool":"get_venue","x-mcp-tools":["get_venue"]}},"/v1/articles":{"get":{"tags":["Articles"],"summary":"Search UFCalendar articles","description":"UFCalendar's own editorial archive — previews, recaps, investigations, fighter-pay and technique pieces — newest first. `q` (at least 2 characters) matches the title, summary or a tag, accent-insensitive (and the translated title and summary when `locale` is set); `tag` is an exact tag match; `locale` is one of the 13 site languages (`en` default, `es`, `pt`, `de`, `fr`, `tr`, `ru`, `ka`, `ja`, `ko`, `pl`, `sr`, `zh`) — a row serves its translation when one exists and English otherwise, and its `locale` names the language actually served. Each row: `slug`, `url` (the canonical page in the requested language), `title`, `description`, `author_name`, `tags`, `published_at`, `locale`. Pass the `slug` to `/v1/articles/{slug}` for the body. A `q` under 2 characters 400s `invalid_query`; an unknown `locale` 400s `invalid_locale`. Betting-advice editorial (picks, parlays) is not served. Link back when quoting.","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","minLength":2},"description":"Keyword: matches title, summary or a tag."},{"name":"tag","in":"query","required":false,"schema":{"type":"string"},"description":"Exact tag."},{"name":"locale","in":"query","required":false,"schema":{"type":"string","enum":["en","es","pt","de","fr","tr","ru","ka","ja","ko","pl","sr","zh"],"default":"en"},"description":"Site language to serve."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from `meta.pagination.next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Articles, newest first","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticlesPageResponse"},"example":{"data":[{"slug":"noche-ufc-payouts-bonuses-jean-silva","url":"https://www.ufcalendar.com/blog/noche-ufc-payouts-bonuses-jean-silva","title":"Noche UFC payouts: who made what","description":"Estimated purses and bonuses for every fighter on the card.","author_name":"Mate Bersenadze","tags":["ufc","payouts"],"published_at":"2026-09-14T09:00:00.000Z","locale":"en"}],"meta":{"locale":"en","note":"Editorial content by UFCalendar; link back when quoting.","pagination":{"next_cursor":"eyJpZCI6NDF9","has_more":true}}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_query`, `invalid_locale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/articles?q=title%20fight&limit=3\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nfor row in api.articles(q=\"title fight\"):\n    print(row)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nfor await (const row of api.articles({ q: \"title fight\" })) {\n  console.log(row);\n}"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"search_articles\",\n    \"arguments\": {\n      \"q\": \"title fight\"\n    }\n  }\n}"}],"x-mcp-tool":"search_articles","x-mcp-tools":["search_articles"]}},"/v1/articles/{slug}":{"get":{"tags":["Articles"],"summary":"Get an article","description":"One published UFCalendar article by slug: `title`, `description`, `author_name`, `author_slug`, `tags`, `published_at`, `url` and the full `body_md` (Markdown; the site's client-only widgets — fighter cards, embeds and offer blocks — are removed). No cover image is served: its license credit has no place in this payload. `locale` is the language requested and `served_locale` the one delivered: the translation when one exists, English otherwise. An unknown slug (or a draft) 404s; betting-advice editorial (picks, parlays) is not served, so such a slug 404s too; an unknown `locale` 400s `invalid_locale`. Link back when quoting.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Article slug, from `/v1/articles`."},{"name":"locale","in":"query","required":false,"schema":{"type":"string","enum":["en","es","pt","de","fr","tr","ru","ka","ja","ko","pl","sr","zh"],"default":"en"},"description":"Site language to serve."}],"responses":{"200":{"description":"Article","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleResponse"},"example":{"data":{"slug":"noche-ufc-payouts-bonuses-jean-silva","url":"https://www.ufcalendar.com/blog/noche-ufc-payouts-bonuses-jean-silva","title":"Noche UFC payouts: who made what","description":"Estimated purses and bonuses for every fighter on the card.","author_name":"Mate Bersenadze","author_slug":null,"tags":["ufc","payouts"],"published_at":"2026-09-14T09:00:00.000Z","body_md":"## The card\n\n…","locale":"en","served_locale":"en"},"meta":{"note":"Editorial content by UFCalendar; link back when quoting."}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_locale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/articles/noche-ufc-payouts-bonuses-jean-silva\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.article(\"noche-ufc-payouts-bonuses-jean-silva\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.article(\"noche-ufc-payouts-bonuses-jean-silva\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_article\",\n    \"arguments\": {\n      \"slug\": \"noche-ufc-payouts-bonuses-jean-silva\"\n    }\n  }\n}"}],"x-mcp-tool":"get_article","x-mcp-tools":["get_article"]}},"/v1/search":{"get":{"tags":["Search"],"summary":"Typeahead search","description":"Accent-insensitive search across roster fighters and events (up to 8 of each). Great for building pickers.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2}}],"responses":{"200":{"description":"Matches","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"},"example":{"data":{"fighters":[{"id":1665,"slug":"jon-jones","name":"Jon Jones","nickname":"Bones","nationality":"United States","country_code":"US"}],"events":[{"id":719,"slug":"ufc-309-2024-11-16","title":"UFC 309: Jones vs Miocic","org":"ufc","starts_at":"2024-11-17T03:00:00.000Z"}]},"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"400":{"description":"Invalid input (`invalid_query`). `q` must be at least 2 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/search?q=makhachev\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.search(\"makhachev\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.search(\"makhachev\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"search\",\n    \"arguments\": {\n      \"q\": \"makhachev\"\n    }\n  }\n}"}],"x-mcp-tool":"search","x-mcp-tools":["search"]}},"/v1/calendar/{org}.ics":{"get":{"tags":["Events"],"summary":"ICS calendar feed","description":"Subscribe your calendar app to an org's schedule. Calendar apps can't send headers, so pass the key as `?key=`. Refresh hourly at most. Three shapes: `{org}.ics` is one entry per event (first bell to the estimated last bout, full card and results in the description); `{org}-sections.ics` splits each card into early prelims, prelims and main card at their declared start times; `{org}-fights.ics` has one TENTATIVE entry per bout at its estimated start, linking the bout page. No betting odds.","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"},"description":"`ufc`, `pfl`, `oktagon`, `bkfc` or `rizin`; append `-sections` or `-fights` for the per-section or per-bout shape (e.g. `ufc-fights.ics`)"},{"name":"key","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"text/calendar VEVENT feed of upcoming events (or their card sections / bouts)","content":{"text/calendar":{"schema":{"type":"string"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/calendar/ufc.ics?key=$UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\nurl = api.calendar_ics_url(\"ufc\")"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst url = api.calendarIcsUrl(\"ufc\");"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_calendar_feed_url\",\n    \"arguments\": {\n      \"org\": \"ufc\"\n    }\n  }\n}"}],"x-mcp-tool":"get_calendar_feed_url","x-mcp-tools":["get_calendar_feed_url"]}},"/v1/webhook-endpoints":{"get":{"tags":["Account"],"summary":"List your webhook endpoints","description":"Pro and above. Counts as one request against your quota; the deliveries themselves do not.","parameters":[],"responses":{"200":{"description":"Endpoints","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointsResponse"},"example":{"data":[{"id":12,"url":"https://example.com/ufcalendar","events":["fight.result","card.changed"],"active":true,"failure_count":0,"created_at":"2026-09-01T12:00:00.000Z"}],"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Requires Pro or above (`tier_required`), or a plan bought directly rather than through RapidAPI (`direct_plan_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/webhook-endpoints\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.webhook_endpoints()"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.webhookEndpoints();"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"list_webhook_endpoints\",\n    \"arguments\": {}\n  }\n}"}],"x-mcp-tool":"list_webhook_endpoints","x-mcp-tools":["list_webhook_endpoints"]},"post":{"tags":["Account"],"summary":"Register a webhook endpoint","description":"Pro+. Body: `{\"url\": \"https://...\", \"events\": [\"event.announced\", \"fight.result\", \"card.changed\", \"event.completed\", \"odds.moved\"]}`. Subscribe to `event.announced` and you do not need to poll `/v1/events` to discover new cards — it fires once, within a minute of a card first landing in our data, and carries the same event object the list endpoint returns. `fight.result` fires once per bout within a minute of the result, as `revision` 1, and again as the next revision (`corrected: true`, with the `previous` result) whenever the winner, method, round, time or status is corrected in the 72 h after it — upsert on `fight_id` and keep the highest `revision`. `odds.moved` fires when the UFCalendar consensus line on an upcoming bout moves at least 5 implied-probability points on corner a, or the favourite flips, measured against the last line we delivered for that bout (its opening line before the first delivery), so a slow drift arrives once, not per refresh: `data` is `{fight_id, event, fighter_a, fighter_b, odds: {consensus, opening, movement, updated_at}, previous, delta_points_a, direction, favourite_flipped, moved_at}`. Information only, not betting advice. The response contains the signing `secret` ONCE. Every delivery body is `{\"id\", \"type\", \"data\", \"sent_at\"}` (`WebhookDelivery` schema) — `id` is stable across retries, so deduplicate on it. Deliveries carry `X-UFCalendar-Signature: t=<unix>,v1=<hmac>` where the HMAC-SHA256 input is `\"<t>.<rawBody>\"`. **Verify the timestamp too**: reject anything where `|now - t|` exceeds 300 seconds, otherwise a captured delivery can be replayed at you forever with a valid HMAC. Delivery is at-least-once — expect a retry roughly every 60s until your endpoint returns 2xx. Endpoints auto-disable after 20 consecutive failures, and you may hold at most 3 active endpoints (409 `endpoint_limit`). Latency: results are dispatched within ~1 minute of the result being recorded. `event.announced` only fires for cards that have not started yet, so archive backfills never reach you as new-card noise. `card.changed` is filtered the same way: a change whose before and after read identically (a venue row re-minted for the same arena, a source dropping a sub-time it never knew) is never delivered, and when a source flip-flops a value we deliver the move and its undo once, not the twentieth repeat. Deliveries are free — they never count against your monthly request quota, only the calls you make to manage endpoints do.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Must be `https://`."},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookKind"},"description":"Defaults to every kind when omitted."}},"required":["url"],"additionalProperties":false},"example":{"url":"https://example.com/ufcalendar","events":["fight.result","card.changed"]}}}},"responses":{"201":{"description":"Created — includes the one-time secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreatedResponse"},"example":{"data":{"id":12,"url":"https://example.com/ufcalendar","events":["fight.result","card.changed"],"secret":"whsec_…"},"meta":{}}}}},"400":{"description":"Invalid input (`invalid_json`, `invalid_url`, `invalid_events`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Requires Pro or above (`tier_required`), or a plan bought directly rather than through RapidAPI (`direct_plan_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"At most 3 active endpoints (`endpoint_limit`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST \"https://api.ufcalendar.com/v1/webhook-endpoints\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\":\"https://example.com/ufcalendar\",\"events\":[\"fight.result\",\"card.changed\"]}'"},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.create_webhook_endpoint(\"https://example.com/ufcalendar\", [\"fight.result\", \"card.changed\"])"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.createWebhookEndpoint(\"https://example.com/ufcalendar\", [\"fight.result\", \"card.changed\"]);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"create_webhook_endpoint\",\n    \"arguments\": {\n      \"url\": \"https://example.com/ufcalendar\",\n      \"events\": [\n        \"fight.result\",\n        \"card.changed\"\n      ]\n    }\n  }\n}"}],"x-mcp-tool":"create_webhook_endpoint","x-mcp-tools":["create_webhook_endpoint"]}},"/v1/webhook-endpoints/{id}":{"delete":{"tags":["Account"],"summary":"Delete a webhook endpoint","description":"Pro and above. Idempotent: deleting an id that is not yours (or no longer exists) still answers 200.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointDeletedResponse"},"example":{"data":{"ok":true},"meta":{}}}}},"400":{"description":"Invalid input (`invalid_id`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Requires Pro or above (`tier_required`), or a plan bought directly rather than through RapidAPI (`direct_plan_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X DELETE \"https://api.ufcalendar.com/v1/webhook-endpoints/12\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.delete_webhook_endpoint(12)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.deleteWebhookEndpoint(12);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"delete_webhook_endpoint\",\n    \"arguments\": {\n      \"endpoint_id\": 12\n    }\n  }\n}"}],"x-mcp-tool":"delete_webhook_endpoint","x-mcp-tools":["delete_webhook_endpoint"]}},"/v1/webhook-endpoints/{id}/rotate-secret":{"post":{"tags":["Account"],"summary":"Rotate an endpoint signing secret","description":"Pro and above. Issues a fresh `whsec_` secret for the endpoint and returns it ONCE, keeping the endpoint id and its delivery history. The previous secret stops verifying the moment this returns, so deploy the new one to your receiver first (or accept both during the cutover). Use this instead of delete-and-recreate when a secret leaks.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Rotated — includes the new one-time secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreatedResponse"}}}},"400":{"description":"Invalid input (`invalid_id`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Requires Pro or above (`tier_required`), or a plan bought directly rather than through RapidAPI (`direct_plan_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such endpoint on this account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST \"https://api.ufcalendar.com/v1/webhook-endpoints/12/rotate-secret\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.rotate_webhook_secret(12)"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.rotateWebhookSecret(12);"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"rotate_webhook_secret\",\n    \"arguments\": {\n      \"endpoint_id\": 12\n    }\n  }\n}"}],"x-mcp-tool":"rotate_webhook_secret","x-mcp-tools":["rotate_webhook_secret"]}},"/v1/usage":{"get":{"tags":["Account"],"summary":"Your quota usage","description":"Current-month usage for the calling key: tier, requests used/limit, rpm limit, and the reset as both a Unix timestamp (`reset`) and ISO-8601 (`reset_at`); `month` (`YYYYMM`) and `period` (`YYYY-MM`) are the same month in two spellings. On the free 1-day trial, `trial_ends_at` is when access stops (null on a paid plan) — plan around it, not `reset_at`.","parameters":[],"responses":{"200":{"description":"Usage","headers":{"ETag":{"description":"Weak validator over the body, e.g. `W/\"GKrimLo826WBqG27jbNFsW2ZHmA\"`. Send it back as `If-None-Match` to get a 304.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `private, no-cache`.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Monthly request quota of the plan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left this month.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix seconds of the monthly reset.","schema":{"type":"integer"}},"x-request-id":{"description":"Quote it to support; the same id is in every error body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"},"example":{"data":{"tier":"pro","month":"202608","requests_used":1204,"requests_limit":200000,"rpm_limit":300,"reset":1756684800,"period":"2026-08","reset_at":"2026-09-01T00:00:00.000Z","trial_ends_at":null},"meta":{}}}}},"304":{"description":"Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body."},"401":{"description":"Missing/invalid API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (`not_found`; staged-org data 404s until the org is promoted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something broke on our side (`internal_error`). It has been logged under the `request_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.ufcalendar.com/v1/usage\" \\\n  -H \"Authorization: Bearer $UFCALENDAR_API_KEY\""},{"lang":"Python","label":"ufcalendar (PyPI)","source":"from ufcalendar import FightAPI\n\napi = FightAPI()  # or FightAPI(\"ufcalendar_...\")\ndata = api.usage()"},{"lang":"TypeScript","label":"@ufcalendar/sdk (npm)","source":"import { FightAPI } from '@ufcalendar/sdk';\n\nconst api = new FightAPI(process.env.UFCALENDAR_API_KEY);\nconst data = await api.usage();"},{"lang":"JSON","label":"MCP tool call","source":"{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"get_usage\",\n    \"arguments\": {}\n  }\n}"}],"x-mcp-tool":"get_usage","x-mcp-tools":["get_usage"]}}}}