Ultimate Fighting Calendar
UFCalendar Fight API

UFC Live Stats API: round, clock and in-fight stats over WebSocket

The UFCalendar UFC Live Stats API streams what is happening in the cage as it happens: the round and a running clock, unofficial significant-strike, takedown, knockdown and control-time totals for both corners, round-by-round lines, the referee, and a timestamped play-by-play timeline (round starts, knockdowns, takedowns, submission attempts). One WebSocket, one JSON document, pushed within 1–2 seconds of every change. Pro plans and up.

Free 1-day trial · 100 requests · no credit card. Paid plans from $19/mo for 30,000 requests, cancel anytime.

1–2 s
seconds from the cage to your socket
22
stat fields per corner, live
16
timeline action types

A socket, not a poll

developers.topicApi.ufcLive.edge1Body

The clock is yours to tick

Every document carries clock_sec and clock_observed_at, and the clock is derived from the official round_start timestamp rather than a lagging counter. Add the wall time since the observation and you have a second-accurate round clock in your own UI, whether the last frame arrived one second ago or forty. Stats are flagged official: false until the promotion finalizes them.

Endpoints for this job

Method and path, linked to the reference. The same key covers every endpoint in the API.

Method & pathWhat it returns
GET /v1/events/{slug}/liveReal-time fight-night stream: round, clock, unofficial in-fight stats and a play-by-play timeline, pushed over WebSocket as they change.
GET /v1/events/{slug}One event with its full fight card (both corners, results when completed), venue and event-level broadcasts.
GET /v1/fights/{id}/statsPer-fight totals for both corners: strikes by target and position, takedowns, control time.
POST /v1/webhook-endpointsSigned webhooks for fight results, card changes and event completion · no polling needed.

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
$ curl "https://api.ufcalendar.com/v1/events/ufc-2026-09-20/live" \
    -H "Authorization: Bearer $UFCAL_KEY"

{
  "data": {
    "event": { "slug": "ufc-2026-09-20", "status": "live" },
    "current": {
      "phase": "round", "round": 2, "possible_rounds": 5,
      "clock_sec": 67, "official": false,
      "stats": { "a": { "sig_strikes_landed": 41, "takedowns_landed": 0,
                        "control_time_sec": 1, ... },
                 "b": { "sig_strikes_landed": 20, "takedowns_landed": 1, ... } },
      "timeline": [ { "t": "…", "type": "takedown", "round": 2,
                      "clock": "2:57", "side": "b" }, ... ]
    },
    "last": { "winner": "a", "method": "KO/TKO", "round": 1, "time": "4:56" }
  },
  "meta": { "live": true, "websocket": "wss://live.ufcalendar.com/v1" }
}

# Or hold one socket open and let every change come to you:
$ wscat -c "wss://live.ufcalendar.com/v1?key=$UFCAL_KEY"
> {"action":"subscribe","event":"ufc-2026-09-20"}
< {"type":"snapshot","data":{...}}
< {"type":"update","data":{...}}        # every few seconds while a round runs
< {"type":"fight.final","data":{...}}   # the moment a bout ends
Python
import json, websocket   # pip install websocket-client

ws = websocket.create_connection(f"wss://live.ufcalendar.com/v1?key={UFCAL_KEY}")
ws.send(json.dumps({"action": "subscribe", "event": "ufc-2026-09-20"}))

while True:
    frame = json.loads(ws.recv())
    if frame["type"] == "pong" or not frame.get("data"):
        continue
    cur = frame["data"]["current"]
    if cur and cur["phase"] == "round":
        a, b = cur["stats"]["a"], cur["stats"]["b"]
        print(f"R{cur['round']} {cur['clock_sec']}s  sig {a['sig_strikes_landed']}-{b['sig_strikes_landed']}")
    if frame["type"] == "fight.final":
        print("FINAL:", frame["data"]["last"])
JavaScript
const ws = new WebSocket(`wss://live.ufcalendar.com/v1?key=${process.env.UFCAL_KEY}`);
ws.onopen = () => ws.send(JSON.stringify({ action: "subscribe", event: "ufc-2026-09-20" }));
ws.onmessage = (e) => {
  const { type, data } = JSON.parse(e.data);
  if (!data?.current) return;
  const { phase, round, clock_sec, stats, timeline } = data.current;
  if (phase === "round")
    console.log(`R${round} ${clock_sec}s  sig ${stats.a.sig_strikes_landed}-${stats.b.sig_strikes_landed}`);
  if (type === "fight.final") console.log("FINAL", data.last);
  // timeline[] carries round_start / knockdown / takedown / submission_attempt … with a clock
};

Questions

Which promotions have live stats?
UFC only in this first version — including numbered cards, Fight Nights and the live-streamed prelims. The source is the promotion's own real-time feed, and no other promotion publishes one. Other orgs still get results within minutes through the normal API and webhooks.
How live is live?
The promotion's feed changes every 5–10 seconds during a round. We poll it at 1–2 seconds and publish only when the content changes, so you see a new frame within about two seconds of the source. Between frames, interpolate the clock from clock_observed_at.
What is in the document?
The full card with statuses and results, the bout in progress (phase: prefight, round, break or over; round; running clock; both corners' totals across 22 stat fields; per-round lines; referee; the action timeline) and the last result. It is the same document the website's live panel renders.
Which plan do I need, and how many connections?
Pro and up. Pro keys may hold 2 concurrent connections, Business 5, Enterprise 25. Messages are not metered and do not count toward your monthly request quota; the REST snapshot does count as a normal request.

UFC API guides by use case

One page per job — schedules, results, per-round statistics and rankings history — 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