UFC Live Data API

The UFC Live Data API is a real-time fight-night data feed from Cito API, documented on ufcapi.dev. It pushes round, clock, status, and liveStats (sigStrikes, takedowns) over websocket so apps update as the fight does—without multi-second REST polling.

js · websocket
const key = process.env.CITO_API_KEY;
const ws = new WebSocket(
  `wss://api.citoapi.com/api/v1/ufc/live/ws?api_key=${encodeURIComponent(key)}`
);

ws.onopen = () => console.log("connected");

ws.onmessage = (ev) => {
  const msg = JSON.parse(ev.data);

  // Server hello — then subscribe to bout and/or event rooms
  if (msg.type === "ready") {
    ws.send(JSON.stringify({
      action: "subscribe",
      rooms: [
        "bout:ufc-12938",
        "event:ufc-fight-night-example"
      ]
    }));
    return;
  }

  if (msg.type === "subscribed") {
    console.log("rooms", msg.rooms);
    return;
  }

  // Live fight frame
  if (msg.type === "ufc.live.update") {
    const { currentRound, currentTime, liveStats, status } = msg.data;
    console.log(msg.room, status, "R" + currentRound, currentTime, liveStats);
  }
};

ws.onerror = (err) => console.error("ws error", err);
ws.onclose = () => console.log("closed — reconnect with backoff");
json · ufc.live.update
{
  "type": "ufc.live.update",
  "room": "bout:ufc-12938",
  "data": {
    "boutId": "ufc-12938",
    "eventSlug": "ufc-fight-night-example",
    "status": "live",
    "currentRound": 2,
    "currentTime": "3:12",
    "red": { "fighterName": "Islam Makhachev", "corner": "red" },
    "blue": { "fighterName": "Arman Tsarukyan", "corner": "blue" },
    "liveStats": {
      "red": { "sigStrikes": 42, "takedowns": 1 },
      "blue": { "sigStrikes": 31, "takedowns": 0 }
    },
    "lagSeconds": 2,
    "source": "ufc_fightmetric_cdn"
  }
}

Websocket vs polling

REST polling

You only see new state when you request it. A 2-5s poll adds lag. Fine for archives, weak for fight night UIs.

Websocket push

Server pushes frames when they land. Your frontend updates as soon as Cito has the frame.

What data updates in real time?

  • currentRound — active round number as the bout progresses
  • currentTime — clock remaining in the round (null when empty)
  • status — live / watching / final and related bout state
  • liveStats.sigStrikes — significant strike totals per corner when present
  • liveStats.takedowns — takedown counts per corner when present
  • red / blue.fighterName — corner identity on each ufc.live.update frame
  • boutId + room — bout:{id} and event:{slug} subscribe targets
  • lagSeconds + source — lag metadata and fight-night source tag

What data is returned

type
Frame type: ready, subscribed, ufc.live.update, ping, or error
room
Subscribed room id — bout:{boutId} or event:{eventSlug}
boutId
Bout identity for subscribe filters and REST catch-up
eventSlug
Event slug when the frame is scoped to a card
status
Bout state: live, watching, final, and related values
currentRound
Active round number during the bout
currentTime
Clock remaining in the round (null when empty)
red / blue
Corner objects with fighterName (and corner when present)
liveStats
Per-corner totals when present (sigStrikes, takedowns, …)
liveStats.*.sigStrikes
Significant strike count for that corner
liveStats.*.takedowns
Takedown count for that corner
lagSeconds
Observed lag from source clock to Cito frame
source
Fight-night source tag (e.g. ufc_fightmetric_cdn)

When to use this

  • Build a UFC live data API consumer for fight-night scoreboards and broadcast overlays
  • Push currentRound, currentTime, and strike/takedown liveStats the moment a frame lands
  • Power fantasy, engagement, or second-screen apps that react to momentum mid-bout
  • Replace multi-second REST polling when lag would show behind the broadcast
  • Subscribe to event:{slug} for multi-bout boards or bout:{id} for a single fight UI

Full reference docs citoapi.com/docs/api/ufc/live/websocket

Get your free UFC API key