# UFCalendar Fight API — the MMA Fight Data API > TL;DR: UFCalendar's MMA Fight Data API — REST + a hosted MCP server (47 tools) for UFC, PFL, OKTAGON, BKFC and RIZIN: events, fight cards, results, per-round stats, rankings history, judges' scorecards and a consensus odds line (information only, not betting advice). > Plans: Hobby $19 / Pro $49 / Business $149 a month (hard caps, no overage); free 1-day, 100-request trial, no card, self-serve at https://www.ufcalendar.com/account/api?trial=1 > Docs: https://api.ufcalendar.com/docs · pricing and guides: https://www.ufcalendar.com/developers · plans as JSON, no key: https://api.ufcalendar.com/v1/plans > > Self-serve MMA API and fight data API (MMA + bare-knuckle boxing) by UFCalendar > (https://www.ufcalendar.com), also reachable as a hosted MMA Fight Data MCP > server at https://api.ufcalendar.com/mcp. Events, > full fight cards, results, per-fight and per-round statistics, fighters with > complete multi-promotion career timelines, official rankings history > (UFC 2013->present), judges' scorecards round by round (the official > athletic-commission record: UFC 1995->present, cross-checked against the > scorecards ufc.com publishes, which also cover DWCS and Road to UFC from > March 2022; RIZIN 2026->present), > UFCalendar Power Index ratings, AI win probabilities, the UFCalendar consensus > odds line (current, opening and closing on every plan; line movement Pro+), > and per-country broadcast rights — for UFC, PFL, OKTAGON, BKFC and RIZIN (more orgs > join as they clear a reliability bar; /v1/orgs lists per-org capability flags). Built for indie developers, side projects and small teams: fantasy apps, stats sites, Discord bots, analytics projects. Plans are priced for them: self-serve only, no sales-negotiated contracts, and none planned. Base URL: https://api.ufcalendar.com/v1 Auth: Authorization: Bearer — keys at https://www.ufcalendar.com/account/api (plan or trial required) Spec: https://api.ufcalendar.com/openapi.json (OpenAPI 3.1) Docs: https://api.ufcalendar.com/docs Pricing: https://www.ufcalendar.com/developers (Hobby $19 30k req/mo at 60 rpm, Pro $49 200k at 300 rpm + webhooks, Business $149 1M at 600 rpm; hard caps, no overage billing. No free tier — free 1-day trial, 100 requests, no card, self-serve at https://www.ufcalendar.com/account/api?trial=1) Coverage pages: https://www.ufcalendar.com/developers/ufc-api · https://www.ufcalendar.com/developers/pfl-api · https://www.ufcalendar.com/developers/oktagon-api · https://www.ufcalendar.com/developers/bkfc-api · https://www.ufcalendar.com/developers/rizin-api Use-case guides (UFC): https://www.ufcalendar.com/developers/ufc-schedule-api · https://www.ufcalendar.com/developers/ufc-results-api · https://www.ufcalendar.com/developers/ufc-stats-api · https://www.ufcalendar.com/developers/ufc-rankings-api · https://www.ufcalendar.com/developers/ufc-scorecards-api · https://www.ufcalendar.com/developers/ufc-odds-api MMA API overview: https://www.ufcalendar.com/developers/mma-api MCP server pages: https://www.ufcalendar.com/developers/ufc-mcp-server · https://www.ufcalendar.com/developers/mma-mcp-server Plans (no credential needed): https://api.ufcalendar.com/v1/plans Full reference for agents: https://api.ufcalendar.com/llms-full.txt Agent quickstart page: https://www.ufcalendar.com/developers/agents Python client: pip install ufcalendar (https://github.com/UFCalendar/ufcalendar-python · https://pypi.org/project/ufcalendar/) TypeScript client: npm install @ufcalendar/sdk (https://github.com/UFCalendar/ufcalendar-typescript · https://www.npmjs.com/package/@ufcalendar/sdk) Agent skill: npx skills add UFCalendar/fight-api-skill (https://github.com/UFCalendar/fight-api-skill) Also listed on RapidAPI Hub (https://rapidapi.com/ceo-SP8r6F1JT/api/ufc-and-mma-fight-data-by-ufcalendar), Postman (https://www.postman.com/ceo-5d84eedc/workspace/ufcalendar-fight-api) and GitHub (hosted MCP server: https://github.com/UFCalendar/ufcalendar-mcp) Terms: https://www.ufcalendar.com/developers/terms Odds are one UFCalendar consensus line per corner: the mean across the sportsbooks we track, with how many books backed each point (sources); book identities are never exposed. Refreshed every 30 minutes in the 48 hours before a card, every 2 hours otherwise. Information only, not betting advice. Scorecards are the official commission record (judges, rounds, totals, deductions); media-member and fan scorecards are not part of the API. Not affiliated with UFC/Zuffa/TKO or any promotion. ## For AI agents: how to get access 1. Read https://api.ufcalendar.com/v1/plans first — plans, quotas, the trial rule and this server's MCP endpoint, with NO credential. 2. Human at the keyboard: send them to https://www.ufcalendar.com/account/api?trial=1 — free 24-hour trial, 100 requests, no card, one per account. The key it mints goes in `Authorization: Bearer ` on every REST call and on https://api.ufcalendar.com/mcp. 3. No human at the keyboard: use the device flow. POST `https://www.ufcalendar.com/api/auth/device/code` with a JSON or form-encoded body carrying `client_id` (and optional `scope`), show the human the `verification_uri_complete` it returns, poll the token endpoint with the `device_code` until it stops answering `authorization_pending`, then send the access token as a bearer. 4. In an MCP client that speaks OAuth (Claude, ChatGPT): add https://api.ufcalendar.com/mcp as a connector and sign in. Calling a gated tool unauthenticated answers 401 with `WWW-Authenticate: Bearer resource_metadata="https://api.ufcalendar.com/.well-known/oauth-protected-resource"`, which is the whole discovery chain. Signing in for the first time starts the free trial automatically when the account has never held a plan. There is no free tier: after the trial, a plan is required. ## Endpoints - GET /v1/plans — plans, quotas, trial terms, MCP endpoint and links (NO key required; the one open endpoint) - GET /v1/orgs — launch orgs + capability flags (stats/rounds/rankings/broadcasts/predictions/scorecards/odds) - GET /v1/orgs/{slug} — one org by slug - GET /v1/events?org=&status=&from=&to=&order= — schedule + results, cursor pagination (bare listing = upcoming calendar, soonest first; status=upcoming = every card not yet over; order=desc for the archive newest-first) - GET /v1/events/{idOrSlug} — event with full card (bouts carry division_slug + result.method_normalized / finish_detail / time_seconds), venue, broadcasts; stale slugs 308 - GET /v1/events/{idOrSlug}/changes — card-change diff log (fight added/moved, opponent swapped, fighter profile merged: kind fighter-merged) - GET /v1/fights/{id}?include=odds — one bout with result (raw method + method_normalized), corners carry country_code; include=odds adds the current consensus line (the closing line once the bout is settled) - GET /v1/fights/{id}/odds — the UFCalendar consensus line for one bout: current, opening, closing (settled bouts), movement in implied-probability points, sources = books behind each point, meta.checked_at, plus props: method of victory per corner (KO/TKO, submission, decision), total rounds over/under per line, goes the distance (closing props once settled; null when unpriced); 200 with nulls when unpriced; information only, not betting advice - GET /v1/fights/{id}/odds/history?from=&to=&limit=&cursor= — odds history: every consensus point oldest first (a point is stored only when the line moves); REQUIRES Pro+ (403 tier_required below) - GET /v1/events/{idOrSlug}/odds — consensus odds (moneyline + props) for every non-cancelled bout on one card, card order, unpriced bouts included with nulls; meta.priced / meta.unpriced - GET /v1/fights/{id}/stats — per-fight totals for both corners (each line has corner 'a'|'b') - GET /v1/fights/{id}/rounds — round-by-round statistics (round + corner per line) - GET /v1/fights/{id}/scorecards — judges' scorecards: every official, every round, card totals, decision type, point deductions (official athletic-commission record; UFC cards cross-checked against ufc.com's published scorecards, incl. DWCS and Road to UFC; source = commission-record, ufc-official-cards or the promotion's own slug; PFL US cards may be totals-only with no judge identity); 200 with cards: [] when no commission record exists, 404 only for an unknown fight - GET /v1/judges?q=&org=&min_fights= — judge directory with career aggregates (fights, rounds, 10-8s, split cards, lone dissents) - GET /v1/judges/{id} — one judge - GET /v1/judges/{id}/scorecards — every card that judge has turned in, newest first - GET /v1/fighters?q=&org=&country= — roster search (country_code ISO-2; country= accepts a code or a name) - GET /v1/fighters/{idOrSlug} — bio, records (career + per-org W-L-D with wins/losses/draws/no_contests, keyed pro_mma / ufc / …), stats (one per-minute panel + numeric values, with a basis naming the bouts it covers), raw career_stats rows, Power Index, CC-licensed images; stale slugs 308 - GET /v1/fighters/{idOrSlug}/history — complete multi-promotion career timeline; every key on every row plus status / method_normalized / time_seconds / opponent - GET /v1/fighters/{idOrSlug}/stats — raw career stat rows, one source-stamped row per scope (pro-mma, etc.); meta.records + meta.stats carry the readable split - GET /v1/fighters/{idOrSlug}/rankings?limit=&cursor= — official ranking history rows (board official|meta, is_champion), cursor-paginated, limit up to 500 - GET /v1/fighters/{idOrSlug}/power-index — rating trajectory: newest 500 points oldest-first, with result; meta.truncated - GET /v1/rankings/{org}?date=YYYY-MM-DD — official board, point-in-time since 2013 (rank 0 = champion) - GET /v1/orgs/{slug}/divisions/{division} — one weight class in one promotion: current rankings board (null where none is published), upcoming bouts at that weight, the latest results and the roster by recency - GET /v1/events?org=&status=&from=&to=&order=&is_title_card=&is_ppv=&include=headline — schedule + results, cursor pagination (bare listing = upcoming calendar, soonest first; status=upcoming = every card not yet over; order=desc for the archive newest-first); include=headline adds each card's main event and its result - GET /v1/events/{id|slug}?include=eta,odds — event with full card, venue, broadcasts; include=eta adds per-bout estimated start times (estimates, re-anchored on each completed bout); include=odds adds each bout's current consensus line (the closing line once settled) - GET /v1/events/{id}/changes — card-change diff log (fight added/moved, opponent swapped, fighter profile merged: kind fighter-merged); no-op rows and flaps filtered, same rule as the webhook - GET /v1/changes?org=&since=&kind= — the card-change feed across every event, newest first (default: last 90 days); the card.changed webhook's audit trail for callers that poll - GET /v1/events/{id|slug}/watch?country=XX — how to watch one event: the promotion's rights deals for its series merged with the event's own broadcast listings, per country, WORLD first - GET /v1/events/{id|slug}/storylines — the talking points of one card as of its start: title fights and eliminators, the closest bout (UFCalendar model, else Power Index), rematches and trilogy deciders, streaks, debuts and long layoffs, ranked fighters and champions, nations, tallest / longest reach and the fastest career finish on the bill - GET /v1/events/{id|slug}/pickem — how the UFCalendar community is picking each bout on one card (picks per corner, total, percentage; card order) — crowd sentiment from our own pick'em game, not a market and not a forecast - GET /v1/fights/search?org=&title_only=&method=ko|sub|dec|finish&division=&fighter=&winner=&from=&to=&main_events_only=&order=newest|oldest — completed bouts, filtered (at least one narrowing filter required; 25 per page, 10 pages deep, newest first) — "the last title fight to end by KO" in one call - GET /v1/fights/{id} — one bout with result - GET /v1/fights/{id}/stats — per-fight totals for both corners - GET /v1/fights/{id}/rounds — round-by-round statistics - GET /v1/fights/{id}/scorecards — judges' scorecards: every official, every round, card totals, decision type, point deductions (official athletic-commission record; UFC cards cross-checked against ufc.com's published scorecards, incl. DWCS and Road to UFC; source = commission-record, ufc-official-cards or the promotion's own slug; PFL US cards may be totals-only with no judge identity) - GET /v1/scorecards/splits?org=&from=&to= — split and majority decisions, newest first, with every judge's card and the dissenting judges named (commission records only) - GET /v1/judges?q=&org=&min_fights= — judge directory with career aggregates (fights, rounds, 10-8s, split cards, lone dissents) + meta.league baseline rates - GET /v1/judges/{id} — one judge - GET /v1/judges/{id}/scorecards — every card that judge has turned in, newest first, with lone_dissent / split flags and the colleagues' totals - GET /v1/fighters?q=&org=&country= — roster search - GET /v1/fighters/{id|slug}?include=bonuses,credentials — bio, records (career + per-org W-L-D, keyed pro_mma / ufc / …), stats (one per-minute panel with a basis naming the bouts it covers), raw career_stats rows, Power Index, CC-licensed images, next_fight + last_fight; include=bonuses adds the UFC bonus ledger (FOTN/POTN/KOTN/SOTN); include=credentials adds grappling and wrestling pedigree, gyms and coaches (every row with its sources and a confidence grade; verify before republishing) - GET /v1/fighters/{id}/history — complete multi-promotion career timeline - GET /v1/fighters/{id}/stats — raw career stat rows, one source-stamped row per scope (pro-mma, etc.); meta.records + meta.stats carry the readable split - GET /v1/fighters/{id}/rankings — official ranking history rows - GET /v1/fighters/{id}/power-index — rating trajectory - GET /v1/compare?a=&b= — two fighters side by side in one call: bios + age, career stats, strike location/position mix, win streaks, previous meetings, common opponents, the booked bout between them, UFCalendar model win probability for it (UFC) and Power Index ratings - GET /v1/rankings/{org}?date=YYYY-MM-DD — official board, point-in-time since 2013 (rank 0 = champion), movement + is_new vs the previous snapshot, meta.previous/next_snapshot_date - GET /v1/rankings/{org}/{division} — one division - GET /v1/champions?org=&division= — current champions across launch orgs; org= / division= narrow it - GET /v1/power-index/{org}?view=current|movers|peaks&division=&days= — UFCalendar Power Index board; movers = biggest risers over a window, peaks = all-time peak ratings - GET /v1/matchmaker/{org}?division=&limit= — UFCalendar's matchmaker: the fights worth making in one MMA promotion, scored 0–100 (rank proximity, momentum, competitiveness, story), per division or across the roster; not a list of bookings, computed without the site's Fight DNA factor - GET /v1/matchmaker/next/{fighter} — who one fighter should fight next: the best-scored opponents with the Power Index win probability for each, plus the bout already booked - GET /v1/stats/leaders?org=&metric=&division=&country=&population=all|active — one Record Book leaderboard for one promotion (48 metrics: career, single-fight, round, division and event boards), ranked with the sample size behind each value; ties flagged - GET /v1/stats/record-book?org=&division=&country=&population=&scope=&top= — every leaderboard's top rows for one promotion, grouped by category - GET /v1/stats/years/{year}?org= — a year in review for one promotion (or every covered promotion): events, title fights, finish methods, divisions, fastest finishes, biggest upsets, Power Index climbers, busiest fighters, host countries and the most-used judges - GET /v1/predictions/upcoming?event= — model win probabilities (UFC), ~3 weeks ahead, repriced weekly and on any corner change; event= narrows to one card - GET /v1/broadcast-rights/{org}?country=XX&series=dwcs|rtufc — who airs it, per country (org-wide deals by default; series= for a UFC sub-series grid) - GET /v1/venues?q=&country= — search venues that hosted a covered promotion (name, city, country) - GET /v1/venues/{id} — venue detail - GET /v1/venues/{id}/events?status=&from=&to=&order= — every covered event at one venue, newest first - GET /v1/search?q= — typeahead across fighters and events - GET /v1/usage — your key's quota usage (period YYYY-MM, reset_at ISO; trial_ends_at = when a free 1-day trial stops, null on a paid plan) - GET /v1/articles?q=&tag=&locale= — UFCalendar's own editorial archive (previews, recaps, investigations), newest first, in any of the 13 site languages; canonical URL per row - GET /v1/articles/{slug}?locale= — one article: full Markdown body (client widgets removed), author, tags, publication date; the translation when one exists, English otherwise - GET /v1/usage — your key's quota usage - GET /v1/calendar/{org}.ics?key= — ICS calendar feed for calendar apps ({org}-sections.ics per card section, {org}-fights.ics per bout at its estimated start) - GET/POST/DELETE /v1/webhook-endpoints — signed webhooks: event.announced, fight.result, card.changed, event.completed, odds.moved (consensus line on an upcoming bout moved 5+ implied-probability points or the favourite flipped; information only, not betting advice) (Pro+, max 3 endpoints); delivery bodies are {id, type, data, sent_at} — deduplicate on id; fight.result carries revision (1 = first) and is re-sent as the next revision with corrected: true and the previous result when the winner/method/round/time is corrected within 72 h — upsert on fight_id - DELETE /v1/webhook-endpoints/{id} — remove an endpoint - POST /v1/webhook-endpoints/{id}/rotate-secret — new signing secret, returned once (Pro+) ## MCP The same data is available as a Model Context Protocol server, so an agent can call it without an HTTP client. Endpoint: https://api.ufcalendar.com/mcp Transport: stateless Streamable HTTP. POST JSON-RPC only; GET answers 405. Send `Accept: application/json, text/event-stream` — the transport answers 406 without it. Auth (either one): an API key as `Authorization: Bearer `, OR sign in with your UFCalendar account over OAuth 2.1 — unauthenticated calls to a gated tool answer 401 with `WWW-Authenticate: Bearer resource_metadata="https://api.ufcalendar.com/.well-known/oauth-protected-resource"`, which is the discovery document. Metering: 1 tool call = 1 metered request against the same plan quota as REST. `get_plans`, `list_orgs` and `how_to_connect` need no credential and cost nothing. Tools: * get_plans — Plans and quotas * list_orgs — List promotions * how_to_connect — How to connect * get_org — Get a promotion * get_division — Get a division * list_events — List events * get_next_event — Get the next event * get_event_card — Get an event and its full card * get_event_changes — Get an event’s change log * list_changes — List recent card changes * how_to_watch — How to watch an event * get_event_storylines — Get event storylines * get_pickem_splits — Get pick'em splits * get_event_odds — Get consensus odds for a card * get_fight_odds — Get consensus odds for a bout * get_odds_history — Get the odds line movement * get_fight — Get a bout * find_fights — Find fights * search — Search fighters and events * search_fighters — Search the roster * get_fighter — Get a fighter * compare_fighters — Compare two fighters * get_rankings — Get a rankings board * get_champions — Get current champions * get_power_index — Get the UFCalendar Power Index board * get_matchmaker — Get the matchmaker board * whos_next — Who should fight next * get_leaderboard — Get a stat leaderboard * get_record_book — Get the record book * get_year_stats — Get a year in review * get_predictions_upcoming — Get model win probabilities * get_broadcast_rights — Get broadcast rights * list_judges — List judges * get_judge — Get a judge * get_judge_scorecards — Get a judge’s scorecards * list_split_decisions — List split and majority decisions * get_usage — Get your API usage * get_venue — Get a venue * search_venues — Search venues * get_venue_events — List events at a venue * search_articles — Search UFCalendar articles * get_article — Get an article * get_calendar_feed_url — Get calendar feed URLs * list_webhook_endpoints — List webhook endpoints * create_webhook_endpoint — Register a webhook endpoint * rotate_webhook_secret — Rotate a webhook signing secret * delete_webhook_endpoint — Delete a webhook endpoint ## Conventions - JSON, snake_case, {"data": ..., "meta": ...} envelope; meta is ALWAYS present ({} at minimum) - Every response body has a schema under components.schemas in the OpenAPI document (closed objects, enums for every vocabulary) — generate types from it - Errors: {"error": {"code", "message", "request_id"}} with proper HTTP status; every code is in the ErrorCode enum - Cursor pagination: ?cursor= from meta.pagination.next_cursor, ?limit= up to 100 - Every GET /v1 200 carries a weak ETag and Cache-Control: private, no-cache; send If-None-Match and an unchanged payload answers 304 with no body - Dates (from=, to=, date=) must be real calendar days → 400 invalid_date otherwise; status=postponed is accepted - Query parameters an endpoint does not take are ignored, never a 400 — and named: header X-UFCalendar-Ignored-Params plus meta.ignored_params on a 200 (e.g. ?limit= on /history) - Timestamps UTC ISO-8601; events carry the venue IANA tz - Rate headers: X-RateLimit-Limit / -Remaining / -Reset (monthly quota), Retry-After on 429 - Plan gating: webhook endpoints and odds history (GET /v1/fights/{id}/odds/history) need Pro+; every other endpoint (ICS feeds included) is open to any active plan. A key below the required tier gets 403 tier_required - List endpoints return identity fields; the full record lives on the detail route. /v1/events omits the card, /v1/fighters omits the physical bio, and there is no /v1/fights list — fetch a fight by id or read it off the event; /v1/fights/search is a bounded filtered search - Webhook DELIVERIES do not count against your monthly quota — only the calls you make to register, list, rotate or delete endpoints do - Webhook delivery is at-least-once: verify X-UFCalendar-Signature (HMAC-SHA256 over ".") AND reject t older than 300s, deduplicate on the body, and return 2xx fast. We retry about once a minute until you do; 20 consecutive failures auto-disable the endpoint - Fighter images are Wikimedia Commons/CC only and carry license + artist fields: displaying the credit is required by the license - source / source_slug values name official publishers only (ufc-stats, ufc-official, ufc-official-cards, a promotion's *-official, wikipedia, ufcalendar); every other publisher ships as public-records (career records, history rows) or commission-record (judges' scorecards)