---
title: "Complete career timeline"
method: GET
path: "/v1/fighters/{idOrSlug}/history"
tags: ["Fighters"]
---

# Complete career timeline

`GET /v1/fighters/{idOrSlug}/history`

## Request

- Base URL: `https://api.ufcalendar.com`
- URL: `https://api.ufcalendar.com/v1/fighters/{idOrSlug}/history`
- Auth: HTTP bearer

The fighter's FULL multi-promotion career: native tracked bouts (richest data, `source: "native"`) merged with the wider multi-promotion career record (`source: "history"`). Spans every promotion they fought in — not just launch orgs. **Every key is present on every row** (null when unknown), and each row carries `status` (one vocabulary across both sources: `win`, `loss`, `draw`, `no_contest`, `cancelled`, `upcoming`, `unknown`), `method_normalized`, `time_seconds` and an `opponent` object (`{id, slug, name}`, ids only on native rows) beside the raw `result` / `method` / `time` strings. Newest first; `meta.truncated` is true when the history rows hit their 500-row cap. `source_slug` names the publisher: `ufcalendar` on native rows; on history rows an official publisher (`ufc-official`, `wikipedia`, a promotion's `*-official`), else `public-records`.

## Path parameters

- `idOrSlug` string, required

## Response `200`

Timeline entries, newest first

- FighterHistoryResponse: Newest first.
  - `data` HistoryEntry[], required
    - `source` 'native' | 'history', required: `native` = a bout UFCalendar tracks (richest data); `history` = a career row from the wider multi-promotion record.
    - `fight_id` integer, nullable, required
    - `event_id` integer, nullable, required
    - `event_title` string, nullable, required
    - `event_name` string, nullable, required: Same as `event_title`.
    - `event_slug` string, nullable, required
    - `org_slug` string, nullable, required
    - `date` string, date, nullable, required: `native` rows: the UTC calendar day of the event's `starts_at` (first bell) — an evening card in the Americas starts after midnight UTC, so it can read one day after the venue's local date. `history` rows carry no time, only the date as the publisher printed it (usually the venue's local date).
    - `opponent_id` integer, nullable, required
    - `opponent_name` string, nullable, required
    - `opponent_slug` string, nullable, required
    - `opponent` HistoryOpponent, required
      - `id` integer, nullable, required
      - `slug` string, nullable, required
      - `name` string, nullable, required
    - `result` string, nullable, required: Raw result (`win`, `loss`, `draw`, `nc`, `no_contest`, `cancelled`, …). Prefer `status`.
    - `status` 'win' | 'loss' | 'draw' | 'no_contest' | 'cancelled' | 'upcoming' | 'unknown', required: One status vocabulary across native and history rows.
    - `method` string, nullable, required
    - `method_normalized` 'ko_tko' | 'submission' | 'technical_submission' | 'decision_unanimous' | 'decision_split' | 'decision_majority' | 'decision' | 'draw' | 'no_contest' | 'dq' | 'other', required: Closed vocabulary over every source spelling of a result method (`normalize.ts`). `other` = a non-empty method nothing matched.
    - `round` integer, nullable, required
    - `time` string, nullable, required
    - `time_seconds` integer, nullable, required
    - `weight_class` string, nullable, required
    - `is_title` boolean, nullable, required
    - `sport` string, nullable, required
    - `competition_level` string, nullable, required: `pro`, `amateur`, … (native rows are `pro`).
    - `source_slug` string, nullable, required: Who published the row: `ufcalendar` for native bouts; on history rows an official publisher's slug (`ufc-official`, `wikipedia`, a promotion's `*-official`), else `public-records`.
  - `meta` object, required
    - `truncated` boolean, required: true when the history rows hit their 500-row cap.
    - `ignored_params` string[]: Present only when the request carried query parameters this endpoint does not take — they were ignored. Same list as the `X-UFCalendar-Ignored-Params` header. Sorted, unique.

## Other responses

- `304`: Not Modified — `If-None-Match` matched the current weak `ETag`. Empty body.
- `308`: The slug is a retired alias (the event or fighter was renamed). Follow `Location` to the canonical URL; the numeric-id form never redirects.
- `401`: Missing/invalid API key (`unauthorized`).
- `403`: No active plan on the key's account (`subscription_required`) — choose a plan or start the free 1-day trial at https://www.ufcalendar.com/account/api.
- `404`: Not found (`not_found`; staged-org data 404s until the org is promoted).
- `429`: Rate limited (`rate_limited`) or monthly quota reached (`quota_exceeded`). Honor `Retry-After`.
- `500`: Something broke on our side (`internal_error`). It has been logged under the `request_id`.

---

[API](https://skmtc.dev/ufcalendar/apis/ufcalendar-fight-api.md) · [All operations](https://skmtc.dev/ufcalendar/apis/ufcalendar-fight-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ufcalendar/apis/ufcalendar-fight-api/revisions/9623cc8fb70b?raw)
