# Get a fixture's match events

`GET /v1/fixtures/{id}/events`

A fixture's match events (goals, own goals, penalties, cards, substitutions, VAR
decisions) as known at `known_at`, as `ev_<digits>` match events, each a citable record
with its own identifier and versions. Governed by the `events` dataset: the organization needs a current
`events` grant (and the `read:entities` scope) whose competitions include the fixture's;
an unknown fixture is `404`, a fixture outside the grant `403 not-entitled`
(`restriction: competition`).

- **Versions and `known_at`.** Every event is the highest version recorded by the
  cutoff; a correction is a new version of the same `ev_` (a goal re-classified as an own
  goal, a corrected minute), so an earlier `known_at` serves the version before. An
  event the source's newer capture of the match drops is retracted and left out from
  then on; one the source withdrew itself is served with `rescinded: true`.
- **VAR.** A VAR decision is an event of its own (`kind: var_decision`, `detail` such as
  `goal_disallowed`); the goal it concerns is never edited, so a disallowed goal is the
  goal plus a later VAR decision.
- **Sides and persons.** `team_id` is the side the event counts for: an own goal is filed
  under the side it benefits, and `person_team_id` names the scorer's own side (the team
  of his lineup entry, when the caller's `lineups` grant also serves the fixture, with no
  longer delay, and the entry's source may serve lineups to it). For a
  substitution `person_id` is the player coming on and `related_person_id` the one going
  off; for a goal the related person is the assist. Teams and persons are the canonical
  identifiers at the cutoff. An event naming a person known only from sources you may
  not be served is left out, as `GET /v1/persons/{id}` answers `404`.
- **Order.** Match order: `minute`, `extra_minute` (none first), then the source's event
  order; a penalty shootout comes last. Each event the source reported is served once,
  also when two fixtures merged into one both recorded it.
- **Filters.** `team_id` (events counting for that team), `person_id` (events naming the
  person as player or related player) and `kind`, all canonical at the cutoff; a filter
  that matches nothing on an `available` fixture serves `available` with no events.
- **`status`.** `available`: the events are served. `unavailable`: no event is known for
  the fixture at the cutoff. `withheld`: events exist but a source of them holds no
  display right for events (`events` empty; nothing about them is disclosed). Sportmonks
  holds the display right.
- **Freshness delay** and **billing** as for lineups: a grant with a delay is served what
  was known at `request time - delay` at the latest, and a response that is not
  `available` is recorded with 0 units.

Source references (`sources`, with `read:sources`) appear on a served response and follow
the source-reference rules for events.

Parameters:
- `id` (path, string, required): Canonical or retired fixture identifier (`fx_<digits>`); another kind's prefix or an undecodable body is a 400 naming `id`.
- `known_at` (query, timestamp, optional): Knowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
- `team_id` (query, string, optional): Only the events counting for this team (canonical at the cutoff).
- `person_id` (query, string, optional): Only the events naming this person as the player or the related player (canonical at the cutoff).
- `kind` (query, enum, optional): Only the events of this kind. One of: `goal`, `own_goal`, `penalty_goal`, `penalty_missed`, `yellow_card`, `second_yellow`, `red_card`, `substitution`, `var_decision`, `shootout_goal`, `shootout_missed`.

Returns `200`: The fixture's match events as known at the cutoff.
The body is [the fixture events object](obj-FixtureEvents.md).

Errors: `400` Malformed parameter or cursor (`invalid-request`).; `401` Missing or invalid credential (`unauthenticated`).; `403` Operation not permitted (`forbidden`) or restricted by grants/rights (`not-entitled`).; `404` Unknown identifier at the requested cutoff (`not-found`).; `422` Well-formed but unanswerable (`invalid-range`, `unsupported-historical-capability`).; `429` The per-minute rate limit is used up (`rate-limited`) or a daily allowance is exhausted (`quota-exceeded`). Failed requests (403, 404, other 4xx, 5xx) use up the per-minute rate limit too.; `500` Unexpected failure (`internal-error`); `request_id` identifies the server-side record.; `503` A service this operation depends on, or the access check, is temporarily unavailable (`unavailable`, `policy-unavailable`).

Example request (200 · Withheld):

```bash
curl https://api.example.com/v1/fixtures/fx_1/events \
  -H "X-API-Key: $ODDSFINDER_API_KEY"
```

Example response (200):

```json
{
  "fixture_id": "fx_1",
  "status": "withheld",
  "events": [],
  "knowledge": {
    "known_at": "2026-10-03T19:00:00Z",
    "as_requested": false
  }
}
```
