- Record
- 13-2-0
- Height
- 5'7"
- Reach
- 65"
- Stance
- Orthodox
- Weight
- 125 lb
- Fights
- 9
Documentation
Base URL https://ufc.proptechusa.ai. Data contract 2026-09-06.3, Fight DNA definitions v1. Every response is { ok, data, meta } or { ok:false, data:null, error, meta }. Every example below is a schema example: a real response captured from the canonical API on Sep 7, 2026 and pinned here, so the shape, field names and semantics you read are exactly what you receive. Pinned examples do not move. For values on the published refresh cadence, see the live demos on the home page, which carry their own capture time and freshness state. Each important endpoint shows request → response → what you can build.
pt_ufc_live_<id>_<secret>) is provisioned automatically and shown once on the dashboard.export UFC_API_KEY=pt_ufc_live_…curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3const res = await fetch("https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} Read data; keep meta.request_id for support; watch X-Quota-Remaining. Or skip the terminal: open the Workspace, paste your key and run the current card.
403 plan_required; anything else under /v1 is 404 route_not_found.curl -H "Authorization: Bearer $UFC_API_KEY" https://ufc.proptechusa.ai/v1/ufc
# equivalent
curl -H "X-API-Key: $UFC_API_KEY" https://ufc.proptechusa.ai/v1/ufc X-API-Key. The key id (12 characters after pt_ufc_live_) is safe to log; the secret is not.401 api_key_required, invalid_api_key, api_key_expired, api_key_revoked, api_key_suspended.One key per subscription, tied to a plan and a channel. Manage it on the dashboard: copy, rotate (new secret issued once, old key revoked immediately, subscription stays attached), see usage, denied requests and recent calls, and open the Stripe customer portal. Enterprise keys can carry per-key overrides for quota and rate limit.
| Plan | Price | Requests / month | Requests / minute | At the limit | Unlocks |
|---|---|---|---|---|---|
| Developer | $79/mo | 25,000 | 60 | 429 quota_exceeded | Core UFC data |
| Pro | $199/mo | 100,000 | 180 | 429 quota_exceeded | Fighter intelligence |
| Ultra | $499/mo | 500,000 | 600 | 429 quota_exceeded | Matchup intelligence |
| Scale | $1499/mo | 2,000,000 | 1200 | allowed, X-Quota-Status: over-quota-soft | Production infrastructure |
| Enterprise | Let's talk | custom | custom | custom | Custom |
Headers on every response: X-Request-Id, X-Upstream-Request-Id, X-API-Version, X-Gateway-Version, X-Plan, X-RateLimit-Limit/Remaining/Reset, X-Quota-Limit/Remaining/Reset, Retry-After (429 only). Denied requests never consume quota. Cache-Control: private, max-age=N mirrors canonical freshness: short for upcoming cards, rankings and search; longer for history and as-of DNA.
| Status | Code | Meaning |
|---|---|---|
401 | api_key_required | No credential sent. |
401 | invalid_api_key | Malformed or unknown key, or secret mismatch. |
401 | api_key_expired | Key past expires_at. |
401 | api_key_revoked | Key revoked or rotated. |
401 | api_key_suspended | Subscription not active (unpaid, canceled). Manage it in the dashboard. |
403 | plan_required | Endpoint or parameter needs a higher plan; detail carries required_plan, current_plan, upgrade_url. |
404 | route_not_found | Path is not part of the commercial contract (no upstream call is made). |
429 | rate_limited | Per-minute limit hit; Retry-After set. |
429 | quota_exceeded | Monthly quota hit on a hard-limit plan; Retry-After set. |
502 / 504 | upstream_unavailable / upstream_timeout | Canonical API unreachable or slow. |
Canonical API errors pass through unchanged:
| Status | Codes | Meaning |
|---|---|---|
400 | invalid_include · invalid_ids · too_many_ids · invalid_as_of · invalid_stance · invalid_metric · invalid_bound · invalid_confidence · invalid_type · invalid_fighter_id · invalid_matchup | Validation errors from the canonical API; detail lists allowed values. |
404 | event_not_found · fighter_not_found · bout_not_found · article_not_found · division_not_found | Unknown entity. |
404 | dna_not_available | No Fight DNA snapshot for the fighter (or none at/before as_of). detail.reason: no_snapshot | no_snapshot_at_or_before_as_of. |
503 | rankings_not_available · dna_not_available · ledger_not_available · videos_not_available | The store does not exist yet; data is null, nothing is synthesized. |
null, an explicit status, or a 404/503 with a reason.GET /v1/ufc/events?status=upcoming|recent|all&date=YYYY-MM-DD&limit=N, then GET /v1/ufc/events/{id} by UUID, UFCStats id or ESPN event id.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3const res = await fetch("https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/events?status=upcoming&limit=3",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} {
"ok": true,
"data": [
{
"id": "187505ab-636d-4f90-8d5f-d98ebfd1cd7c",
"ufcstats_id": null,
"espn_event_id": "600060736",
"name": "Dana White's Contender Series: Season 10, Week 5",
"event_date": "2026-09-08",
"venue": "Meta APEX",
"city": "Las Vegas",
"region": "NV",
"country": "USA",
"commission": null,
"is_ppv": null,
"card_status": "announced",
"updated_at": "2026-09-07T06:03:34.55+00:00"
},
{
"id": "1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52",
"ufcstats_id": "638cfec7ec559d6e",
"espn_event_id": "600060772",
"name": "Noche UFC: Silva vs. Delgado",
"event_date": "2026-09-12",
"venue": "Desert Diamond Arena",
"city": "Glendale",
"region": "AZ",
"country": "USA",
"commission": null,
"is_ppv": null,
"card_status": "announced",
"updated_at": "2026-09-07T06:03:41.716+00:00"
}
],
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "299c1248-929c-4612-aa4c-f221e5f1d01a",
"count": 3,
"total": 17,
"status": "upcoming",
"date": null,
"access_tier": "public"
}
} | Date | Event | Venue | Status |
|---|---|---|---|
| 2026-09-08 | Dana White's Contender Series: Season 10, Week 5 | Meta APEX, Las Vegas | announced |
| 2026-09-12 | Noche UFC: Silva vs. Delgado | Desert Diamond Arena, Glendale | announced |
| 2026-09-15 | Dana White's Contender Series: Season 10, Week 6 | Meta APEX, Las Vegas | announced |
GET /v1/ufc/events/{id}/card?include=media,results,stats returns event plus ordered bouts[] with both fighters, images and results. include=stats (round rows per bout) requires Pro.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/events/1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52/cardconst res = await fetch("https://ufc.proptechusa.ai/v1/ufc/events/1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52/card", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/events/1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52/card",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} {
"ok": true,
"data": {
"event": {
"id": "1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52",
"ufcstats_id": "638cfec7ec559d6e",
"espn_event_id": "600060772",
"name": "Noche UFC: Silva vs. Delgado",
"event_date": "2026-09-12",
"venue": "Desert Diamond Arena",
"city": "Glendale",
"region": "AZ",
"country": "USA",
"commission": null,
"is_ppv": null,
"card_status": "announced",
"updated_at": "2026-09-07T06:03:41.716+00:00"
},
"bouts": [
{
"id": "89e38074-f431-4bc3-b51e-fe42058e60d0",
"bout_order": 13,
"weight_class": "FEATHERWEIGHT",
"scheduled_rounds": 5,
"fighter_a": {
"id": "eed368a5-484b-412f-9d2c-a4fd6d24d019",
"name": "Jean Silva",
"…": "record, stance, primary_image"
},
"fighter_b": {
"id": "55ef67ad-88fe-4f7a-b4cb-dc9a10c12feb",
"name": "Jose Miguel Delgado",
"…": "…"
},
"result": null
}
],
"…": "12 more bouts"
},
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "9ff18c79-ee61-4832-b2d5-1a45c9d7b9ab",
"include": [],
"bouts": 13,
"access_tier": "public"
}
}
GET /v1/ufc/fighters?q=&active=true to search, GET /v1/ufc/fighters/{id}?include=media,ranking,next,history,stats,videos for the composite profile (ids: UUID, UFCStats or ESPN athlete id). include=stats requires Pro. History: /fighters/{id}/history?limit=.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6?include=ranking,next,history&history_limit=5const res = await fetch("https://ufc.proptechusa.ai/v1/ufc/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6?include=ranking,next,history&history_limit=5", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6?include=ranking,next,history&history_limit=5",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} {
"ok": true,
"data": {
"id": "2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6",
"ufcstats_id": "34ff304266360297",
"espn_athlete_id": "4608674",
"name": "Manon Fiorot",
"nickname": "The Beast",
"dob": "1990-02-17",
"height_in": 67,
"reach_in": 65,
"weight_lbs": 125,
"stance": "ORTHODOX",
"record_w": 13,
"record_l": 2,
"record_d": 0,
"record_nc": 0,
"is_active": true,
"career_slpm": 5.66,
"career_str_acc": 42,
"career_sapm": 3.58,
"career_str_def": 66,
"career_td_avg": 1.05,
"career_td_acc": 29,
"career_td_def": 87,
"career_sub_avg": 0,
"fight_history_count": 9,
"updated_at": "2026-09-06T16:30:42.017224+00:00",
"slug_id": "4608674",
"primary_image": {
"id": "61827143-8f84-4f0d-8e06-53486dcc22ac",
"image_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/portrait.jpg",
"card_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/card.jpg",
"thumb_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/thumb.jpg",
"author": "Lucie Bertaud",
"license": "CC BY 3.0",
"source_url": "https://commons.wikimedia.org/wiki/File:MANON_FIOROT_ET_ALDRIC_CASSATA,_LE_COUPLE_GOAL_DU_MMA_-_MMA_EXTRA_ROUND_-22_-_YouTube_-_0-28-31_(cropped).jpg",
"kind": "wikimedia",
"attribution_text": "Lucie Bertaud, CC BY 3.0, via Wikimedia Commons",
"rights_label": "CC BY 3.0"
},
"next_bout": {
"id": "c5ab710f-9440-4142-b87f-d2de30c1780d",
"ufcstats_id": "d9712b45c094730e",
"espn_competition_id": "401897734",
"event_id": "1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52",
"weight_class": "FLYWEIGHT",
"weight_class_raw": "Women's Flyweight",
"is_womens": true,
"is_title": false,
"scheduled_rounds": 3,
"card_position": "main",
"bout_order": 10,
"status": "announced",
"replaced_bout_id": null,
"short_notice_days": null,
"fighter_a": {
"id": "2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6",
"dob": "1990-02-17",
"name": "Manon Fiorot",
"stance": "ORTHODOX",
"nickname": "The Beast",
"reach_in": 65,
"record_d": 0,
"record_l": 2,
"record_w": 13,
"height_in": 67,
"is_active": true,
"record_nc": 0,
"weight_lbs": 125,
"ufcstats_id": "34ff304266360297",
"espn_athlete_id": "4608674"
},
"fighter_b": {
"id": "1d296292-4969-43a8-9948-cd0a76a642ce",
"dob": "1993-08-09",
"name": "Alexa Grasso",
"stance": "ORTHODOX",
"nickname": null,
"reach_in": 66,
"record_d": 1,
"record_l": 5,
"record_w": 17,
"height_in": 65,
"is_active": true,
"record_nc": 0,
"weight_lbs": 126,
"ufcstats_id": "e8b731feff72294b",
"espn_athlete_id": "3136287"
},
"result": null,
"event": {
"id": "1d0b22df-81e7-4e5b-8fa5-8e5d03c24c52",
"city": "Glendale",
"name": "Noche UFC: Silva vs. Delgado",
"venue": "Desert Diamond Arena",
"is_ppv": null,
"region": "AZ",
"country": "USA",
"commission": null,
"event_date": "2026-09-12",
"updated_at": "2026-09-07T06:03:41.716+00:00",
"card_status": "announced",
"ufcstats_id": "638cfec7ec559d6e",
"espn_event_id": "600060772"
},
"is_fighter_a": true,
"opponent": {
"id": "1d296292-4969-43a8-9948-cd0a76a642ce",
"name": "Alexa Grasso",
"nickname": null,
"ufcstats_id": "e8b731feff72294b",
"espn_athlete_id": "3136287",
"slug_id": "3136287",
"record_w": 17,
"record_l": 5,
"record_d": 1,
"record_nc": 0,
"primary_image": {
"id": "85e0a287-fae3-43d1-be20-0fa490c01fb8",
"image_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/1d296292-4969-43a8-9948-cd0a76a642ce/portrait.jpg",
"card_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/1d296292-4969-43a8-9948-cd0a76a642ce/card.jpg",
"thumb_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/1d296292-4969-43a8-9948-cd0a76a642ce/thumb.jpg",
"author": "Alexa Lopez Col",
"license": "CC BY 3.0",
"source_url": "https://commons.wikimedia.org/wiki/File:Alexa_Grasso_2023_03.png",
"kind": "wikimedia",
"attribution_text": "Alexa Lopez Col, CC BY 3.0, via Wikimedia Commons",
"rights_label": "CC BY 3.0"
}
},
"outcome": null
}
},
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "ea40960e-eaf1-4048-ad39-c4c2b09c271c",
"include": [
"ranking",
"next",
"history"
],
"history_count": 3,
"access_tier": "public"
}
}
GET /v1/ufc/bouts/{id} for one bout; GET /v1/ufc/bouts/{id}/stats for every UFC Stats round row (kd, sig_str_*, total_str_*, td_*, sub_att, rev, ctrl_sec, head/body/leg and distance/clinch/ground splits) plus per-fighter totals, fight_time_sec and provenance. Bouts without rows return empty arrays. Career aggregates with computed rates: GET /v1/ufc/fighters/{id}/stats (Pro).
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/statsconst res = await fetch("https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/stats", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/stats",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} GET /v1/ufc/results?limit=N: most recent completed bouts with winner, method, round and time. Results are ESPN-sourced facts; a bout without a result has result: null.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/results?limit=10const res = await fetch("https://ufc.proptechusa.ai/v1/ufc/results?limit=10", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/results?limit=10",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} GET /v1/ufc/rankings?division=&womens=: the verified ufc.com snapshot with per-division champion and entries, linked to canonical fighter ids. Attribution is required: render source and source_url. 503 rankings_not_available when no store exists.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/rankings?division=FEATHERWEIGHTconst res = await fetch("https://ufc.proptechusa.ai/v1/ufc/rankings?division=FEATHERWEIGHT", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/rankings?division=FEATHERWEIGHT",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"}
Movsar Evloev —
Diego Lopes —
Aljamain Sterling —
Yair Rodriguez —
Jean Silva — Fighter rows carry primary_image (image_url, card_url 800×1000, thumb_url 320×400) with author, license, source_url, kind, attribution_text and rights_label; fighter detail adds images[]; GET /v1/ufc/fighters/media?ids=… maps up to 150 ids. Render the credit wherever the image is shown; the file's license governs reuse. Official video metadata (/videos, /fighters/{id}/videos, /events/{id}/videos) returns ids, official URLs, embed_url and attribution; play through the provider, never rehost.
{
"id": "61827143-8f84-4f0d-8e06-53486dcc22ac",
"image_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/portrait.jpg",
"card_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/card.jpg",
"thumb_url": "https://tkmlnhmylqnttmnsnief.supabase.co/storage/v1/object/public/ufc-media/fighters/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/thumb.jpg",
"author": "Lucie Bertaud",
"license": "CC BY 3.0",
"source_url": "https://commons.wikimedia.org/wiki/File:MANON_FIOROT_ET_ALDRIC_CASSATA,_LE_COUPLE_GOAL_DU_MMA_-_MMA_EXTRA_ROUND_-22_-_YouTube_-_0-28-31_(cropped).jpg",
"kind": "wikimedia",
"attribution_text": "Lucie Bertaud, CC BY 3.0, via Wikimedia Commons",
"rights_label": "CC BY 3.0"
} GET /v1/ufc/fighters/{id}/dna[?as_of=YYYY-MM-DD]: the fighter's snapshot with metrics (striking, pace, grappling, finish), stance_splits, round_profile, finish_profile, context_splits, position_profile and provenance. Family routes: /splits?opponent_stance=, /round-profile, /finish-profile, /position-profile. Definitions for every metric: GET /v1/ufc/dna/metrics (all plans).
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/dnaconst res = await fetch("https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/dna", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/fighters/ec94d296-2db3-4e0d-be6a-46de4f480672/dna",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} {
"ok": true,
"data": {
"fighter": {
"id": "ec94d296-2db3-4e0d-be6a-46de4f480672",
"name": "Sean Strickland"
},
"snapshot": {
"as_of_date": "2026-09-06",
"definition_version": 1,
"sample_bouts": 3,
"sample_rounds": 8,
"sample_seconds": 2243,
"coverage_status": "low",
"metrics": {
"sig_landed_per_min": {
"unit": "per_min",
"value": 6.2327,
"origin": "pbe_derived",
"numerator": 233,
"as_of_date": "2026-09-06",
"confidence": "medium",
"metric_key": "sig_landed_per_min",
"denominator": 2243,
"sample_bouts": 2,
"sample_rounds": 8,
"sample_seconds": 2243,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
},
"finish_rate": {
"unit": "ratio",
"value": 0.5,
"origin": "pbe_derived",
"numerator": 1,
"as_of_date": "2026-09-06",
"confidence": "low",
"metric_key": "finish_rate",
"denominator": 2,
"sample_bouts": 2,
"sample_rounds": 8,
"sample_seconds": 2243,
"coverage_status": "high",
"source_families": [
"espn",
"ufcstats"
],
"definition_version": 1
},
"…": "more metric keys"
},
"…": "stance_splits, round_profile, finish_profile, context_splits, provenance"
}
},
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "bb5b2e51-f863-477d-aeb2-94486fb9fcd9",
"requested_as_of": null,
"resolved_as_of": "2026-09-06",
"definition_version": 1,
"as_of_semantics": "as_of_date is exclusive: the snapshot dated D contains bouts with event_date < D, so a bout fought on D is excluded by the snapshot dated D. ?as_of=D resolves to the latest stored snapshot with as_of_date <= D, which therefore never contains a bout fought on or after D.",
"origin": "pbe_derived",
"origin_label": "PBE DERIVED",
"access_tier": "public"
}
}
Registry families: stance, striking, pace, grappling, finish, context. See the methodology for every definition.
GET /v1/ufc/matchups/{a}/{b}/dna[?as_of=] compares 18 paired metrics (delta, direction, comparable), adds stance_context, and emits insights[] only above the thresholds in meta.insight_rules; the rest is named in warnings[]. Also Ultra: /dna/query, /bouts/{id}/ledger, /events/{id}/intelligence.
curl \
-H "Authorization: Bearer $UFC_API_KEY" \
https://ufc.proptechusa.ai/v1/ufc/matchups/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/1d296292-4969-43a8-9948-cd0a76a642ce/dnaconst res = await fetch("https://ufc.proptechusa.ai/v1/ufc/matchups/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/1d296292-4969-43a8-9948-cd0a76a642ce/dna", {
headers: { Authorization: `Bearer ${UFC_API_KEY}` },
});
const { ok, data, meta } = await res.json();res = requests.get("https://ufc.proptechusa.ai/v1/ufc/matchups/2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6/1d296292-4969-43a8-9948-cd0a76a642ce/dna",
headers={"Authorization": f"Bearer {UFC_API_KEY}"})
body = res.json() # {"ok", "data", "meta"} {
"ok": true,
"data": {
"fighters": [
{
"id": "2c9c2a88-aec1-4bf0-9b16-3ce58adf6fd6",
"name": "Manon Fiorot",
"stance": "ORTHODOX"
},
{
"id": "1d296292-4969-43a8-9948-cd0a76a642ce",
"name": "Alexa Grasso",
"stance": "ORTHODOX"
}
],
"comparisons": [
{
"key": "sig_landed_per_min",
"label": "Sig. strikes landed / min",
"unit": "per_min",
"family": "striking",
"higher_is_better": true,
"mismatch": null,
"min_abs_delta": null,
"a": {
"unit": "per_min",
"value": 12.973,
"origin": "pbe_derived",
"numerator": 16,
"as_of_date": "2026-09-06",
"confidence": "low",
"metric_key": "sig_landed_per_min",
"denominator": 74,
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 74,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
},
"b": {
"unit": "per_min",
"value": 4.4444,
"origin": "pbe_derived",
"numerator": 12,
"as_of_date": "2026-09-06",
"confidence": "low",
"metric_key": "sig_landed_per_min",
"denominator": 162,
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 162,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
},
"delta": 8.5286,
"direction": "a",
"comparable": true,
"min_confidence": "low"
},
{
"key": "sig_absorbed_per_min",
"label": "Sig. strikes absorbed / min",
"unit": "per_min",
"family": "striking",
"higher_is_better": false,
"mismatch": null,
"min_abs_delta": null,
"a": {
"unit": "per_min",
"value": 1.6216,
"origin": "pbe_derived",
"numerator": 2,
"as_of_date": "2026-09-06",
"confidence": "low",
"metric_key": "sig_absorbed_per_min",
"denominator": 74,
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 74,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
},
"b": {
"unit": "per_min",
"value": 1.8519,
"origin": "pbe_derived",
"numerator": 5,
"as_of_date": "2026-09-06",
"confidence": "low",
"metric_key": "sig_absorbed_per_min",
"denominator": 162,
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 162,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
},
"delta": -0.2303,
"direction": "b",
"comparable": true,
"min_confidence": "low"
}
],
"insights": [
{
"key": "head_attack_share_mismatch",
"label": "Head attack share mismatch",
"value": 0.1472,
"unit": "ratio",
"a_value": 0.963,
"b_value": 0.8158,
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 74,
"samples": {
"a": {
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 74,
"confidence": "low"
},
"b": {
"sample_bouts": 1,
"sample_rounds": 1,
"sample_seconds": 162,
"confidence": "low"
}
},
"confidence": "low",
"direction": "a",
"side": "a",
"metric_keys": [
"head_attack_share"
],
"explanation": "Head attack share: Manon Fiorot 96% (1 bout / 1 round / 1.2 min) vs Alexa Grasso 82% (1 bout / 1 round / 2.7 min); delta +15% toward Manon Fiorot.",
"origin": "pbe_derived"
}
],
"warnings": [
"Manon Fiorot vs orthodox opponents: 1 appearance, confidence low; needs >= 3 appearances and confidence >= low. No stance insight emitted.",
"Alexa Grasso vs orthodox opponents: 0 appearances, confidence insufficient; needs >= 3 appearances and confidence >= low. No stance insight emitted."
],
"…": "stance_context, bettors_edge_evidence, note"
},
"meta": {
"resolved_as_of": {
"a": "2026-09-06",
"b": "2026-09-06"
},
"insights": 5,
"warnings": 8
}
} 

