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

How do I get PFL, OKTAGON and BKFC fight data?

Use the same MMA Fight Data API endpoints as for the UFC and set org to pfl, oktagon or bkfc. Schedules, full cards with results, per-fight and per-round stats, official rankings and the consensus odds line come back in the same JSON, and GET /v1/orgs tells you what each promotion supports before you build a screen for it.

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

Endpoints used

Endpoints used
Method & pathWhat it returnsPlan
GET /v1/orgsEvery covered promotion with its sport and capability flags: stats, rounds, rankings, broadcasts, predictions, scorecards and odds.All plans
GET /v1/events?org=pflMMA 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/rankings/{org}Official ranking boards, point-in-time back to 2013 for the UFC. Champions across every launch org.All plans

The code

curl and Python read each promotion's capability flags, then the next card for all three; the JavaScript block fetches each promotion's latest completed card and its main event result.

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/orgs" \
  -H "Authorization: Bearer $UFCAL_API_KEY"
Python
# pip install ufcalendar
from ufcalendar import FightAPI

api = FightAPI()  # reads UFCAL_API_KEY from the environment

# What each promotion supports, straight from the API
for org in api.orgs():
    caps = [k for k, v in org["capabilities"].items() if v]
    print(f"{org['short_name']:<8} {org['sport']:<20} {', '.join(caps)}")

# The same calls work for every promotion: only `org` changes
for slug in ("pfl", "oktagon", "bkfc"):
    ev = next(api.events(slug, limit=1))
    print(f"{slug:<8} next card: {ev['starts_at'][:10]}  {ev['title']}")
JavaScript
// npm install @ufcalendar/sdk
import { FightAPI } from "@ufcalendar/sdk";

const api = new FightAPI(); // reads UFCAL_API_KEY from the environment

// Latest completed card per promotion, with its main event result
for (const org of ["pfl", "oktagon", "bkfc"]) {
  for await (const ev of api.events({ org, status: "completed", limit: 1 })) {
    const { card } = await api.event(ev.slug);
    const main = card.find((f) => f.is_main) ?? card[0];
    const winner = [main.fighter_a, main.fighter_b].find((c) => c?.id === main.result?.winner_fighter_id);
    console.log(`${ev.title} (${card.length} bouts): ${winner?.name ?? "no winner"} by ${main.result?.method ?? "-"}`);
  }
}

Sample response

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

GET /v1/orgs
{
  "data": [
    {
      "id": 2,
      "slug": "pfl",
      "name": "Professional Fighters League",
      "short_name": "PFL",
      "country_code": "US",
      "sport": "mma",
      "capabilities": {
        "stats": true,
        "rounds": true,
        "rankings": true,
        "broadcasts": true,
        "predictions": false,
        "scorecards": true,
        "odds": true
      }
    },
    {
      "id": 857,
      "slug": "bkfc",
      "name": "Bare Knuckle Fighting Championship",
      "short_name": "BKFC",
      "country_code": "US",
      "sport": "bare-knuckle-boxing",
      "capabilities": {
        "stats": true,
        "rounds": true,
        "rankings": true,
        "broadcasts": true,
        "predictions": false,
        "scorecards": false,
        "odds": true
      }
    },
    …
  ]
}

Notes and pitfalls

  • BKFC is bare-knuckle boxing: sport is bare-knuckle-boxing, its stats are punch counts, and it publishes no commission scorecards, so capabilities.scorecards is false.
  • Read capabilities before you render a feature. Model predictions cover the UFC only, so a PFL or OKTAGON screen should not expect them.
  • Method wording follows each promotion, for example SUB or Unanimous Decision. Use method_normalized when you compare results across promotions.
  • Each of the three has its own official rankings board; the point-in-time history back to 2013 is the UFC's. One API key covers every promotion, UFC and RIZIN included.

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 PFL, OKTAGON and BKFC fight data? | UFCalendar