Skip to content
MMA Calendar
MMA Fight Data API · Code guide

How do I get the upcoming UFC schedule in Python?

Call GET /v1/events?org=ufc on the MMA Fight Data API, or api.events("ufc") with the ufcalendar Python package. It returns every upcoming UFC card, soonest first, with the first-bell, main-card and prelims times in UTC, the venue's time zone and a PPV flag. Pass a card's slug to the event endpoint for the full fight card.

Free plan: 1,000 requests a month, no card. Paid plans from $19/mo.

Endpoints used

Endpoints used
Method & pathWhat it returnsPlan
GET /v1/events?org=ufcMMA schedule + results API: full fight cards, venues, broadcasts, and a card-change diff log for late reshuffles.All plans
GET /v1/events/{slug}One event with its full fight card (both corners, results when completed), venue and event-level broadcasts.All plans
GET /v1/events/{slug}/changesThe card-change diff log: fight added or removed, opponent swapped, date or order moved.All plans
GET /v1/calendar/ufc.icsICS calendar feeds per organization · subscribe any calendar app to every event, auto-updating as cards change.All plans

The code

curl lists the next three cards. The Python block prints the next five in your own time zone, then the next card's bouts in running order; the JavaScript block adds each card's main event.

Every block runs as shown with your API key in the UFCAL_API_KEY environment variable. Python uses pip install ufcalendar and JavaScript or TypeScript uses npm install @ufcalendar/sdk; any HTTP client works too.

curl
curl "https://api.ufcalendar.com/v1/events?org=ufc&limit=3" \
  -H "Authorization: Bearer $UFCAL_API_KEY"
Python
# pip install ufcalendar
from datetime import datetime
from zoneinfo import ZoneInfo

from ufcalendar import FightAPI

api = FightAPI()  # reads UFCAL_API_KEY from the environment
here = ZoneInfo("America/New_York")  # the time zone you want to show


def parse(ts):
    return datetime.fromisoformat(ts.replace("Z", "+00:00"))


# A bare listing is the upcoming calendar, soonest first
for ev in api.events("ufc", limit=5):
    main = parse(ev["main_card_at"] or ev["starts_at"])
    ppv = "  (PPV)" if ev["is_ppv"] else ""
    print(f"{main.astimezone(here):%a %d %b %H:%M}  {ev['title']}{ppv}")

# The full card of the next event, in running order
nxt = next(api.events("ufc", limit=1))
for f in api.event(nxt["slug"])["card"]:
    if f["status"] != "cancelled":
        section = f["card_section"] or "-"
        print(f"{section:<14}{f['fighter_a']['name']} vs {f['fighter_b']['name']} ({f['weight_class']})")
JavaScript
// npm install @ufcalendar/sdk
import { FightAPI } from "@ufcalendar/sdk";

const api = new FightAPI(); // reads UFCAL_API_KEY from the environment
const when = new Intl.DateTimeFormat("en-GB", {
  timeZone: "Europe/London",
  weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit",
});

// Upcoming UFC cards, soonest first, with each card's main event
for await (const ev of api.events({ org: "ufc", limit: 5, include: ["headline"] })) {
  const main = new Date(ev.main_card_at ?? ev.starts_at);
  const bout = ev.headline ? `${ev.headline.fighter_a.name} vs ${ev.headline.fighter_b.name}` : "TBA";
  console.log(when.format(main), "|", ev.title, "|", bout, ev.is_ppv ? "(PPV)" : "");
}

Sample response

A real response from the live API, trimmed for length. … marks removed fields.

GET /v1/events?org=ufc&limit=3
{
  "data": [
    {
      "id": 2805,
      "slug": "ufc-fight-night-2026-10-31",
      "title": "UFC Fight Night: Moicano vs Nolan",
      "short_title": "Fight Night",
      "numbering": "Fight Night",
      "org": "ufc",
      "sport": "mma",
      "starts_at": "2026-10-31T21:00:00.000Z",
      "main_card_at": "2026-11-01T00:00:00.000Z",
      "prelims_at": "2026-10-31T21:00:00.000Z",
      "early_prelims_at": null,
      "tz": "America/Los_Angeles",
      "status": "announced",
      "is_ppv": false,
      "is_title_card": false
    },
    {
      "id": 2549,
      "slug": "ufc-fight-night-2026-11-07",
      "title": "UFC Fight Night: Bonfim vs Brady",
      "short_title": "Fight Night",
      "numbering": "Fight Night",
      "org": "ufc",
      "sport": "mma",
      "starts_at": "2026-11-07T22:00:00.000Z",
      "main_card_at": "2026-11-08T01:00:00.000Z",
      "prelims_at": "2026-11-07T22:00:00.000Z",
      "early_prelims_at": null,
      "tz": "America/Los_Angeles",
      "status": "announced",
      "is_ppv": false,
      "is_title_card": false
    },
    …
  ],
  "meta": {
    "pagination": { "next_cursor": "eyJpZCI6MjU2M30", "has_more": true, "limit": 3 }
  }
}

Notes and pitfalls

  • starts_at is the first bell of the night, usually the earliest prelims. main_card_at, prelims_at and early_prelims_at are the section times, and they are null when a promotion publishes no split. Every time is UTC; tz is the venue's IANA time zone.
  • A bare listing is the calendar: cards not yet over, including one that started a few hours ago, soonest first. Pass status=completed for past cards, or from and to (YYYY-MM-DD) for a date range.
  • Results come in pages. The Python and JavaScript clients follow meta.pagination.next_cursor for you; with plain HTTP, send it back as the cursor parameter.
  • Cards change late. Poll the card-change feed at GET /v1/changes, subscribe to the card.changed webhook on Pro, or give a calendar app the ICS feed at /v1/calendar/ufc.ics.

Related pages

More code guides

All code guides →

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

How do I get the upcoming UFC schedule in Python? | UFCalendar