| 65" | Reach | 66" |
|---|---|---|
| Orthodox | Stance | Orthodox |
| 12.97 | Pace (sig. landed/min)low / low | 4.44 |
| 59% | Strike accuracylow / low | 32% |
| 59% | Distance sharelow / low | 97% |
| 0.00 | Takedown attempts /15low / low | 0.00 |
| — | Takedown accuracylow / low | — |
| — | Pace retention R3/R1insufficient / insufficient | — |
| 100% | Finish rate (wins)insufficient / insufficient | 100% |
warnings[] instead of being guessed.as_of_date is exclusive: the snapshot dated D contains bouts with event_date < D, so a bout fought on D is excluded by the snapshot dated D. ?as_of=D resolves to the latest stored snapshot with as_of_date <= D, which therefore never contains a bout fought on or after D.
Add ?as_of=YYYY-MM-DD to fighter DNA routes (Pro) or Matchup DNA (Ultra). meta.requested_as_of / meta.resolved_as_of report the snapshot used. A date before the first snapshot is a truthful 404:
{
"ok": false,
"data": null,
"error": {
"code": "dna_not_available",
"message": "No Fight DNA snapshot exists for Sean Strickland at or before 2024-01-01. Nothing is synthesized.",
"detail": {
"fighter_id": "ec94d296-2db3-4e0d-be6a-46de4f480672",
"requested_as_of": "2024-01-01",
"definition_version": 1,
"reason": "no_snapshot_at_or_before_as_of"
}
},
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "475fa213-d202-4353-a79d-d31519c3b4a3"
}
} | Tier | Rule |
|---|---|
insufficient | sample below the metric's registry minimum (min_bouts / min_rounds / min_seconds); value is null when there is no denominator |
low | minimum met but sample_bouts < 3 (result metrics) or sample_seconds < 1800 (rate metrics) |
medium | sample_bouts < 8 (result metrics) or sample_seconds < 5400 (rate metrics) |
high | sample_bouts >= 8 (result metrics) or sample_seconds >= 5400 (rate metrics) |
coverage_status uses the same scale for stat coverage of the sample. Present insufficient and low as exactly that.
Every derived value is a MetricObject; the gateway never strips it.
{
"unit": "per_min",
"value": 6.2327,
"origin": "pbe_derived",
"numerator": 233,
"as_of_date": "2026-09-06",
"confidence": "medium",
"metric_key": "sig_landed_per_min",
"denominator": 2243,
"sample_bouts": 2,
"sample_rounds": 8,
"sample_seconds": 2243,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
} GET /v1/ufc/fighters?q=fiorot → take id (or accept a UFCStats / ESPN id directly).GET /v1/ufc/fighters/{id}?include=ranking,next,history&history_limit=10 → name, record, height/reach/stance, primary_image (+ credit), ranking positions, next bout, recent history.GET /v1/ufc/fighters/{id}/stats → computed.career_rates with provenance; label as display aggregates.GET /v1/ufc/fighters/{id}/dna → render metrics with their confidence; show the sample line; hide nothing.Result: the fighter profile demo on the homepage, rendered from exactly these responses. Try it live in the Workspace.
Production example
See how this is used in a real product: A fighter profile on PropBetEdge UFC →
Fighter pages on the production application are built from the same fighter, stats and Fight DNA responses documented above.
GET /v1/ufc/events?status=upcoming&limit=1 → the next event id.GET /v1/ufc/events/{id}/card?include=media,results → bouts[] ordered main event first (bout_order), with card_position (main, prelim, early_prelim), weight class, scheduled rounds, title flag, both fighters with images, and result when fought.card_position; render the highest bout_order as the main event; credit every portrait.GET /v1/ufc/events/{id}/videos for the official fight-week video timeline (link out, never rehost).See Fight Week on the homepage or run Current card in the Workspace.
Production example
See how this is used in a real product: Fight Week on PropBetEdge UFC →
The production Fight Week view is composed from the event card response, per-bout fighters and their media.
GET /v1/ufc/matchups/{a}/{b}/dna (Ultra).fighters[] (reach, stance, record, rank); paired rows from comparisons[] (comparable=false → show “—”, never a placeholder number); stance_context for the stance story.insights[] as the read, each with its confidence and sample; surface warnings[] so users see what was not claimed.Live: Workspace matchup builder.
Production example
See how this is used in a real product: A matchup page on PropBetEdge UFC →
Matchup pages render comparisons[], insights[] and warnings[] exactly as returned, with non-comparable rows shown as em-dashes.
GET /v1/ufc/rankings (all divisions, official order) or ?division=FEATHERWEIGHT.champion; list from entries[] with rank, change, is_new; ties are real, ranks may skip.fighter.id values and call GET /v1/ufc/fighters/media?ids=a,b,c (≤150) once; render credits.source / source_url (ufc.com) and snapshot_date.Production example
See how this is used in a real product: Rankings on PropBetEdge UFC →
The production rankings screen renders the same official snapshot, with portraits from one bulk media call.
/fighters/{id} per bout (or reuse card payload)./fighters/{id}/dna (Pro) for each side; /matchups/{a}/{b}/dna (Ultra) for the read; /events/{id}/intelligence (Ultra) for the ledger view across the card./rankings for implications, /events/{id}/videos for official media, /news for PropBetEdge editorial.Production example
See how this is used in a real product: Fight Week on PropBetEdge UFC →
PropBetEdge UFC's Fight Week is one production implementation of this exact flow: card, faces, per-side Fight DNA, the matchup read and ranking implications.
| Endpoint | Summary | Origin | Minimum plan |
|---|---|---|---|
/v1/ufc | API index | source fact | Developer |
/v1/ufc/events | List events (upcoming, recent, all, by date) | source fact | Developer |
/v1/ufc/events/{id} | Event by UUID, UFCStats id or ESPN id | source fact | Developer |
/v1/ufc/events/{id}/card | Event plus its ordered fight card | source fact | Developer |
/v1/ufc/events/{id}/articles | PropBetEdge articles for an event | editorial | Developer |
/v1/ufc/events/{id}/videos | Official video metadata for an event, grouped for the fight-week timeline | third party link | Developer |
/v1/ufc/events/{id}/intelligence | Fight Week intelligence per bout from the Fight State Ledger | pbe derived | Ultra |
/v1/ufc/fighters | Search and list fighters | source fact | Developer |
/v1/ufc/fighters/media | Bulk primary_image map (max 150 ids) | media | Developer |
/v1/ufc/fighters/{id} | Fighter profile composite (include=media,ranking,next,history,stats,videos) | source fact | Developer |
/v1/ufc/fighters/{id}/history | Fighter bout history | source fact | Developer |
/v1/ufc/fighters/{id}/stats | Career round rows plus computed rates and per-bout aggregates | pbe derived | Pro |
/v1/ufc/fighters/{id}/articles | PropBetEdge articles for a fighter | editorial | Developer |
/v1/ufc/fighters/{id}/videos | Official video metadata for a fighter | third party link | Developer |
/v1/ufc/fighters/{id}/dna | Fighter Fight DNA snapshot (metrics, stance splits, round, finish, context) | pbe derived | Pro |
/v1/ufc/fighters/{id}/splits | Stance DNA split rows | pbe derived | Pro |
/v1/ufc/fighters/{id}/round-profile | Round DNA profile | pbe derived | Pro |
/v1/ufc/fighters/{id}/finish-profile | Finish DNA profile | pbe derived | Pro |
/v1/ufc/fighters/{id}/position-profile | Position profile (licensed family; explicit unavailable until a licensed source exists) | licensed | Pro |
/v1/ufc/bouts/{id} | Bout detail | source fact | Developer |
/v1/ufc/bouts/{id}/stats | Round-level statistics for a bout | source fact | Developer |
/v1/ufc/bouts/{id}/videos | Official video metadata for a bout | third party link | Developer |
/v1/ufc/bouts/{id}/ledger | Fight State Ledger snapshots and deterministic diffs | pbe derived | Ultra |
/v1/ufc/matchups/{fighterA}/{fighterB}/dna | Matchup DNA | pbe derived | Ultra |
/v1/ufc/results | Recent results | source fact | Developer |
/v1/ufc/rankings | Official rankings snapshot (ufc.com) | source fact | Developer |
/v1/ufc/news | PropBetEdge newsroom list | editorial | Developer |
/v1/ufc/articles/{slug} | PropBetEdge article | editorial | Developer |
/v1/ufc/wire | Third-party headline wire (Enterprise / first-party only pending rights review) | third party link | Enterprise |
/v1/ufc/search | Search fighters, events and articles | source fact | Developer |
/v1/ufc/counts | Coverage counts | source fact | Developer |
/v1/ufc/videos | Official video metadata feed | third party link | Developer |
/v1/ufc/dna/metrics | Fight DNA metric registry | pbe derived | Developer |
/v1/ufc/dna/query | Cross-fighter Fight DNA query | pbe derived | Ultra |
| Label | Where | Rule |
|---|---|---|
| Source | events, fighters, bouts, results, round stats, rankings | Normalized ESPN / UFC Stats / ufc.com facts. Attribute the source where displayed. |
| PBE derived | Fight DNA, Matchup DNA, computed career rates, ledger diffs | PropBetEdge analytics. Show sample and confidence. Never present as official statistics or predictions. |
| Licensed | position profile (reserved) | Licensed enrichment, labelled separately when it exists. |
| Editorial | news, articles | PropBetEdge newsroom content. |
| Media | primary_image, images[], hero_image | Render attribution_text; each file's license governs reuse. |
| Third-party link | videos, wire | Ids and official URLs only. Provider player; never rehost. |
The commercial contract is generated from the canonical API's OpenAPI plus the entitlement config, so data schemas (MetricObject, StanceSplit, DnaSnapshot, MatchupDna, Video, PrimaryImage, envelopes) are byte-identical to upstream and every operation carries x-plan and x-origin. Servers: https://ufc.proptechusa.ai (commercial) and https://ufc-api.propbetedge.ai (canonical, first-party). Import openapi.json into your client generator, or browse the interactive reference.