UFC Odds API: consensus lines, line movement and closing odds
The UFCalendar UFC Odds API serves one consensus moneyline for every priced UFC bout: the mean across about 18 sportsbooks, with American and decimal prices, implied probability, a de-vigged fair probability, the opening and closing line and the movement between them. Closing lines go back to 2012 for 9,400+ completed fights across UFC, PFL, OKTAGON, BKFC and RIZIN, refreshed every 30 minutes in fight week. Book identities are not exposed; information only, not betting advice.
Free 1-day trial · 100 requests · no credit card. Paid plans from $19/mo for 30,000 requests, cancel anytime.
Need the numbers while the fight is still happening? The live feed pushes the round, the clock and in-fight totals over one WebSocket. UFC Live API
One line per bout, not a wall of books
GET /v1/fights/{id}/odds returns the current, opening and closing line side by side, each with American and decimal prices, implied probability and sources, the number of sportsbooks behind it. Prediction markets and exchanges are excluded, so the number is a sportsbook market rather than an order book. GET /v1/events/{slug}/odds returns the whole card in one call.
Movement history and a closing-line archive
Pro plans read every movement point with GET /v1/fights/{id}/odds/history and can subscribe to the odds.moved webhook, which fires when a line moves 5 points of implied probability or the favourite flips. Enterprise gets every closing line since 2012 in one gzipped file, ready to join against results for market-accuracy research.
Endpoints for this job
Method and path, linked to the reference. The same key covers every endpoint in the API.
| Method & path | What it returns |
|---|---|
GET /v1/fights/{id}/odds | One bout's consensus moneyline: American and decimal prices, implied and de-vigged probabilities, the opening and closing line and the movement between them. |
GET /v1/events/{slug}/odds | The consensus line for every bout on a card in one call, in card order, unpriced bouts included. |
GET /v1/fights/{id}/odds/history | Every movement point of a bout's consensus line, oldest first, with the number of sportsbooks behind each point. |
GET /v1/events/{slug}?include=odds | Add include=odds to an event or fight call and every bout carries its current consensus line inline. |
POST /v1/webhook-endpoints | A signed odds.moved delivery when a bout's consensus line moves 5 points of implied probability or the favourite flips. |
GET /v1/bulk/odds-closing.json.gz | Every completed, priced bout since 2012 with its opening and closing line, in one gzipped file. |
Quickstart in curl, Python and JavaScript
Complete requests against the live API. Any HTTP client works, or `pip install ufcalendar` for a typed Python client (source on GitHub); every response is plain JSON in a {"data": ..., "meta": ...} envelope.
$ curl "https://api.ufcalendar.com/v1/fights/62368/odds" \
-H "Authorization: Bearer $UFCAL_KEY"
{
"data": {
"fight_id": 62368,
"status": "completed",
"event": { "id": 489, "slug": "ufc-229-2018-10-07",
"title": "UFC 229: Khabib vs McGregor", "org": "ufc",
"starts_at": "2018-10-07T02:00:00.000Z" },
"fighter_a": { "id": 1966, "slug": "khabib-nurmagomedov", "name": "Khabib Nurmagomedov" },
"fighter_b": { "id": 2033, "slug": "conor-mcgregor", "name": "Conor McGregor" },
"closing": {
"a": { "american": -168, "decimal": 1.595, "implied_probability": 0.6269 },
"b": { "american": 141, "decimal": 2.41, "implied_probability": 0.4149 },
"favourite": "a",
"fair_probability_a": 0.6017,
"sources": 6,
"recorded_at": "2018-10-07T00:39:06.000Z"
},
"opening": { "a": { "american": -115, ... }, "b": { "american": -115, ... },
"favourite": null, "recorded_at": "2017-04-13T23:07:26.000Z", ... },
"consensus": { ... }, // settled bout: the same point as "closing"
"movement": { "delta_points_a": 9.2, "direction": "a",
"since": "2017-04-13T23:07:26.000Z" },
"points": 217,
"updated_at": "2018-10-07T00:39:06.000Z"
},
"meta": {
"note": "UFCalendar consensus line across the sportsbooks we track (book identities are not exposed). Information only, not betting advice.",
"checked_at": "…",
"history": "/v1/fights/62368/odds/history"
}
}from ufcalendar import FightAPI
api = FightAPI() # UFCAL_API_KEY in the environment
# The closing line next to the result: what the market priced, and what happened
card = api.event_odds("ufc-229-2018-10-07")
for f in card["fights"]:
close = f["closing"]
if not close:
continue # unpriced bout: the row is present, the line is null
fav = f["fighter_a"] if close["favourite"] == "a" else f["fighter_b"]
print(f"{f['fighter_a']['name']} vs {f['fighter_b']['name']}:",
close["a"]["american"], "/", close["b"]["american"],
"favourite:", fav["name"] if close["favourite"] else "pick'em")
# Pro plans: every movement point, oldest first
for p in api.fight_odds_history(62368, limit=500):
print(p["recorded_at"], p["a"]["american"], p["b"]["american"], p["sources"])import { FightAPI } from "@ufcalendar/sdk";
const api = new FightAPI(); // UFCAL_API_KEY in the environment
// Opening vs closing: how far did the market move on this bout?
const { consensus, opening, closing, movement } = await api.fightOdds(62368);
console.log("opened", opening?.a.american, "closed", closing?.a.american);
console.log(`moved ${movement?.delta_points_a} points toward`, movement?.direction);
// Or ask for the line inline on a normal event call:
// GET /v1/events/ufc-229-2018-10-07?include=odds -> each bout carries odds: { a, b, favourite, ... }Questions
- Is there a UFC odds API?
- Yes. Every priced UFC bout returns a consensus moneyline on GET /v1/fights/{id}/odds, and a whole card comes back from GET /v1/events/{slug}/odds, on every plan including the free 1-day trial. Add include=odds to an event or fight call to get the line inline.
- Is this betting advice?
- No. The API reports what the betting market priced, the same way it reports a result or a ranking. It does not recommend a side, a stake or a book, and nothing in it is an offer to wager. Odds are information only, not betting advice.
- Which sportsbooks are included?
- The consensus is the mean across the sportsbooks we track, about 18 on a UFC card. Prediction markets and exchanges are excluded. Book identities are not exposed: each line carries a sources count instead, so you can see how many books stand behind it.
- How fresh are the odds?
- Lines refresh every 30 minutes in the 48 hours before a card and every 2 hours otherwise. updated_at is when the consensus last moved and meta.checked_at is when we last read the market, so a quiet line is never mistaken for a stale one.
- How far back does the odds data go?
- The earliest consensus line is from 2012, and 9,400+ completed fights carry a closing line. 2,700+ of them also carry a full movement series from open to close; many older bouts have a single recorded point, so their opening and closing line are the same. The points field tells you how many points a bout has.
- Which promotions and plans are covered?
- UFC, PFL, OKTAGON, BKFC and RIZIN, under the same key and schema. The current, opening and closing lines are on every plan; movement history and the odds.moved webhook are Pro and up; the closing-line bulk file is Enterprise.
UFC API guides by use case
One page per job: schedules, results, per-round statistics, rankings history, judges' scorecards, the live feed and consensus odds, each with its own endpoints, sample responses and code.
UFCalendar is an independent publication, not affiliated with UFC/Zuffa/TKO, PFL, OKTAGON MMA, BKFC, RIZIN FF or any promotion. Organization names are used to describe the data. Terms of service · Refund Policy