OddsFinder API
Canonical football data with full revision history.
The OddsFinder API serves football competitions, teams, persons, fixtures, results and match facts, each as it was known at any point in time. Conventions that apply to every operation:
Authentication, Errors, Pagination, Identifiers, Timestamps, Exact decimals, Missing values, Enumerated values can grow, Time semantics, Freshness delay and source references, Rate limit and allowances, Match facts and source rights, HEAD and Request id.
Using this page
- Each operation shows a recorded request and response on the right; operations with more than one example list them above the request.
- Select a field name in a response to read its description; every field and parameter has a link of its own.
- Press / to find any endpoint, object, field or parameter.
- The samples call
https://api.example.com, a placeholder: use the API address that comes with your API key. The recorded responses come from a synthetic test dataset, so their names and sources are made up. - For language models: every section has Copy for LLM and a Markdown version; llms.txt indexes them, llms-full.txt holds all of it in one file, and openapi.json is the contract itself.
curl https://api.example.com/v1/me/entitlements \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"principal": {
"type": "api_client",
"id": "c0a80002-0000-4000-8000-000000000071"
},
"organization_id": "c0a80001-0000-4000-8000-000000000071",
"scopes": [
"read:coverage",
"read:entities",
"read:me",
"read:sources"
],
"grant_version": "context:1,entities:1,events:1,lineups:1,statistics:1",
"source_rights_version": "v1",
"policy_version": "2026-10-15.1",
"territory": null,
"freshness_delay_seconds": 0,
"lookback_days": null,
"datasets": [
{
"dataset": "context",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "entities",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "events",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "lineups",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "statistics",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
}
]
}Authentication
Every /v1 operation requires either a user access token issued by OddsFinder sign-in (Authorization: Bearer <jwt>) or an OddsFinder customer API key (X-API-Key). Effective access is the intersection of the caller's permissions, the client's scopes, the organization's grants, source rights and territory and time restrictions; a denied restriction is a 403 not-entitled problem naming the restriction. Because the body depends on the credential, every response carries Cache-Control: private, no-store and Vary: X-API-Key, Authorization: no shared cache may store or reuse it.
Schemes
Authorization: BearerhttpA user access token (JWT) issued by OddsFinder sign-in, validated for its signature, issuer, audience and expiry.
X-API-KeyapiKeyAn OddsFinder customer API key issued to an API client of your organization; it can be revoked and is limited to its scopes.
curl https://api.example.com/v1/me/entitlements \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());curl https://api.example.com/v1/me/entitlements \
-H "Authorization: Bearer $ODDSFINDER_TOKEN"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
headers={"Authorization": "Bearer " + os.environ["ODDSFINDER_TOKEN"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements",
{ headers: { "Authorization": "Bearer " + process.env.ODDSFINDER_TOKEN } },
);
console.log(response.status, await response.json());Errors
Errors are RFC 9457 Problem Details (application/problem+json). type is urn:oddsfinder:problem:<slug>; the catalogue is in components.x-problem-types.
Problem types
| Status | Type | Meaning |
|---|---|---|
| 400 | invalid-request | Malformed path/query/header value, unknown query parameter, or malformed/expired cursor. errors lists each offending parameter. |
| 401 | unauthenticated | No credential, or an invalid, expired or revoked credential. WWW-Authenticate names the accepted schemes. |
| 403 | forbidden | The principal or client scope does not permit the operation at all. |
| 403 | not-entitled | A grant, source-rights, territory, lookback or freshness restriction denies this request; restriction names it. |
| 404 | not-found | No such path, or no entity with that identifier is visible to the caller at the requested knowledge cutoff. |
| 405 | method-not-allowed | The path exists but not for this method. |
| 422 | invalid-range | A well-formed window is inverted, wider than the operation's bound, or otherwise too large for the operation to answer. |
| 422 | unsupported-historical-capability | A valid_at, known_at or other time parameter this operation does not support or cannot answer faithfully (for example a known_at earlier than the retained correction history). Today's state is never served instead. |
| 429 | rate-limited | The requests_per_minute rate limit is used up for the calendar minute, the organization's or, for a caller without an organization, the default per-caller limit; limit_kind (requests_per_minute) and limit name it and Retry-After is the end of the minute. Every request counts towards it, failed ones (403, 404, other 4xx, 5xx, a refusal by a daily allowance), /v1/me/* and paths without an operation included, so a credential missing the operation's scope receives this problem instead of 403 not-entitled once its minute is used; a refusal by the rate limit itself does not count, except for a caller without an organization, whose refusals count towards its minute too (it is still refused only until the minute ends). No usage is metered for the rejected request. When a daily allowance is exhausted too, the answer is quota-exceeded. |
| 429 | quota-exceeded | A daily allowance of the organization (requests_per_day, or a per-dataset allowance) is exhausted for its UTC day; limit_kind and limit name it and Retry-After is the end of the latest-ending exhausted period. No usage is metered for the rejected request. A daily allowance counts the requests in flight and the served ones (a failed request releases what it reserved); metered usage counts served requests only. A used-up per-minute rate limit alone is rate-limited. |
| 500 | internal-error | Unexpected failure; request_id identifies the server-side record. |
| 503 | unavailable | A service this operation depends on is temporarily unavailable; nothing is served in its place. |
| 503 | policy-unavailable | Your access, quota or usage records cannot be checked right now, so the request is refused rather than served unchecked. |
The problem object
typestringtitlestringstatusintegerBetween
400and599.detailstringinstancestringRequest path.
request_iduuidServer-generated request identifier (UUID); not an entity identifier.
errorsarray of objectsPer-parameter detail for
invalid-request.Show child attributes
locationenumOne ofpathqueryheaderbodynamestringmessagestring
restrictionenumFor
not-entitled: which restriction denied the request.One ofscopedatasetcompetitionterritorylookbackfreshnesssource_rightsretry_after_secondsinteger
{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No person with that identifier is visible at the requested cutoff.",
"instance": "/v1/persons/psn_999999999",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Pagination
List operations return items in the documented stable order plus page.next_cursor; pass it back as cursor with the same filters (a valid_at/known_at you did not supply may keep defaulting to the request time between pages). Cursors are opaque, signed by the server and expire; a malformed, edited, forged or expired cursor is a 400 invalid-request naming cursor. limit is bounded per operation.
{
"items": [
{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}
],
"page": {
"next_cursor": null,
"limit": 50
}
}Identifiers
Identifiers are OddsFinder typed identifiers: a kind prefix, an underscore and a decimal sequence number (fx_1839204, tm_3041, dec_12). The prefix is part of the identity, so each parameter states the kind it expects. An identifier whose prefix does not match the parameter's kind, or whose body is not a plain decimal number (a bare UUID, leading zeros, letters), is a 400 invalid-request naming the parameter; a well-formed identifier that does not exist is a 404 not-found. When two records turn out to be the same entity they are merged and one identifier is retired; a retired identifier keeps resolving, and the response carries a resolution object naming the requested and the canonical identifier.
Timestamps
Timestamps are RFC 3339 in UTC with a Z suffix (2026-10-03T16:30:00Z), both in responses and in query parameters. Offsets are rejected.
Exact decimals
Exact decimals (such as venue coordinates) are strings with a fixed pattern, never JSON numbers.
Missing values
Missing values are null, usually with a sibling status that says why (for example name_status, formation_status, or a result's status). withheld always means that a value exists but the rights of its source do not allow serving it to you. Zero is an ordinary value and is never used to mean "missing".
Enumerated values can grow
A field with a fixed list of values (a status, a kind, a role, a dataset, a problem type) may gain values as sports, competitions and datasets are added, without a new API version. Accept a value you do not know and treat it as unknown rather than failing on it.
Time semantics
valid_at is business-effective time (which role, kickoff or membership applied at that instant); known_at is the knowledge cutoff (what OddsFinder had recorded by that instant, including merges, corrections and backfills). Operations that accept known_at echo the effective cutoff in knowledge. Answers for a known_at at or before the watermark that GET /v1/coverage reports for a dataset are stable: nothing recorded at or before that instant is still being accepted, so the same request gives the same answer later. An operation that does not list one of these parameters does not support it and rejects it with the unsupported-historical-capability problem rather than silently serving today's state.
Freshness delay and source references
A grant may carry a freshness delay. It applies to every read of its dataset that has a knowledge cutoff: entity, fixture, result and match-fact reads are served as known at request time - delay at the latest (knowledge.known_at reports the cutoff served), so nothing recorded inside the delay window, such as a kickoff move or a result, is served before the delay has passed. GET /v1/competitions, which takes no known_at, lists today's names as known at request time - delay too. Source references (sources) appear only where the rights of the source and your read:sources scope permit them.
Rate limit and allowances
Every authenticated /v1 request counts towards the organization's requests_per_minute rate limit, including failed requests, /v1/me/* and paths without an operation: a 403, a 404, any other 4xx and a 5xx use up the minute like a served request. A caller without an organization (a user without a membership) has no organization limits and is paced by a default per-caller requests_per_minute instead. Once the minute is used up every request is 429 rate-limited (limit_kind requests_per_minute) until that calendar minute ends, so a credential missing the operation's scope is answered 403 not-entitled (restriction scope) only until then. The daily allowances (requests_per_day and any per-dataset allowance of the organization) are consumed by metered operations alone and never by a failed request; an exhausted one is 429 quota-exceeded. /v1/me/* consumes no allowance, so GET /v1/me/usage reports every limit (limits) while the minute has room.
{
"type": "urn:oddsfinder:problem:rate-limited",
"title": "Rate limited",
"status": 429,
"detail": "The request rate limit for the minute is used up.",
"instance": "/v1/coverage",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"limit_kind": "requests_per_minute",
"limit": 0,
"retry_after_seconds": 60
}Match facts and source rights
Lineups (GET /v1/fixtures/{id}/lineups, dataset lineups) are served only where every source of a team sheet holds a display right for lineups; elsewhere the side is withheld with no entries. Sportmonks, today's lineup source, holds that right, so its sheets are served with a lineups grant. Statistics (GET /v1/fixtures/{id}/statistics, dataset statistics) follow the same rule per source: a value is served only where its source holds a display right for statistics; Sportmonks, today's statistics source, holds it. Match events and sidelined players (GET /v1/fixtures/{id}/events, GET /v1/fixtures/{id}/sidelined, dataset events) follow the same rule per fixture with the display rights for events and for sidelined players; Sportmonks holds both.
HEAD
Every GET operation also answers HEAD with the GET's status and headers and no body; it is authorized, rate limited and metered exactly as the GET.
Request id
Every /v1 response carries X-Request-Id, the server-generated identifier of the logical request (also request_id in Problem Details); quote it when reporting a problem.
Competitions
Leagues and cups, with their seasons.
The competition object
Attributes
idstringCompetition identifier (
cmp_<digits>).namestringThe display name at the date (names are dated, and a sponsor rename never changes the identifier);
nullwithname_status: unavailablewhen no dated name exists.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldassociation_codestringMember association of a national competition;
nullwhen a confederation or FIFA organises it (seeorganiser).organiserenumWho organises a competition or registers a side.
national_associationmeans the siblingassociation_codenames the member association; a confederation orFIFAorganises competitions that have no country and the sibling isnull.One ofnational_associationUEFACONMEBOLCONCACAFAFCCAFOFCFIFAcompetition_kindenumThe kind of competition.
One ofleaguecupinternationalfriendlytierinteger1 = top division;
nullwhen unknown (no sibling status exists yet).Between
1and20.seasonsarray of objectsShow child attributes
idstringSeason identifier (
ssn_<digits>).labelstringstarts_ondateends_ondate
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}The competition detail object
A single competition read; list items carry no resolution, knowledge or provenance.
Attributes
idstringCompetition identifier (
cmp_<digits>).namestringThe display name at the date (names are dated, and a sponsor rename never changes the identifier);
nullwithname_status: unavailablewhen no dated name exists.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldassociation_codestringMember association of a national competition;
nullwhen a confederation or FIFA organises it (seeorganiser).organiserenumWho organises a competition or registers a side.
national_associationmeans the siblingassociation_codenames the member association; a confederation orFIFAorganises competitions that have no country and the sibling isnull.One ofnational_associationUEFACONMEBOLCONCACAFAFCCAFOFCFIFAcompetition_kindenumThe kind of competition.
One ofleaguecupinternationalfriendlytierinteger1 = top division;
nullwhen unknown (no sibling status exists yet).Between
1and20.seasonsarray of objectsShow child attributes
idstringSeason identifier (
ssn_<digits>).labelstringstarts_ondateends_ondate
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"resolution": {
"requested_id": "cmp_1",
"canonical_id": "cmp_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}List competitions
GET/v1/competitions
Competitions the caller's entities grant admits, with their seasons: a grant naming competitions lists those only. Stable order: name ascending, then id ascending; competitions without a current dated name (name null, name_status: unavailable) follow, by id. known_at is not supported.
Parameters
association_codestringFIFA member-association code of national competitions (
ENG,SCO,ITA). Confederation and FIFA competitions have no association code and are not matched by this filter.cursorstringOpaque page cursor from a previous
page.next_cursor; filters must be repeated unchanged.limitintegerMaximum items per page.
Default
50. Between1and200.
Returns 200
One page of competitions.
itemsarray of objectsEach item is the competition object.
pageobjectShow child attributes
next_cursorstringCursor for the next page, or
nullon the last page.limitintegerBetween
1and200.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/competitions \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d limit=50 \
-d association_code=SYNimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/competitions",
params={"limit": "50", "association_code": "SYN"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/competitions?" +
new URLSearchParams({ limit: "50", association_code: "SYN" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}
],
"page": {
"next_cursor": null,
"limit": 50
}
}curl https://api.example.com/v1/competitions \
-H "Authorization: Bearer $ODDSFINDER_TOKEN"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/competitions",
headers={"Authorization": "Bearer " + os.environ["ODDSFINDER_TOKEN"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/competitions",
{ headers: { "Authorization": "Bearer " + process.env.ODDSFINDER_TOKEN } },
);
console.log(response.status, await response.json());{
"items": [
{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}
],
"page": {
"next_cursor": null,
"limit": 50
}
}Get a competition
GET/v1/competitions/{id}
One competition by canonical or retired identifier, with its seasons. name is the dated display name at valid_at as known at known_at; a registered competition without a dated name at that date is still served, with name null and name_status: unavailable (never a 404). include=provenance adds, for each field whose value is chosen among several sources, the source it was taken from (needs the read:sources scope; fields whose source holds no display right are withheld). 403 not-entitled (restriction: competition) when the caller's entities grant names competitions and excludes this one; unknown identifiers are 404.
Parameters
idstringrequiredCanonical or retired competition identifier (
cmp_<digits>); another kind's prefix or an undecodable body is a 400 namingid.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The competition as known at the cutoff.
Returns the competition detail object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/competitions/cmp_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/competitions/cmp_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/competitions/cmp_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"resolution": {
"requested_id": "cmp_1",
"canonical_id": "cmp_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}curl -G https://api.example.com/v1/competitions/cmp_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d include=provenanceimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/competitions/cmp_1",
params={"include": "provenance"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/competitions/cmp_1?" +
new URLSearchParams({ include: "provenance" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "cmp_1",
"name": "Synthetic Premier Division",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"competition_kind": "league",
"tier": 1,
"seasons": [
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31"
}
],
"resolution": {
"requested_id": "cmp_1",
"canonical_id": "cmp_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
},
"provenance": {
"policy": {
"sport": "soccer",
"version": 11
},
"fields": {
"official_name": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"display_name": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"short_name": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"code": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"association_code": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"organiser": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"competition_kind": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"tier": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
}
}
}
}Seasons
One edition of a competition and its stages.
The season detail object
A single season read.
Attributes
idstringSeason identifier (
ssn_<digits>).labelstringstarts_ondateends_ondatecompetition_idstringCompetition identifier (
cmp_<digits>).default_stage_idstringThe stage created with the season; every season has exactly one.
stagesarray of objectsEach item is the stage object.
team_idsarray of stringsTeams entered in the season, by identifier.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31",
"competition_id": "cmp_1",
"default_stage_id": "stg_1",
"stages": [
{
"id": "stg_1",
"season_id": "ssn_1",
"label": "Regular season",
"kind": "regular_season",
"is_default": true,
"ordinal": 1,
"parent_stage_id": null
}
],
"team_ids": [
"tm_1",
"tm_2"
],
"resolution": {
"requested_id": "ssn_1",
"canonical_id": "ssn_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "unknown",
"items": []
}
}Get a season
GET/v1/seasons/{id}
One season (edition of a competition) with its stages, its default stage and the teams entered in it (team_ids). Fixtures of the season are listed with GET /v1/fixtures?competition_id=&season_id=. Authorized through the season's competition.
Parameters
idstringrequiredSeason identifier (
ssn_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The season as known at the cutoff.
Returns the season detail object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/seasons/ssn_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/seasons/ssn_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/seasons/ssn_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "ssn_1",
"label": "2026/27",
"starts_on": "2026-08-01",
"ends_on": "2027-05-31",
"competition_id": "cmp_1",
"default_stage_id": "stg_1",
"stages": [
{
"id": "stg_1",
"season_id": "ssn_1",
"label": "Regular season",
"kind": "regular_season",
"is_default": true,
"ordinal": 1,
"parent_stage_id": null
}
],
"team_ids": [
"tm_1",
"tm_2"
],
"resolution": {
"requested_id": "ssn_1",
"canonical_id": "ssn_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "unknown",
"items": []
}
}Stages
A phase of a season: the league table, a group, a knockout round.
The stage object
Attributes
idstringStage identifier (
stg_<digits>).season_idstringSeason identifier (
ssn_<digits>).labelstringStructural label (
Regular season,Group B); a source's round label (matchday 12) is not a stage.kindenumThe kind of stage.
One ofregular_seasonmain_drawgroupqualifyingknockout_roundplayofffinalis_defaultbooleanordinalintegerBetween
1and32767.parent_stage_idstringnullfor a top-level stage (the default stage always is).resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "stg_1",
"season_id": "ssn_1",
"label": "Regular season",
"kind": "regular_season",
"is_default": true,
"ordinal": 1,
"parent_stage_id": null,
"resolution": {
"requested_id": "stg_1",
"canonical_id": "stg_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}Get a stage
GET/v1/stages/{id}
One structural part of a season (regular season, group, knockout round). Every season has exactly one default stage; a fixture always belongs to a stage. Authorized through the season's competition.
Parameters
idstringrequiredStage identifier (
stg_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The stage as known at the cutoff.
Returns the stage object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/stages/stg_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/stages/stg_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/stages/stg_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "stg_1",
"season_id": "ssn_1",
"label": "Regular season",
"kind": "regular_season",
"is_default": true,
"ordinal": 1,
"parent_stage_id": null,
"resolution": {
"requested_id": "stg_1",
"canonical_id": "stg_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}Clubs
The organisation behind one or more teams.
The club object
Attributes
idstringClub identifier (
clb_<digits>).namestringThe display name at
valid_atas known at the cutoff;nullwithname_status: unavailablewhen no dated name exists.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldassociation_codestringMember association the club is affiliated to;
nullwhen unknown.founded_yearintegerBetween
1800and2100.team_idsarray of stringsThe sides the club fields.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "clb_1",
"name": "Northbridge FC",
"name_status": "known",
"association_code": "SYN",
"founded_year": 1901,
"team_ids": [
"tm_1"
],
"resolution": {
"requested_id": "clb_1",
"canonical_id": "clb_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "unknown",
"items": []
}
}Get a club
GET/v1/clubs/{id}
One club (the organisation) with the teams it fields (team_ids). name follows the dated-name rules of competitions (null with name_status: unavailable when no dated name exists at valid_at). A club is linked to the competitions its teams entered or played in; a competition-limited grant must name one of them.
Parameters
idstringrequiredCanonical or retired club identifier (
clb_<digits>); another kind's prefix or an undecodable body is a 400 namingid.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The club as known at the cutoff.
Returns the club object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/clubs/clb_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/clubs/clb_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/clubs/clb_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "clb_1",
"name": "Northbridge FC",
"name_status": "known",
"association_code": "SYN",
"founded_year": 1901,
"team_ids": [
"tm_1"
],
"resolution": {
"requested_id": "clb_1",
"canonical_id": "clb_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "unknown",
"items": []
}
}Teams
Senior, women's, academy and national sides.
The team object
Attributes
idstringTeam identifier (
tm_<digits>).namestringThe display name at
valid_atas known at the cutoff;nullwithname_status: unavailablewhen no dated name exists, which is not a 404.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldkindenumThe kind of side.
One ofsenior_mensenior_womenreserveyouthnational_mennational_womennational_youthclub_idstringOwning club for club sides (
clb_<digits>);nullfor national teams.association_codestringMember association the side is registered with;
nullonly for a representative side of a confederation or FIFA (seeorganiser).organiserenumWho organises a competition or registers a side.
national_associationmeans the siblingassociation_codenames the member association; a confederation orFIFAorganises competitions that have no country and the sibling isnull.One ofnational_associationUEFACONMEBOLCONCACAFAFCCAFOFCFIFAresolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "tm_1",
"name": "Northbridge FC",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"kind": "senior_men",
"club_id": "clb_1",
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}Get a team
GET/v1/teams/{id}
One team (senior, women's, academy or national side) by canonical or retired identifier. Clubs and teams are distinct; club_id links a club side to its club. name is the dated display name at valid_at as known at known_at; a registered team without a dated name at that date is served with name null and name_status: unavailable, never as a 404. known_at limits merges, revisions and names to those recorded by the cutoff. include=provenance adds, for each field whose value is chosen among several sources, the source it was taken from (needs the read:sources scope). 403 not-entitled (restriction: competition) when the caller's entities grant names competitions and the team entered or played in none of them; unknown identifiers are 404.
Parameters
idstringrequiredCanonical or retired team identifier (
tm_<digits>); another kind's prefix or an undecodable body is a 400 namingid.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The team as known at the cutoff.
Returns the team object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/teams/tm_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/teams/tm_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/teams/tm_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "tm_1",
"name": "Northbridge FC",
"name_status": "known",
"association_code": "SYN",
"organiser": "national_association",
"kind": "senior_men",
"club_id": "clb_1",
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}Persons
Players, coaches and referees with their dated roles.
The person object
Attributes
idstringPerson identifier (
psn_<digits>).namestringThe familiar name the person is known by (Rodri); the legal name is
full_name.nullwithname_status: unavailablewhen the person has no name yet (a referee or coach whose source gives no name), which is not a 404.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldfull_namestringThe full legal name (Rodrigo Hernández Cascante for
nameRodri);nullwhen no servable source supplies it.first_namestringFirst name;
nullwhen no servable source supplies it.last_namestringLast name;
nullwhen no servable source supplies it.aliasesarray of stringsEvery other spelling a servable source gave for the person (Savio, Sávio Moreira de Oliveira for
nameSavinho), including those given for a person merged into this one while the merge stands, withoutnameandfull_name; a spelling stops being an alias when its source no longer maps the person or corrects it. For search and matching. Empty when there is none.association_codestringFootball nationality as a FIFA member-association code;
nullwhen unknown.born_ondateheight_cmintegerHeight in centimetres;
nullwhen unknown.Between
140and215.weight_kgintegerWeight in kilograms;
nullwhen unknown.Between
45and120.birth_country_codestringCountry of birth as a FIFA code (not the football nationality, which is
association_code);nullwhen unknown.positionenumA player's main position;
nullwhen unknown or never a player.One ofgoalkeeperdefendermidfielderattackerdetailed_positionenumA player's detailed position, always one of
position's (a source's detailed position of another main position is not served);nullwhen unknown or never a player.One ofgoalkeepercentre_backleft_backright_backdefensive_midfieldcentral_midfieldattacking_midfieldleft_midfieldright_midfieldleft_wingright_wingsecond_strikercentre_forwardpreferred_footenumPreferred foot;
nullwhen unknown.One ofleftrightbothbirth_placestringPlace of birth as the source names it;
nullwhen unknown.contract_untildateEnd of the current club contract;
nullwhen unknown.rolesarray of objectsShow child attributes
roleenumOne ofcoachplayerrefereeteam_idstringTeam identifier (
tm_<digits>).competition_idstringCompetition identifier (
cmp_<digits>).fromdatetodate
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "psn_5",
"name": "L. Ferri",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": null,
"born_on": null,
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [],
"resolution": {
"requested_id": "psn_5",
"canonical_id": "psn_5",
"status": "canonical",
"decision_id": "dec_2",
"decided_at": "2026-09-20T10:00:00Z"
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}List persons by role
GET/v1/persons
Persons with their dated roles. role restricts to persons holding that role at valid_at (default: request time); team_id restricts to roles attached to that team. Stable order: name ascending, then id ascending. known_at limits identity decisions and role revisions to those recorded by the cutoff; an identifier that is an alias at the cutoff (merged into another person by a decision recorded by then and not reversed) is not listed as a separate person, although GET /v1/persons/{id} still resolves it. An entities grant naming competitions lists only persons linked to one of them: through a membership (any role, any date) at a team that entered or played in the competition, or a fixture of it they officiated.
Parameters
roleenumRole held at
valid_at.One ofcoachplayerrefereeteam_idstringTeam identifier (
tm_<digits>). A retired identifier filters by the team it resolves to atknown_at, andresolution.team_idsays so.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
cursorstringOpaque page cursor from a previous
page.next_cursor; filters must be repeated unchanged.limitintegerMaximum items per page.
Default
50. Between1and200.
Returns 200
One page of persons.
itemsarray of objectsEach item is the person object.
pageobjectShow child attributes
next_cursorstringCursor for the next page, or
nullon the last page.limitintegerBetween
1and200.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow each identifier filter of a list read resolved at
known_at, by parameter name; present when a supplied filter names a registered entity the caller is served and its grant admits (an entity outside a competition restriction, or one the single read answers as unknown, is not echoed and the filter applies as given). A retired identifier (statusalias) filters, and for a competition is authorized, as itscanonical_id; list items themselves never carry a resolution.Show child attributes
team_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
competition_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
season_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/persons \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d role=coach \
-d valid_at=2026-10-01T00:00:00Z \
-d known_at=2026-10-02T12:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons",
params={"role": "coach", "valid_at": "2026-10-01T00:00:00Z", "known_at": "2026-10-02T12:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons?" +
new URLSearchParams({ role: "coach", valid_at: "2026-10-01T00:00:00Z", known_at: "2026-10-02T12:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"id": "psn_1",
"name": "Ada Kowalski",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": "SYN",
"born_on": "1978-03-14",
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [
{
"role": "coach",
"team_id": "tm_1",
"competition_id": null,
"from": "2026-07-01",
"to": null
}
],
"knowledge": {
"known_at": "2026-10-02T12:00:00Z",
"as_requested": true
},
"sources": {
"status": "withheld",
"items": []
}
}
],
"page": {
"next_cursor": null,
"limit": 50
},
"knowledge": {
"known_at": "2026-10-02T12:00:00Z",
"as_requested": true
}
}curl -G https://api.example.com/v1/persons \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d role=player \
-d team_id=tm_1import os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons",
params={"role": "player", "team_id": "tm_1"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons?" +
new URLSearchParams({ role: "player", team_id: "tm_1" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"id": "psn_2",
"name": "Jonas Berg",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": "SYN",
"born_on": "1999-07-02",
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [
{
"role": "player",
"team_id": "tm_1",
"competition_id": null,
"from": "2026-07-01",
"to": null
}
],
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
},
{
"id": "psn_4",
"name": "Luca Ferri",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": "SYN",
"born_on": "1996-01-30",
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [
{
"role": "player",
"team_id": "tm_1",
"competition_id": null,
"from": "2026-07-01",
"to": null
}
],
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}
],
"page": {
"next_cursor": null,
"limit": 50
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}Get a person
GET/v1/persons/{id}
One person by canonical or retired identifier. A retired identifier resolves to the surviving identity and the response carries resolution with the merge decision; after a reversal the identifier resolves to itself again. With known_at before the merge decision, the retired identifier is still its own identity and resolution.status is canonical. Roles are filtered to those effective at valid_at. 403 not-entitled (restriction: competition) when the caller's entities grant names competitions and the person is linked to none of them (memberships at teams that entered or played in a granted competition, or fixtures of it they officiated); unknown identifiers are 404.
Parameters
idstringrequiredCanonical or retired person identifier (
psn_<digits>); another kind's prefix or an undecodable body is a 400 namingid.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The person as known at the cutoff.
Returns the person object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/persons/psn_5 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons/psn_5",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons/psn_5",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "psn_5",
"name": "L. Ferri",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": null,
"born_on": null,
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [],
"resolution": {
"requested_id": "psn_5",
"canonical_id": "psn_5",
"status": "canonical",
"decision_id": "dec_2",
"decided_at": "2026-09-20T10:00:00Z"
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/persons/psn_8 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons/psn_8",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons/psn_8",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "psn_8",
"name": null,
"name_status": "unavailable",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": null,
"born_on": null,
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [],
"resolution": {
"requested_id": "psn_8",
"canonical_id": "psn_8",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
}
}curl -G https://api.example.com/v1/persons/psn_5 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-09-01T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons/psn_5",
params={"known_at": "2026-09-01T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons/psn_5?" +
new URLSearchParams({ known_at: "2026-09-01T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "psn_5",
"name": "L. Ferri",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": null,
"born_on": null,
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [],
"resolution": {
"requested_id": "psn_5",
"canonical_id": "psn_5",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-09-01T00:00:00Z",
"as_requested": true
}
}curl -G https://api.example.com/v1/persons/psn_5 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-09-15T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons/psn_5",
params={"known_at": "2026-09-15T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons/psn_5?" +
new URLSearchParams({ known_at: "2026-09-15T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "psn_4",
"name": "Luca Ferri",
"name_status": "known",
"full_name": null,
"first_name": null,
"last_name": null,
"aliases": [],
"association_code": "SYN",
"born_on": "1996-01-30",
"height_cm": null,
"weight_kg": null,
"birth_country_code": null,
"position": null,
"detailed_position": null,
"preferred_foot": null,
"birth_place": null,
"contract_until": null,
"roles": [
{
"role": "player",
"team_id": "tm_1",
"competition_id": null,
"from": "2026-07-01",
"to": null
}
],
"knowledge": {
"known_at": "2026-09-15T00:00:00Z",
"as_requested": true
},
"resolution": {
"requested_id": "psn_5",
"canonical_id": "psn_4",
"status": "alias",
"decision_id": "dec_1",
"decided_at": "2026-09-10T10:00:00Z"
}
}curl https://api.example.com/v1/persons/psn_999999999 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/persons/psn_999999999",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/persons/psn_999999999",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No person with that identifier is visible at the requested cutoff.",
"instance": "/v1/persons/psn_999999999",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Venues
Grounds fixtures are played at.
The venue object
Attributes
idstringVenue identifier (
ven_<digits>).namestringThe display name at
valid_atas known at the cutoff (sponsor names are display names of their period);nullwithname_status: unavailablewhen no dated name exists.name_statusenumSays why a nullable
nameis or is not served:known= a dated name applies atvalid_atas known at the cutoff;unavailable= the entity exists but has no dated name at that date (for example a team known from a source that reports no names);withheld= a name exists but the rights of its sources do not allow serving it to you. An entity is never a 404 for lacking a name.One ofknownunavailablewithheldterritorystringISO 3166-1 alpha-2 (a commercial territory, not an association code);
nullwhen unknown.citystringlatitudestringWGS84 coordinate in decimal degrees as an exact decimal string with up to six fraction digits, never a JSON number.
longitudestringWGS84 coordinate in decimal degrees as an exact decimal string with up to six fraction digits, never a JSON number.
capacityintegerBetween
0and500000.opened_yearintegerBetween
1800and2100.timezonestringIANA zone name, for presenting local kickoffs;
nullwhen unknown.resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "ven_1",
"name": "Northbridge Park",
"name_status": "known",
"territory": "GB",
"city": "Northbridge",
"latitude": null,
"longitude": null,
"capacity": null,
"opened_year": null,
"timezone": null,
"resolution": {
"requested_id": "ven_1",
"canonical_id": "ven_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "withheld",
"items": []
}
}Get a venue
GET/v1/venues/{id}
One venue with its dated name at valid_at (null with name_status: unavailable when none exists), territory, city and optional coordinates (exact decimal strings). A venue is linked to the competitions of the fixtures played there; a venue without fixtures is served only by an unrestricted grant.
Parameters
idstringrequiredCanonical or retired venue identifier (
ven_<digits>); another kind's prefix or an undecodable body is a 400 namingid.valid_attimestampBusiness-effective instant (UTC); default is the request time.
known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The venue as known at the cutoff.
Returns the venue object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/venues/ven_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/venues/ven_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/venues/ven_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "ven_1",
"name": "Northbridge Park",
"name_status": "known",
"territory": "GB",
"city": "Northbridge",
"latitude": null,
"longitude": null,
"capacity": null,
"opened_year": null,
"timezone": null,
"resolution": {
"requested_id": "ven_1",
"canonical_id": "ven_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "withheld",
"items": []
}
}Fixtures
Matches with their kickoff revisions and latest result.
The fixture object
Attributes
idstringFixture identifier (
fx_<digits>).competition_idstringCompetition identifier (
cmp_<digits>).season_idstringSeason identifier (
ssn_<digits>).stage_idstringThe stage the fixture belongs to as known at the cutoff (never null; the season's default stage until the fixture is assigned to another).
venuestringThe venue name as the source reported it;
nullwhen no source reported one.venue_idstringThe venue, once the reported name is matched to one;
nulluntil then.resultobjectThe highest result version recorded by the cutoff;
nullwhen no result record is known yet.Show child attributes
idstringResult identifier (
res_<digits>).versionintegerstatusenumpending= not yet (no kind, no scores);provisional= reported but not settled;final= settled (decided_atset).One ofpendingprovisionalfinalresult_kindenumHow the match was decided (
played,awarded,annulled,abandoned);nullexactly whilestatusispending.One ofplayedawardedannulledabandonedscore_htobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_ftobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_etobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_pensobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
retractedbooleanTrue when this version retracts the result.
decided_attimestampSettlement time;
nullwhile pending (and optionally while provisional).recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
home_team_idstringTeam identifier (
tm_<digits>).away_team_idstringTeam identifier (
tm_<digits>).kickoff_attimestampKickoff as known at the cutoff. Always present;
kickoff_precisionsays how much of it is confirmed.kickoff_precisionenumPrecision of
kickoff_at:minute/second/millisecondare confirmed instants,hour/daymean only that part is known andkickoff_atis the start of it (an early listing with the date only).One ofdayhourminutesecondmillisecondstatusenumThe fixture's status as known at the cutoff.
One ofscheduledpostponedin_playfinishedcancelledabandonedkickoff_revisionsarray of objectsEvery kickoff revision recorded by the cutoff, oldest first.
Show child attributes
idstringRevision identifier (
rev_<digits>).revision_nointegerSequential per fixture; revision 1 is always
initial.kickoff_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.kickoff_precisionenumOne ofdayhourminutesecondmillisecondstatusenumThe fixture status the revision set.
One ofscheduledpostponedin_playfinishedcancelledabandonedrecorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.reasonenumWhy the revision was recorded; revision 1 is
initial.One ofinitialkickoff_correctionpostponementstatus_changevenue_changeparticipant_changestage_changeresult_correction
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
{
"id": "fx_1",
"competition_id": "cmp_1",
"season_id": "ssn_1",
"stage_id": "stg_1",
"home_team_id": "tm_1",
"away_team_id": "tm_2",
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"venue": "Northbridge Park",
"venue_id": "ven_1",
"kickoff_revisions": [
{
"id": "rev_1",
"revision_no": 1,
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-01T09:00:00Z",
"reason": "initial"
},
{
"id": "rev_2",
"revision_no": 2,
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-25T09:00:00Z",
"reason": "kickoff_correction"
}
],
"result": {
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
},
"knowledge": {
"known_at": "2026-10-01T00:00:00Z",
"as_requested": true
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
}
]
}
}List fixtures in a competition and kickoff window
GET/v1/fixtures
Fixtures of one competition whose kickoff (as known at known_at) lies in [from, to). The window is required and bounded to 92 days; a wider or inverted window is a 422 invalid-range. Stable order: kickoff_at ascending, then id ascending. Kickoff is always known (precision may be day for an early listing). Only what sources holding a display right for fixtures stated is served: a fixture known only through other sources is not listed. A page holds limit items while more follow, and next_cursor never refers to a fixture that is not listed.
Parameters
competition_idstringrequiredCompetition identifier (
cmp_<digits>). A retired identifier filters, and is authorized, as the competition it resolves to atknown_at(resolution.competition_id).season_idstringSeason identifier (
ssn_<digits>). A retired identifier filters by the season it resolves to atknown_at(resolution.season_id).fromtimestamprequiredInclusive lower bound of the kickoff window (UTC).
totimestamprequiredExclusive upper bound of the kickoff window (UTC); at most 92 days after
from.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
cursorstringOpaque page cursor from a previous
page.next_cursor; filters must be repeated unchanged.limitintegerMaximum items per page.
Default
50. Between1and200.
Returns 200
One page of fixtures.
itemsarray of objectsEach item is the fixture object.
pageobjectShow child attributes
next_cursorstringCursor for the next page, or
nullon the last page.limitintegerBetween
1and200.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow each identifier filter of a list read resolved at
known_at, by parameter name; present when a supplied filter names a registered entity the caller is served and its grant admits (an entity outside a competition restriction, or one the single read answers as unknown, is not echoed and the filter applies as given). A retired identifier (statusalias) filters, and for a competition is authorized, as itscanonical_id; list items themselves never carry a resolution.Show child attributes
team_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
competition_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
season_idobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/fixtures \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d competition_id=cmp_1 \
-d from=2026-10-01T00:00:00Z \
-d to=2026-10-08T00:00:00Z \
-d known_at=2026-10-01T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures",
params={"competition_id": "cmp_1", "from": "2026-10-01T00:00:00Z", "to": "2026-10-08T00:00:00Z", "known_at": "2026-10-01T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures?" +
new URLSearchParams({ competition_id: "cmp_1", from: "2026-10-01T00:00:00Z", to: "2026-10-08T00:00:00Z", known_at: "2026-10-01T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"id": "fx_1",
"competition_id": "cmp_1",
"season_id": "ssn_1",
"stage_id": "stg_1",
"home_team_id": "tm_1",
"away_team_id": "tm_2",
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"venue": "Northbridge Park",
"venue_id": "ven_1",
"kickoff_revisions": [
{
"id": "rev_1",
"revision_no": 1,
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-01T09:00:00Z",
"reason": "initial"
},
{
"id": "rev_2",
"revision_no": 2,
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-25T09:00:00Z",
"reason": "kickoff_correction"
}
],
"result": {
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
},
"knowledge": {
"known_at": "2026-10-01T00:00:00Z",
"as_requested": true
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
}
]
}
}
],
"page": {
"next_cursor": null,
"limit": 50
},
"knowledge": {
"known_at": "2026-10-01T00:00:00Z",
"as_requested": true
},
"resolution": {
"competition_id": {
"requested_id": "cmp_1",
"canonical_id": "cmp_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
}
}
}curl -G https://api.example.com/v1/fixtures \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d competition_id=cmp_1 \
-d from=2026-01-01T00:00:00Z \
-d to=2026-12-31T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures",
params={"competition_id": "cmp_1", "from": "2026-01-01T00:00:00Z", "to": "2026-12-31T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures?" +
new URLSearchParams({ competition_id: "cmp_1", from: "2026-01-01T00:00:00Z", to: "2026-12-31T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:invalid-range",
"title": "Invalid range",
"status": 422,
"detail": "The kickoff window may span at most 92 days.",
"instance": "/v1/fixtures",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Get a fixture
GET/v1/fixtures/{id}
One fixture with its revision history and current result. Rescheduling preserves the identifier; kickoff_at, status, stage_id, venue and the sides are the state as known at known_at, kickoff_revisions lists every revision recorded by that cutoff (each a citable rev_ record) and result is the highest result version recorded by then (null when none). include=provenance adds, for each field whose value is chosen among several sources, the source it was taken from (needs the read:sources scope). Only what sources holding a display right for fixtures stated is served: revisions and result versions another source reported are left out, a value such a source won is withheld (venue and scores as null), and a fixture known only through such sources, or whose kickoff or status such a source won, is a 404.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The fixture as known at the cutoff.
Returns the fixture object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/fixtures/fx_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-10-01T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1",
params={"known_at": "2026-10-01T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1?" +
new URLSearchParams({ known_at: "2026-10-01T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "fx_1",
"competition_id": "cmp_1",
"season_id": "ssn_1",
"stage_id": "stg_1",
"home_team_id": "tm_1",
"away_team_id": "tm_2",
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"venue": "Northbridge Park",
"venue_id": "ven_1",
"kickoff_revisions": [
{
"id": "rev_1",
"revision_no": 1,
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-01T09:00:00Z",
"reason": "initial"
},
{
"id": "rev_2",
"revision_no": 2,
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-25T09:00:00Z",
"reason": "kickoff_correction"
}
],
"result": {
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
},
"knowledge": {
"known_at": "2026-10-01T00:00:00Z",
"as_requested": true
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
}
]
}
}curl -G https://api.example.com/v1/fixtures/fx_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-09-20T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1",
params={"known_at": "2026-09-20T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1?" +
new URLSearchParams({ known_at: "2026-09-20T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "fx_1",
"competition_id": "cmp_1",
"season_id": "ssn_1",
"stage_id": "stg_1",
"home_team_id": "tm_1",
"away_team_id": "tm_2",
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"venue": "Northbridge Park",
"venue_id": "ven_1",
"kickoff_revisions": [
{
"id": "rev_1",
"revision_no": 1,
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-01T09:00:00Z",
"reason": "initial"
}
],
"result": {
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
},
"knowledge": {
"known_at": "2026-09-20T00:00:00Z",
"as_requested": true
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-01T08:00:00Z",
"recorded_at": "2026-09-01T09:00:00Z",
"precision": "minute"
}
]
}
}curl -G https://api.example.com/v1/fixtures/fx_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d include=provenanceimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1",
params={"include": "provenance"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1?" +
new URLSearchParams({ include: "provenance" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "fx_1",
"competition_id": "cmp_1",
"season_id": "ssn_1",
"stage_id": "stg_1",
"home_team_id": "tm_1",
"away_team_id": "tm_2",
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"venue": "Northbridge Park",
"venue_id": "ven_1",
"kickoff_revisions": [
{
"id": "rev_1",
"revision_no": 1,
"kickoff_at": "2026-10-03T14:00:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-01T09:00:00Z",
"reason": "initial"
},
{
"id": "rev_2",
"revision_no": 2,
"kickoff_at": "2026-10-03T16:30:00Z",
"kickoff_precision": "minute",
"status": "scheduled",
"recorded_at": "2026-09-25T09:00:00Z",
"reason": "kickoff_correction"
}
],
"result": {
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
},
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
}
]
},
"resolution": {
"requested_id": "fx_1",
"canonical_id": "fx_1",
"status": "canonical",
"decision_id": null,
"decided_at": null
},
"provenance": {
"policy": {
"sport": "soccer",
"version": 11
},
"fields": {
"kickoff_at": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"kickoff_precision": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"status": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"venue": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
},
"round_label": {
"status": "no_observation",
"provider": null,
"namespace": null,
"source_time": null,
"source_time_precision": null,
"observed_at": null,
"recorded_at": null
}
}
}
}Match facts
Lineups, statistics, events, sidelined players, officials and conditions of a fixture.
The fixture lineups object
A fixture's two sides with their team sheets as known at the cutoff (GET /v1/fixtures/{id}/lineups).
Attributes
fixture_idstringFixture identifier (
fx_<digits>).sidesarray of objectsThe home side, then the away side.
Show child attributes
team_idstringTeam identifier (
tm_<digits>).sideenumOne ofhomeawaystatusenumavailable= the entries are served;unavailable= no entry is known for the side at the cutoff;withheld= entries exist but a source of the side holds no display right for lineups.One ofavailableunavailablewithheldsheet_completebooleanTrue when every source of the served entries sends complete team sheets, so a player a newer sheet left out is no longer listed, and the entries name eleven starters. False otherwise, and always for a side that is not
available. When false, the sheet may be short, as the source's own record of a match can be, or a player named in an earlier snapshot of the sheet and dropped later may still be listed. A newer sheet naming a player not yet matched to a person removes nobody until that player is matched, so until then that player is missing and one the sheet dropped may be listed, whatever the value.formationstringThe side's formation (
4-2-3-1, outfield lines from defence to attack) as its source wrote it;nullwithformation_statusunavailablewhen no formation the caller may be served is known.formation_statusenumknown=formationis served;unavailable= no formation is known for the side at the cutoff, or its source may not serve lineups to this caller.One ofknownunavailablecoachesarray of objectsThe side's coaches at the cutoff from sources that may serve lineups to the caller (usually one); empty when none is known.
Show child attributes
idstringLineup coach identifier (
lc_<digits>).versionintegerperson_idstringThe canonical person at the cutoff (a coach recorded under a person merged away since is served under the survivor).
recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.
entriesarray of objectsStarters first, then the bench; within each by position (goalkeeper, defender, midfielder, attacker, none) and shirt number (none last).
Show child attributes
idstringLineup entry identifier (
lu_<digits>).versionintegerperson_idstringThe canonical person at the cutoff (an entry recorded under a person merged away since is served under the survivor).
roleenumstarter= in the named eleven,bench= named among the substitutes (bench_statussays whether he came on).One ofstarterbenchbench_statusenumWhether a bench player came on, from the fixture's substitution events at the cutoff:
substitute= he came on,unused_substitute= no event names him coming on,unknown= the events say nothing to this caller (the fixture is not finished or has no events, a substitution names no player, or the caller may not be served them).nullfor a starter.One ofsubstituteunused_substituteunknownpositionenumThe position the sheet gave the player;
nullmeans unavailable (no source reported one).One ofgoalkeeperdefendermidfielderattackerjersey_numberintegerThe shirt number on the sheet;
nullmeans unavailable.Between
0and99.formation_fieldstringThe player's slot on the formation grid (
row:col, row 1 the goalkeeper's);nullfor a bench player or when no source reported one (unavailable).formation_positionintegerThe source's formation position number of the slot (1 the goalkeeper);
nulllikeformation_field.Between
1and30.recorded_attimestampWhen the platform recorded this version (
known_atcompares against it).
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"fixture_id": "fx_1",
"sides": [
{
"team_id": "tm_1",
"side": "home",
"status": "withheld",
"sheet_complete": false,
"formation": null,
"formation_status": "unavailable",
"coaches": [],
"entries": []
},
{
"team_id": "tm_2",
"side": "away",
"status": "unavailable",
"sheet_complete": false,
"formation": null,
"formation_status": "unavailable",
"coaches": [],
"entries": []
}
],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}The fixture statistics object
A fixture's team and player statistics as known at the cutoff (GET /v1/fixtures/{id}/statistics).
Attributes
fixture_idstringFixture identifier (
fx_<digits>).statusenumavailable= at least one value is served;unavailable= no value matching the filters is known at the cutoff;withheld= matching values exist but no source of them holds a display right for statistics.One ofavailableunavailablewithheldstatisticsarray of objectsHome side first; a side's own values, then its players by person identifier; then metric and period scope. Empty unless
statusisavailable.Show child attributes
idstringStatistic observation identifier (
st_<digits>).versionintegerteam_idstringThe side the value belongs to, canonical at the cutoff.
person_idstringThe player the value describes (canonical at the cutoff);
nullfor the side's own value (not applicable).lineup_entry_idstringThe player's lineup entry as
GET /v1/fixtures/{id}/lineupsserves it to the same caller at the same cutoff;nullfor a team value or when no served entry names him.metricenumA metric code of the curated statistics vocabulary; each metric has one unit.
One ofgoalsown_goalsassistsshots_totalshots_on_targetshots_off_targetshots_blockedshots_inside_boxshots_outside_boxgoal_attemptshit_woodworkbig_chances_createdbig_chances_missedchances_createdkey_passespassespasses_accuratepasses_accurate_percentagepasses_successfulpasses_successful_percentagepasses_final_thirdbackward_passeslong_ballslong_balls_wonlong_balls_won_percentagelong_passeslong_passes_successfullong_passes_successful_percentagethrough_ballsthrough_balls_woncrosses_totalcrosses_accuratecrosses_accurate_percentageball_possessionattacksdangerous_attacksball_safetouchesturnoverspossession_lostdispossessedduels_totalduels_wonduels_lostduels_won_percentageaerials_totalaerials_wonaerials_lostaerials_won_percentagesuccessful_headersdribbles_attempteddribbles_successfuldribbles_successful_percentagedribbled_pasttacklestackles_wontackles_won_percentagelast_man_tacklesinterceptionsclearancesblocksball_recoveriesoffsides_provokederrors_leading_to_shotsavessaves_inside_boxpuncheshigh_claimsgoals_concededgoalkeeper_goals_concededgoal_kicksfouls_committedfouls_drawnyellow_cardssecond_yellow_cardsred_cardsoffsidescornersfree_kicksthrow_inssubstitutionsinjuriesminutes_playedcumulative_minutes_playedratingunitenumThe metric's unit;
percentis 0..100 as the source sends it,rating_0_10a source's own player rating.One ofcountpercentminutesrating_0_10period_scopeenumThe part of the match a value covers.
first_halfandsecond_halfare each half alone;as_reportedis the source's whole match where the source does not say whether extra time is included.One offirst_halfsecond_halfregulation_timeregulation_and_extra_timeincluding_penaltiespre_matchas_reportedvaluenumberThe value as the source sent it (a value with more than four decimals is rounded to four).
definition_versionstringThe source definition the value was mapped under (
sportmonks.1); values of two definitions are not comparable. It names the source, so it follows the source-reference rules ofsources, per value; it is present only with theread:sourcesscope and when the value's source holds a display right for statistics, and left out otherwise.recorded_atstringWhen the platform recorded this version (
known_atcompares against it).
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
{
"fixture_id": "fx_1",
"status": "withheld",
"statistics": [],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}The fixture events object
A fixture's match events as known at the cutoff (GET /v1/fixtures/{id}/events).
Attributes
fixture_idstringFixture identifier (
fx_<digits>).statusenumavailable= 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.One ofavailableunavailablewithheldeventsarray of objectsIn match order (minute, extra minute, then the source's event order); empty unless
statusisavailable.Show child attributes
idstringMatch event identifier (
ev_<digits>).versionintegerkindenumMatch event kinds:
goal,own_goal,penalty_goal(scored),penalty_missed(missed or saved;detailpenalty_savedwhen saved),yellow_card,second_yellow(the second yellow, which sends the player off),red_card(a straight red),substitution,var_decision(a decision of its own, never an edit of the event it concerns),shootout_goal,shootout_missed.One ofgoalown_goalpenalty_goalpenalty_missedyellow_cardsecond_yellowred_cardsubstitutionvar_decisionshootout_goalshootout_misseddetailstringThe detail of the event from the source's sub type:
header,right_foot_shot,penalty_saved,goal_disallowed,goal_awarded,card_adjusted,red_card_cancelled,card_withdrawn; more codes may be added.nullmeans unavailable (none given, or not mapped yet).team_idstringThe side the event counts for (an own goal is filed under the side it benefits), canonical at the cutoff.
sideenumWhether
team_idis the home or the away side.One ofhomeawayperiodenumThe period of play, from the regulation clock minute (up to 45 first half, up to 90 second half, later extra time) and
penalty_shootoutfor shootout kicks.One offirst_halfsecond_halfextra_timepenalty_shootoutminuteintegerRegulation clock minute (45+2 is minute 45 with
extra_minute2).Between
0and200.extra_minuteintegerStoppage minutes past
minute;nullwhen the event was not in stoppage time.Between
0and60.person_idstringThe player the event is about (the scorer, the booked player; for a substitution the player coming on), canonical at the cutoff;
nullwhen the source names no player (a card shown to a coach, a VAR decision).person_team_idstringThe team of
person_id's lineup entry on the fixture (the scorer's own side for an own goal);nullwhen no lineup entry the caller may be served names him, or the caller holds nolineupsgrant for the fixture (or one with a longer delay than itseventsgrant).related_person_idstringThe assist of a goal, the player going off in a substitution;
nullwhen there is none.resultstringThe score (home-away) after a goal as the source reported it;
nullfor other events.infostringThe source's short description verbatim (
Foul,Header);nullwhen none.injuredbooleanThe source's flag that the event involved an injury;
nullwhen the source did not say.on_benchbooleanThe source's flag that the person was on the bench;
nullwhen the source did not say.rescindedbooleanThe source's own flag that it withdrew the event;
nullwhen the source did not say.recorded_attimestampWhen the platform recorded this version (
known_atcompares against it).
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"fixture_id": "fx_1",
"status": "withheld",
"events": [],
"knowledge": {
"known_at": "2026-10-03T19:00:00Z",
"as_requested": false
}
}The fixture sidelined object
A fixture's sidelined players as known at the cutoff (GET /v1/fixtures/{id}/sidelined).
Attributes
fixture_idstringFixture identifier (
fx_<digits>).statusenumavailable= the entries are served;unavailable= no entry is known for the fixture at the cutoff (the source sent no list, which does not mean every player was fit);withheld= entries exist but a source of them holds no right to serve sidelined players to this caller.One ofavailableunavailablewithheldentriesarray of objectsInjuries first, then suspensions, then doubtful players; within each by start date (none last); empty unless
statusisavailable.Show child attributes
idstringSidelined entry identifier (
sdl_<digits>).versionintegerperson_idstringThe sidelined person, canonical at the cutoff.
team_idstringThe person's side, canonical at the cutoff.
sideenumOne ofhomeawaycategoryenuminjury,suspendedordoubtful(the source lists the person as sidelined, but he may still play).One ofinjurysuspendeddoubtfulstart_datedateThe day the spell began;
nullmeans unavailable.end_datedateThe day the spell ended or is expected to end;
nullwhen the source does not know.games_missedintegerThe games the spell has cost as of the source's capture;
nullmeans unavailable.Between
0and32767.completedbooleanThe source's flag that the spell is over as of its capture (not at the fixture's date);
nullmeans unavailable.recorded_attimestampWhen the platform recorded this version (
known_atcompares against it).
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"fixture_id": "fx_1",
"status": "withheld",
"entries": [],
"knowledge": {
"known_at": "2026-10-03T19:00:00Z",
"as_requested": false
}
}The fixture officials object
A fixture's officials as known at the cutoff (GET /v1/fixtures/{id}/officials).
Attributes
fixture_idstringFixture identifier (
fx_<digits>).statusenumavailable= the officials are served;unavailable= no official is known for the fixture at the cutoff;withheld= officials exist but a source of them holds no right to serve officials to this caller.One ofavailableunavailablewithheldofficialsarray of objectsReferee, assistant referees by
role_order, fourth official, video assistant; empty unlessstatusisavailable.Show child attributes
idstringMatch official identifier (
mo_<digits>).versionintegerperson_idstringThe official, canonical at the cutoff.
roleenumOne ofrefereeassistant_refereefourth_officialvideo_assistantrole_orderinteger1 and 2 for the first and second assistant referee;
nullfor a role held once (not applicable).Between
1and9.recorded_attimestampWhen the platform recorded this version (
known_atcompares against it).
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"fixture_id": "fx_1",
"status": "withheld",
"officials": [],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}The fixture conditions object
A fixture's conditions as known at the cutoff (GET /v1/fixtures/{id}/conditions), one record per source.
Attributes
fixture_idstringFixture identifier (
fx_<digits>).statusenumavailable= at least one record is served;unavailable= no record is known for the fixture at the cutoff;withheld= records exist but no source of them holds the right to serve conditions to this caller.One ofavailableunavailablewithheldconditionsarray of objectsOne record per source whose source may serve the caller; empty unless
statusisavailable.Show child attributes
idstringMatch condition identifier (
mc_<digits>).versionintegersourcestringThe record's provider (
sportmonks,footystats); present only with theread:sourcesscope and when the source holds a display right for conditions, left out otherwise.attendanceintegerThe crowd the source reported;
nullmeans unavailable.Between
0and200000.neutral_venuebooleanWhether the match was played at a neutral venue;
nullmeans unavailable.weatherobjectThe source's observed weather;
nullwhen the record holds none.Show child attributes
basisenumcurrent= the source's observation at the match;day= its day values, when it has no such observation.One ofcurrentdaytemperature_cnumberAir temperature, degrees Celsius.
feels_like_cnumberFelt temperature, degrees Celsius.
wind_speednumberWind speed in m/s.
wind_direction_degintegerWind direction in degrees.
Between
0and360.humidity_pctintegerBetween
0and100.pressure_hpaintegerBetween
800and1100.clouds_pctintegerBetween
0and100.descriptionstringThe source's short description (
light rain) verbatim.
recorded_attimestampWhen the platform recorded this version (
known_atcompares against it).
attendanceintegerThe reconciled attendance, taken from the first served record, in the order Sportmonks then FootyStats, that reports one;
nullwhen none does (unavailable).Between
0and200000.attendance_sourcestringThe provider whose record supplied
attendance; present only with theread:sourcesscope and when that source holds a display right for conditions.sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
resolutionobjectHow the requested identifier resolved. Present whenever the requested identifier is not the canonical one, and optional otherwise.
Show child attributes
requested_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.canonical_idstringOddsFinder identifier,
<prefix>_<digits>, a per-kind sequence number without padding, leading zeros, grouping or sign (1 to 9223372036854775807). The prefix names the kind; the per-kind schemas fix it where a field or parameter has one kind.Resolutionuses this generic form because its identifiers are of the resource's kind.statusenumcanonical: the requested identifier is the identity itself;alias: it was retired by a merge decision and resolves tocanonical_id.One ofcanonicalaliasdecision_idstringIdentifier of a merge or reversal decision (
dec_<digits>), a record you can cite.decided_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"fixture_id": "fx_1",
"status": "available",
"conditions": [
{
"id": "mc_3",
"version": 1,
"attendance": 18000,
"neutral_venue": null,
"weather": null,
"recorded_at": "2026-11-01T00:30:00Z",
"source": "footystats"
}
],
"attendance": 18000,
"attendance_source": "footystats",
"sources": {
"status": "included",
"items": [
{
"source": "footystats",
"observed_at": "2026-11-01T00:25:00Z",
"recorded_at": "2026-11-01T00:30:00Z",
"precision": "minute"
}
]
},
"knowledge": {
"known_at": "2026-11-01T00:45:00Z",
"as_requested": true
}
}Get a fixture's lineups
GET/v1/fixtures/{id}/lineups
Both sides' team sheets of a fixture as known at known_at: per side its team, whether the sheet can be served (status) and its entries (lu_<digits> lineup entries, each a citable record with its own identifier and versions). Governed by the lineups dataset: the organization needs a current lineups 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 entry is the highest version recorded by the cutoff; a correction is a new version (a laterknown_atserves it, an earlier one the version before), a retraction a version that removes the entry from the sheet. Entries of a team that is not one of the fixture's sides as known at the cutoff are left out. - Identifiers.
person_idandteam_idare the canonical identifiers at the cutoff: an entry recorded under a person or team merged away since is served under the surviving identifier (one entry per person and side). An entry whose player is known only from sources you may not be served is left out, asGET /v1/persons/{id}answers404for that person. - Order. Starters first, then the bench; within each, goalkeeper, defender, midfielder, attacker, then entries without a position; then by shirt number (entries without one last).
status.available: the entries are served.unavailable: no entry is known for the side at the cutoff (entriesempty).withheld: entries exist but a source of the side holds no display right for lineups (entriesempty; nothing about them is disclosed). Sportmonks holds the display right for lineups, so its sheets areavailable.sheet_complete. Whether the served sheet is complete: every source of its entries sends whole team sheets and it names eleven starters. A player a source's newer whole sheet (eleven starters, every entry matched to a person) drops is no longer listed. While it is false the sheet may be short, as the source's own record of a match can be, or still list a player a later snapshot dropped. A newer sheet naming a player not yet matched to a person removes nobody until that player is matched.- Freshness delay. A grant with a freshness delay is served what was known at
request time - delayat the latest (theknowledgeblock names the cutoff used): the fixture, its sides and the fixtures merged into it as known then, and their entries. A merge recorded inside the delay window is not applied yet, and a fixture not known then is404. - Billing. A response in which no side is
available(every side withheld or unavailable) is recorded with 0 units and does not consume the daily allowance. - Formations. A side's
formation(4-2-3-1) is served withformation_statusknownwhen a formation of the side is known at the cutoff from a source that may serve lineups to the caller (the same rights as the entries); otherwise it isnullwithformation_statusunavailable. Each served entry carries the player's slot (formation_field,formation_position;nullon the bench). - Coaches. A side's
coachesare served from the sources that may serve lineups to the caller, under the same rights as the formation; a coach known only from sources you may not be served is left out. The list is empty when none is known at the cutoff. - Bench split. A bench entry's
bench_statussays whether the player came on, from the fixture's substitution events at the cutoff. It needs a finished fixture with events this caller may be served, under a grant that serves them at no later cutoff; otherwise, or when a substitution names no player, it isunknown. A substitution whose player is not yet matched to a person has no event yet, so until it is matched that player readsunused_substitute.
Source references (sources, with read:sources) appear on served sides and follow the source-reference rules for the lineups dataset.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
Returns 200
The fixture's sides and their team sheets as known at the cutoff.
Returns the fixture lineups object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/fixtures/fx_1/lineups \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/lineups",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/lineups",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"sides": [
{
"team_id": "tm_1",
"side": "home",
"status": "withheld",
"sheet_complete": false,
"formation": null,
"formation_status": "unavailable",
"coaches": [],
"entries": []
},
{
"team_id": "tm_2",
"side": "away",
"status": "unavailable",
"sheet_complete": false,
"formation": null,
"formation_status": "unavailable",
"coaches": [],
"entries": []
}
],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_999999999/lineups \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/lineups",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/lineups",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/lineups",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Get a fixture's statistics
GET/v1/fixtures/{id}/statistics
The team and player statistics of a fixture as known at known_at: each value is a st_<digits> statistic record, citable by its own identifier and versioned, with its metric, unit, period scope and definition version. Governed by the statistics dataset: the organization needs a current statistics 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 value is the highest version recorded by the cutoff; a correction in a newer capture is a new version (a laterknown_atserves it, an earlier one the version before), a retraction a version that removes the value. Values of a team that is not one of the fixture's sides as known at the cutoff are left out. - Not tracked is not zero. A metric the source did not send for a subject has no value here; it is never served as
0. A source's explicit zero is served as0. - Metrics are the curated vocabulary (
StatisticMetric), each with one unit (count,percent0..100,minutes,rating_0_10: a source's own player rating).definition_versionnames the source definition the value was mapped under; values of two definitions are not comparable. It names the source, so it is present only where the value's source reference would be included (read:sourcesand the source's display right for statistics). - Period scopes.
first_halfandsecond_halfare each half alone (the second half is not cumulative: a source period that turns out to be the match so far is not served as a half, so a fixture may havefirst_halfandas_reportedvalues withoutsecond_half);as_reportedis the source's whole match where the source does not say whether extra time is included. Player statistics areas_reported. - Identifiers.
team_idandperson_idare the canonical identifiers at the cutoff: a value recorded under a team or person merged away since is served under the surviving identifier (one value per subject, metric, period scope and source). A player value whose player is known only from sources you may not be served is left out, asGET /v1/persons/{id}answers404for that person.lineup_entry_idnames the player's entry ofGET /v1/fixtures/{id}/lineupsas served to the same caller at the same cutoff, elsenull. - Filters.
team_idandperson_idaccept any identifier of the entity (compared as canonical at the cutoff;team_idkeeps the side's own values and its players');metrictakes one or more comma-separated codes (an unknown code is a400);period_scopeone scope;subjectteam(the sides' own values) orplayer. - Order. Home side first; within a side its own values, then its players by person identifier; then by metric code and period scope.
status.available: at least one value is served.unavailable: no value matching the filters is known at the cutoff.withheld: matching values exist but no source of them may be served to you (nothing about them is disclosed). A value of a source without a display right for statistics is left out.- Freshness delay. A grant with a freshness delay is served what was known at
request time - delayat the latest (theknowledgeblock names the cutoff used): the fixture, its sides and the fixtures merged into it as known then, and their values. - Billing. A response with no value served (
statusother thanavailable) is recorded with 0 units and does not consume the daily allowance.
Source references (sources, with read:sources) appear when values are served and follow the source-reference rules for the statistics dataset.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge 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_idstringOnly this side's values (its own and its players'); any identifier of the team (
tm_<digits>).person_idstringOnly this player's values; any identifier of the person (
psn_<digits>).metricstringOne or more comma-separated metric codes (
StatisticMetric); an unknown code is a 400 namingmetric.period_scopeenumOnly values of this period scope.
One offirst_halfsecond_halfregulation_timeregulation_and_extra_timeincluding_penaltiespre_matchas_reportedsubjectenumteam= only the sides' own values;player= only the players'.One ofteamplayer
Returns 200
The fixture's statistics as known at the cutoff.
Returns the fixture statistics object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/fixtures/fx_1/statistics \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/statistics",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/statistics",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "withheld",
"statistics": [],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}curl -G https://api.example.com/v1/fixtures/fx_1/statistics \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d metric=shots_total,expected_goalsimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/statistics",
params={"metric": "shots_total,expected_goals"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/statistics?" +
new URLSearchParams({ metric: "shots_total,expected_goals" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "One or more request parameters are invalid.",
"instance": "/v1/fixtures/fx_1/statistics",
"errors": [
{
"location": "query",
"name": "metric",
"message": "unknown metric code(s): expected_goals"
}
],
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}curl https://api.example.com/v1/fixtures/fx_999999999/statistics \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/statistics",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/statistics",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/statistics",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}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 sameev_(a goal re-classified as an own goal, a corrected minute), so an earlierknown_atserves 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 withrescinded: true. - VAR. A VAR decision is an event of its own (
kind: var_decision,detailsuch asgoal_disallowed); the goal it concerns is never edited, so a disallowed goal is the goal plus a later VAR decision. - Sides and persons.
team_idis the side the event counts for: an own goal is filed under the side it benefits, andperson_team_idnames the scorer's own side (the team of his lineup entry, when the caller'slineupsgrant also serves the fixture, with no longer delay, and the entry's source may serve lineups to it). For a substitutionperson_idis the player coming on andrelated_person_idthe 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, asGET /v1/persons/{id}answers404. - 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) andkind, all canonical at the cutoff; a filter that matches nothing on anavailablefixture servesavailablewith 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 (eventsempty; 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 - delayat the latest, and a response that is notavailableis recorded with 0 units.
Source references (sources, with read:sources) appear on a served response and follow the source-reference rules for events.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge 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_idstringOnly the events counting for this team (canonical at the cutoff).
person_idstringOnly the events naming this person as the player or the related player (canonical at the cutoff).
kindenumOnly the events of this kind.
One ofgoalown_goalpenalty_goalpenalty_missedyellow_cardsecond_yellowred_cardsubstitutionvar_decisionshootout_goalshootout_missed
Returns 200
The fixture's match events as known at the cutoff.
Returns the fixture events object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/fixtures/fx_1/events \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/events",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/events",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "withheld",
"events": [],
"knowledge": {
"known_at": "2026-10-03T19:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_999999999/events \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/events",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/events",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/events",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Get a fixture's sidelined players
GET/v1/fixtures/{id}/sidelined
The players of both sides the source listed as unavailable for the fixture, through injury or suspension, or as doubtful for it (listed, but they may still play), as known at known_at: sdl_<digits> sidelined entries with the spell's start and end date, the games it has cost and whether it is over. Governed by the events dataset, with the access, versioning, identifier, delay and billing rules of GET /v1/fixtures/{id}/events; served where every source holds the display right for sidelined players (Sportmonks does).
- Coverage. The source lists sidelined players for part of the fixtures only (in 2025/26 for 234 of 380 Premier League fixtures):
unavailablemeans the source sent no list, not that every player was fit. - Dates.
end_datenull means the source does not know when the spell ends;completedis the source's flag as of its capture, not at the fixture's date. - Order. Injuries first, then suspensions, then doubtful players; within each by start date (none last).
- Filters.
team_idandperson_id, canonical at the cutoff.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge 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_idstringOnly the entries of this team (canonical at the cutoff).
person_idstringOnly the entries of this person (canonical at the cutoff).
Returns 200
The fixture's sidelined players as known at the cutoff.
Returns the fixture sidelined object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/fixtures/fx_1/sidelined \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/sidelined",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/sidelined",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "withheld",
"entries": [],
"knowledge": {
"known_at": "2026-10-03T19:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_999999999/sidelined \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/sidelined",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/sidelined",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/sidelined",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Get a fixture's officials
GET/v1/fixtures/{id}/officials
The persons who officiated the fixture (the referee, the assistant referees, the fourth official) as known at known_at, as mo_<digits> match officials, each a citable record with its own identifier and versions. Governed by the context dataset: the organization needs a current context 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 official is the highest version recorded by the cutoff; an official the source's newer capture of the match no longer lists is retracted and left out from then on. - Roles.
referee,assistant_referee(role_order1 and 2 for the first and second assistant),fourth_official;video_assistantis in the vocabulary, but no source sends it today. Order: referee, assistants byrole_order, fourth official. - Identifiers.
person_idis the canonical person at the cutoff; a referee the source names is the same person as FootyStats' referee of that name. An official known only from sources you may not be served is left out, asGET /v1/persons/{id}answers404. - Coverage. The source lists officials from 2009/10, in some seasons only part of the roles:
unavailablemeans no official is known for the fixture at the cutoff. status.available: the officials are served.withheld: officials exist but a source of them holds no display right for officials (officialsempty; nothing about them is disclosed). Sportmonks holds the display right.- Freshness delay and billing as for
GET /v1/fixtures/{id}/events: a delayed grant is served what was known atrequest time - delay, and a response that is notavailableis recorded with 0 units.
Source references (sources, with read:sources) appear on an available response and follow the source-reference rules for officials.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
Returns 200
The fixture's officials as known at the cutoff.
Returns the fixture officials object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/fixtures/fx_1/officials \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/officials",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/officials",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "withheld",
"officials": [],
"knowledge": {
"known_at": "2026-10-03T16:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_999999999/officials \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/officials",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/officials",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/officials",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Get a fixture's conditions
GET/v1/fixtures/{id}/conditions
The conditions the fixture was played in (the attendance, whether the venue was neutral, the observed weather) as known at known_at, one mc_<digits> match conditions record per source. Governed by the context dataset, with the access, versioning, delay and billing rules of GET /v1/fixtures/{id}/officials; served where every source holds the display right for conditions (Sportmonks and FootyStats do).
- One record per source. Each source's report is its own record, served side by side.
sourcenames the record's provider where the caller may see source references (read:sourcesand the source's display right) and is left out otherwise. Rights are judged per source: a record whose source may not serve the caller is left out. - One reconciled attendance.
attendanceis the attendance of the first source, in the order Sportmonks then FootyStats, whose served record reports one at the cutoff; a withheld or missing source falls through to the next, any other source never supplies it, and when none does it isnull. Attendance is served from 2026-11-01; for an earlierknown_atit isnull.attendance_sourcenames that source on the terms ofsource. A FootyStats attendance between 1 and 999 (a figure in thousands) is treated as not reported. - Values. A value the source did not report is
null; a later report without it keeps the known value.attendance0 is a match behind closed doors. - Weather. The source's observed weather only, never a forecast;
basiscurrentis its reading at the match,dayits day values when it has no such reading. The values are metric: degrees Celsius, wind speed in m/s, wind direction in degrees, pressure in hPa. status.available: at least one record is served.unavailable: no record is known for the fixture at the cutoff.withheld: records exist but no source of them holds the right to serve conditions to this caller.
Parameters
idstringrequiredCanonical or retired fixture identifier (
fx_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
Returns 200
The fixture's conditions as known at the cutoff.
Returns the fixture conditions object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/fixtures/fx_1/conditions \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-11-01T00:45:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/conditions",
params={"known_at": "2026-11-01T00:45:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/conditions?" +
new URLSearchParams({ known_at: "2026-11-01T00:45:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "available",
"conditions": [
{
"id": "mc_3",
"version": 1,
"attendance": 18000,
"neutral_venue": null,
"weather": null,
"recorded_at": "2026-11-01T00:30:00Z",
"source": "footystats"
}
],
"attendance": 18000,
"attendance_source": "footystats",
"sources": {
"status": "included",
"items": [
{
"source": "footystats",
"observed_at": "2026-11-01T00:25:00Z",
"recorded_at": "2026-11-01T00:30:00Z",
"precision": "minute"
}
]
},
"knowledge": {
"known_at": "2026-11-01T00:45:00Z",
"as_requested": true
}
}curl https://api.example.com/v1/fixtures/fx_1/conditions \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/conditions",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/conditions",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "available",
"conditions": [
{
"id": "mc_3",
"version": 1,
"attendance": 18000,
"neutral_venue": null,
"weather": null,
"recorded_at": "2026-11-01T00:30:00Z",
"source": "footystats"
},
{
"id": "mc_2",
"version": 1,
"attendance": 18250,
"neutral_venue": false,
"weather": null,
"recorded_at": "2026-11-01T01:00:00Z",
"source": "sportmonks"
}
],
"attendance": 18250,
"attendance_source": "sportmonks",
"sources": {
"status": "included",
"items": [
{
"source": "footystats",
"observed_at": "2026-11-01T00:25:00Z",
"recorded_at": "2026-11-01T00:30:00Z",
"precision": "minute"
},
{
"source": "sportmonks",
"observed_at": "2026-11-01T00:55:00Z",
"recorded_at": "2026-11-01T01:00:00Z",
"precision": "minute"
}
]
},
"knowledge": {
"known_at": "2026-11-01T06:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_1/conditions \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_1/conditions",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_1/conditions",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"fixture_id": "fx_1",
"status": "withheld",
"conditions": [],
"attendance": null,
"knowledge": {
"known_at": "2026-10-03T19:00:00Z",
"as_requested": false
}
}curl https://api.example.com/v1/fixtures/fx_999999999/conditions \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/fixtures/fx_999999999/conditions",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/fixtures/fx_999999999/conditions",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:not-found",
"title": "Not found",
"status": 404,
"detail": "No fixture with that identifier is visible at the requested cutoff.",
"instance": "/v1/fixtures/fx_999999999/conditions",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Results
Versioned final scores of a fixture.
The result object
Attributes
idstringResult identifier (
res_<digits>).versionintegerstatusenumpending= not yet (no kind, no scores);provisional= reported but not settled;final= settled (decided_atset).One ofpendingprovisionalfinalresult_kindenumHow the match was decided (
played,awarded,annulled,abandoned);nullexactly whilestatusispending.One ofplayedawardedannulledabandonedscore_htobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_ftobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_etobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_pensobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
retractedbooleanTrue when this version retracts the result.
decided_attimestampSettlement time;
nullwhile pending (and optionally while provisional).recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.fixture_idstringFixture identifier (
fx_<digits>).versionsarray of objectsEvery version recorded by the cutoff, oldest first; the top-level fields repeat the last one.
Show child attributes
idstringResult identifier (
res_<digits>).versionintegerstatusenumpending= not yet (no kind, no scores);provisional= reported but not settled;final= settled (decided_atset).One ofpendingprovisionalfinalresult_kindenumHow the match was decided (
played,awarded,annulled,abandoned);nullexactly whilestatusispending.One ofplayedawardedannulledabandonedscore_htobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_ftobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_etobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
score_pensobjectA score pair for one period; both sides or neither (the owning
statussays why a pair isnull).Show child attributes
homeintegerBetween
0and99.awayintegerBetween
0and99.
retractedbooleanTrue when this version retracts the result.
decided_attimestampSettlement time;
nullwhile pending (and optionally while provisional).recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.
knowledgeobjectThe effective knowledge cutoff of the response. Under a grant freshness delay it is never later than the request time minus the delay, whatever
known_atasked for.Show child attributes
known_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.as_requestedbooleanTrue when the caller supplied
known_at; false when it defaulted to the request time.
sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
provenanceobjectinclude=provenance: for every field whose value OddsFinder chooses among several sources, the source report its ranking of sources selects among those recorded by the cutoff. The served value is in the body; this block says where it came from.policyidentifies the ranking used (sport and version).Show child attributes
policyobjectShow child attributes
sportstringversioninteger
fieldsmapShow attributes of each value
statusenumOne ofknownunavailableno_observationwithheldproviderstringA source provider or namespace name (
footystats,football).namespacestringA source provider or namespace name (
footystats,football).source_timetimestampA
Timestamp, ornullwhen unknown; the owning object says why.source_time_precisionenumOne ofunknowndayhourminutesecondmillisecondobserved_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
{
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z",
"fixture_id": "fx_1",
"versions": [
{
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
}
],
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T09:00:00Z",
"precision": "unknown"
}
]
}
}Get a result
GET/v1/results/{id}
The result of a fixture (res_<digits>, a citable record with its own identifier): the current version recorded by known_at at the top level and every version recorded by then in versions (oldest first; a correction is a new version, a retraction a version with retracted: true). status is the sibling that says why scores are null (pending = not yet, provisional = reported but not settled, final = settled). A result is a record, not an entity that can be merged: there is no resolution object and the result is authorized through its fixture's competition. A result identifier whose first version was recorded after the cutoff is 404.
Parameters
idstringrequiredResult record identifier (
res_<digits>); another kind's prefix or an undecodable body is a 400 namingid.known_attimestampKnowledge cutoff (UTC); the answer reflects only what OddsFinder had recorded by this instant. Default is the request time. Must not be in the future.
includeenumOptional blocks to add to a single-entity read.
provenancenames, for each field whose value is chosen among several sources, the source report it was taken from as known atknown_at; it needs theread:sourcesscope (403 not-entitled,restriction: scopeotherwise), and a field iswithheldwhen its source holds no display right.One ofprovenance
Returns 200
The result as known at the cutoff.
Returns the result object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 404Unknown identifier at the requested cutoff (
not-found). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/results/res_1 \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/results/res_1",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/results/res_1",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z",
"fixture_id": "fx_1",
"versions": [
{
"id": "res_1",
"version": 1,
"status": "pending",
"result_kind": null,
"score_ht": null,
"score_ft": null,
"score_et": null,
"score_pens": null,
"retracted": false,
"decided_at": null,
"recorded_at": "2026-09-01T09:00:00Z"
}
],
"knowledge": {
"known_at": "2026-10-04T09:00:00Z",
"as_requested": false
},
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": null,
"recorded_at": "2026-09-01T09:00:00Z",
"precision": "unknown"
}
]
}
}Account
What the calling credential may read and how much it has used.
The coverage item object
Attributes
datasetenumThe datasets access is granted for.
coverageandaccountare governed by scope only and never appear in an organization's grants or in coverage items.lineups(team sheets,GET /v1/fixtures/{id}/lineups),statistics(player and team match statistics,GET /v1/fixtures/{id}/statistics) andevents(match events and sidelined players,GET /v1/fixtures/{id}/eventsand/sidelined) andcontext(officials and conditions,GET /v1/fixtures/{id}/officialsand/conditions) are granted per organization likeentitiesand read with theread:entitiesscope.One ofentitieslineupsstatisticseventscontextcoverageaccountcompetition_idstringnullmeans every competition.territorystringTerritory a site or grant applies to (ISO 3166-1 alpha-2).
fromtimestampA
Timestamp, ornullwhen unknown; the owning object says why.totimestampA
Timestamp, ornullwhen unknown; the owning object says why.statusenumavailable;partial(gaps inside the period, or only some covering sources may be displayed);restricted(limited by the caller's grant, or no covering source may be displayed; its period, sampling andwatermark_atare then null and no source references are given);unsupported(the platform does not offer it);unavailable(temporarily cannot be served).One ofavailablepartialrestrictedunsupportedunavailablesampling_resolution_secondsintegerwatermark_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.sourcesobjectSource references, or an explicit statement that they are withheld by source rights or unknown.
Show child attributes
statusenumOne ofincludedwithheldunknownitemsarray of objectsShow child attributes
sourcestringSource namespace (for example
footystats).observed_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.recorded_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.precisionenumPrecision of the source timestamp;
unknownwhen the source gave none.One ofunknowndayhourminutesecondmillisecond
{
"dataset": "entities",
"competition_id": "cmp_1",
"territory": null,
"from": "2026-08-01T00:00:00Z",
"to": null,
"status": "available",
"sampling_resolution_seconds": null,
"watermark_at": null,
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}The entitlements object
Attributes
principalobjectShow child attributes
typeenumOne ofuserapi_clientidstring
organization_iduuidAccount identifier of an organization (UUID); organizations are accounts, not football entities.
scopesarray of stringsgrant_versionstringsource_rights_versionstringpolicy_versionstringterritorystringCross-dataset summary (the first territory any grant names); each read applies its own dataset's grant in
datasets[].territories.freshness_delay_secondsintegerCross-dataset summary (the largest delay of any grant); each read applies its own dataset's grant in
datasets[].freshness_delay_seconds.lookback_daysintegerdatasetsarray of objectsShow child attributes
datasetenumThe datasets access is granted for.
coverageandaccountare governed by scope only and never appear in an organization's grants or in coverage items.lineups(team sheets,GET /v1/fixtures/{id}/lineups),statistics(player and team match statistics,GET /v1/fixtures/{id}/statistics) andevents(match events and sidelined players,GET /v1/fixtures/{id}/eventsand/sidelined) andcontext(officials and conditions,GET /v1/fixtures/{id}/officialsand/conditions) are granted per organization likeentitiesand read with theread:entitiesscope.One ofentitieslineupsstatisticseventscontextcoverageaccountcompetition_idsarray of stringsnullmeans every competition.territoriesarray of stringsnullmeans no territory restriction.freshness_delay_secondsintegerlookback_daysintegernullmeans unlimited history depth.
{
"principal": {
"type": "api_client",
"id": "c0a80002-0000-4000-8000-000000000071"
},
"organization_id": "c0a80001-0000-4000-8000-000000000071",
"scopes": [
"read:coverage",
"read:entities",
"read:me",
"read:sources"
],
"grant_version": "context:1,entities:1,events:1,lineups:1,statistics:1",
"source_rights_version": "v1",
"policy_version": "2026-10-15.1",
"territory": null,
"freshness_delay_seconds": 0,
"lookback_days": null,
"datasets": [
{
"dataset": "context",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "entities",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "events",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "lineups",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "statistics",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
}
]
}The usage object
Attributes
principalobjectShow child attributes
typeenumOne ofuserapi_clientidstring
organization_iduuidAccount identifier of an organization (UUID); organizations are accounts, not football entities.
fromtimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.totimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.requestsobjectLogical requests in the window.
meteredcounts billable units once per logical request, however often it was retried;cachedandrejectedare reported separately and not metered.Show child attributes
meteredintegercachedintegerrejectedinteger
quotaobjectShow child attributes
limitintegerremainingintegerresets_attimestampA
Timestamp, ornullwhen unknown; the owning object says why.
limitsarray of objectsEvery limit that applies to the caller, in the order
requests_per_minute,requests_per_day, then any per-dataset allowance, each in its window that contains the usage window's last instant (passtojust after the current instant for the current minute). An organization lists its configured limits (requests_per_minutecounts every request, the allowances only requests in flight or served); a caller without an organization lists the default per-callerrequests_per_minute, counting its recorded requests (refusals included, sousedmay exceedlimit) and this one.quotarepeats therequests_per_dayentry.Show child attributes
limit_kindenumOne ofrequests_per_minuterequests_per_daylimitintegerusedintegerremainingintegerwindow_starttimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.resets_attimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.
policy_versionstring
{
"principal": {
"type": "api_client",
"id": "c0a80002-0000-4000-8000-000000000071"
},
"organization_id": "c0a80001-0000-4000-8000-000000000071",
"from": "2026-10-01T00:00:00Z",
"to": "2026-10-02T00:00:00Z",
"requests": {
"metered": 0,
"cached": 0,
"rejected": 0
},
"quota": {
"limit": 10000,
"remaining": 10000,
"resets_at": "2026-10-02T00:00:00Z"
},
"limits": [
{
"limit_kind": "requests_per_minute",
"limit": 600,
"used": 0,
"remaining": 600,
"window_start": "2026-10-01T23:59:00Z",
"resets_at": "2026-10-02T00:00:00Z"
},
{
"limit_kind": "requests_per_day",
"limit": 10000,
"used": 0,
"remaining": 10000,
"window_start": "2026-10-01T00:00:00Z",
"resets_at": "2026-10-02T00:00:00Z"
}
],
"policy_version": "2026-10-15.1"
}Dataset coverage visible to the caller
GET/v1/coverage
What the caller can obtain: per dataset and competition, the covered period, territory, sampling resolution, history watermark and status (available, partial, restricted by the caller's grant or because no covering source may be displayed, unsupported by the platform, unavailable right now). A restricted item discloses nothing beyond its status: its period, sampling and watermark_at are null and there are no source references. No item names a competition your entity reads do not serve. The match facts (lineups, statistics, events, context) have one item per competition (no territory) whose watermark is the newest version the item's covering sources recorded for its fixtures, counting only the covering sources you may be shown. Stable order: dataset, then competition_id, then territory. Source references appear where source rights permit.
Parameters
competition_idstringCompetition identifier (
cmp_<digits>).datasetenumThe datasets access is granted for.
coverageandaccountare governed by scope only and never appear in an organization's grants or in coverage items.lineups(team sheets,GET /v1/fixtures/{id}/lineups),statistics(player and team match statistics,GET /v1/fixtures/{id}/statistics) andevents(match events and sidelined players,GET /v1/fixtures/{id}/eventsand/sidelined) andcontext(officials and conditions,GET /v1/fixtures/{id}/officialsand/conditions) are granted per organization likeentitiesand read with theread:entitiesscope.One ofentitieslineupsstatisticseventscontextcoverageaccountcursorstringOpaque page cursor from a previous
page.next_cursor; filters must be repeated unchanged.limitintegerMaximum items per page.
Default
50. Between1and200.
Returns 200
One page of coverage entries.
itemsarray of objectsEach item is the coverage item object.
pageobjectShow child attributes
next_cursorstringCursor for the next page, or
nullon the last page.limitintegerBetween
1and200.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/coverage \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d competition_id=cmp_1import os
import httpx
response = httpx.get(
"https://api.example.com/v1/coverage",
params={"competition_id": "cmp_1"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/coverage?" +
new URLSearchParams({ competition_id: "cmp_1" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"dataset": "entities",
"competition_id": "cmp_1",
"territory": null,
"from": "2026-08-01T00:00:00Z",
"to": null,
"status": "available",
"sampling_resolution_seconds": null,
"watermark_at": null,
"sources": {
"status": "included",
"items": [
{
"source": "synthetic_alpha",
"observed_at": "2026-09-25T08:55:00Z",
"recorded_at": "2026-09-25T09:00:00Z",
"precision": "minute"
},
{
"source": "synthetic_beta",
"observed_at": null,
"recorded_at": "2026-09-01T00:00:00Z",
"precision": "unknown"
}
]
}
}
],
"page": {
"next_cursor": null,
"limit": 50
}
}curl -G https://api.example.com/v1/coverage \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d competition_id=cmp_1import os
import httpx
response = httpx.get(
"https://api.example.com/v1/coverage",
params={"competition_id": "cmp_1"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/coverage?" +
new URLSearchParams({ competition_id: "cmp_1" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"items": [
{
"dataset": "events",
"competition_id": "cmp_1",
"territory": null,
"from": null,
"to": null,
"status": "restricted",
"sampling_resolution_seconds": null,
"watermark_at": null
},
{
"dataset": "statistics",
"competition_id": "cmp_1",
"territory": null,
"from": null,
"to": null,
"status": "restricted",
"sampling_resolution_seconds": null,
"watermark_at": null
}
],
"page": {
"next_cursor": null,
"limit": 50
}
}curl https://api.example.com/v1/coverage \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/coverage",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/coverage",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:quota-exceeded",
"title": "Quota exceeded",
"status": 429,
"detail": "The organization allowance for the period is exhausted.",
"instance": "/v1/coverage",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"limit_kind": "requests_per_day",
"limit": 0,
"retry_after_seconds": 3600
}curl https://api.example.com/v1/coverage \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/coverage",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/coverage",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:rate-limited",
"title": "Rate limited",
"status": 429,
"detail": "The request rate limit for the minute is used up.",
"instance": "/v1/coverage",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"limit_kind": "requests_per_minute",
"limit": 0,
"retry_after_seconds": 60
}Effective entitlements of the caller
GET/v1/me/entitlements
The access OddsFinder derived for your credential: principal, organization, scopes, the versions of your grants, source rights and access policy, and the dataset grants with their competition, territory, freshness-delay and lookback limits. It takes no query parameter: any is a 400 invalid-request, and known_at or valid_at a 422 unsupported-historical-capability (the context is the current one). The call consumes no allowance but counts towards the per-minute rate limit like every request.
Returns 200
Effective entitlements.
Returns the entitlements object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl https://api.example.com/v1/me/entitlements \
-H "X-API-Key: $ODDSFINDER_API_KEY"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements",
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"principal": {
"type": "api_client",
"id": "c0a80002-0000-4000-8000-000000000071"
},
"organization_id": "c0a80001-0000-4000-8000-000000000071",
"scopes": [
"read:coverage",
"read:entities",
"read:me",
"read:sources"
],
"grant_version": "context:1,entities:1,events:1,lineups:1,statistics:1",
"source_rights_version": "v1",
"policy_version": "2026-10-15.1",
"territory": null,
"freshness_delay_seconds": 0,
"lookback_days": null,
"datasets": [
{
"dataset": "context",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "entities",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "events",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "lineups",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
},
{
"dataset": "statistics",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
}
]
}curl https://api.example.com/v1/me/entitlements \
-H "Authorization: Bearer $ODDSFINDER_TOKEN"import os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
headers={"Authorization": "Bearer " + os.environ["ODDSFINDER_TOKEN"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements",
{ headers: { "Authorization": "Bearer " + process.env.ODDSFINDER_TOKEN } },
);
console.log(response.status, await response.json());{
"principal": {
"type": "user",
"id": "a0a80001-0000-4000-8000-0000000000a2"
},
"organization_id": "c0a80001-0000-4000-8000-000000000072",
"scopes": [
"read:coverage",
"read:entities",
"read:me",
"read:sources"
],
"grant_version": "entities:1",
"source_rights_version": "v1",
"policy_version": "2026-10-15.1",
"territory": "GB",
"freshness_delay_seconds": 900,
"lookback_days": 7,
"datasets": [
{
"dataset": "entities",
"competition_ids": null,
"territories": null,
"freshness_delay_seconds": 0,
"lookback_days": null
}
]
}curl -G https://api.example.com/v1/me/entitlements \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d dataset=entitiesimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
params={"dataset": "entities"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements?" +
new URLSearchParams({ dataset: "entities" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "One or more request parameters are invalid.",
"instance": "/v1/me/entitlements",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"errors": [
{
"location": "query",
"name": "dataset",
"message": "Unknown query parameter"
}
]
}curl -G https://api.example.com/v1/me/entitlements \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d known_at=2026-10-01T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/entitlements",
params={"known_at": "2026-10-01T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/entitlements?" +
new URLSearchParams({ known_at: "2026-10-01T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"type": "urn:oddsfinder:problem:unsupported-historical-capability",
"title": "Unsupported historical capability",
"status": 422,
"detail": "known_at is not supported on this operation; the platform never substitutes today's state.",
"instance": "/v1/me/entitlements",
"request_id": "0f1e2d3c-4b5a-4968-8776-655443322110"
}Metered usage and quota of the caller's organization
GET/v1/me/usage
Logical metered requests for the caller's organization (or the user alone when there is none) in [from, to); default is the current allowance period. The window is bounded to 93 days. Server-side retries and cache hits are reported separately and never counted twice. limits reports every limit that applies to the caller. The call consumes no allowance but counts towards the per-minute rate limit like every request.
Parameters
fromtimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.totimestampRFC 3339 instant in UTC with
Zsuffix; optional fractional seconds up to microseconds.
Returns 200
Usage summary.
Returns the usage object.
Error responses
- 400Malformed parameter or cursor (
invalid-request). - 401Missing or invalid credential (
unauthenticated). - 403Operation not permitted (
forbidden) or restricted by grants/rights (not-entitled). - 422Well-formed but unanswerable (
invalid-range,unsupported-historical-capability). - 429The 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. - 500Unexpected failure (
internal-error);request_ididentifies the server-side record. - 503A service this operation depends on, or the access check, is temporarily unavailable (
unavailable,policy-unavailable).
curl -G https://api.example.com/v1/me/usage \
-H "X-API-Key: $ODDSFINDER_API_KEY" \
-d from=2026-10-01T00:00:00Z \
-d to=2026-10-02T00:00:00Zimport os
import httpx
response = httpx.get(
"https://api.example.com/v1/me/usage",
params={"from": "2026-10-01T00:00:00Z", "to": "2026-10-02T00:00:00Z"},
headers={"X-API-Key": os.environ["ODDSFINDER_API_KEY"]},
)
print(response.status_code, response.json())const response = await fetch(
"https://api.example.com/v1/me/usage?" +
new URLSearchParams({ from: "2026-10-01T00:00:00Z", to: "2026-10-02T00:00:00Z" }),
{ headers: { "X-API-Key": process.env.ODDSFINDER_API_KEY } },
);
console.log(response.status, await response.json());{
"principal": {
"type": "api_client",
"id": "c0a80002-0000-4000-8000-000000000071"
},
"organization_id": "c0a80001-0000-4000-8000-000000000071",
"from": "2026-10-01T00:00:00Z",
"to": "2026-10-02T00:00:00Z",
"requests": {
"metered": 0,
"cached": 0,
"rejected": 0
},
"quota": {
"limit": 10000,
"remaining": 10000,
"resets_at": "2026-10-02T00:00:00Z"
},
"limits": [
{
"limit_kind": "requests_per_minute",
"limit": 600,
"used": 0,
"remaining": 600,
"window_start": "2026-10-01T23:59:00Z",
"resets_at": "2026-10-02T00:00:00Z"
},
{
"limit_kind": "requests_per_day",
"limit": 10000,
"used": 0,
"remaining": 10000,
"window_start": "2026-10-01T00:00:00Z",
"resets_at": "2026-10-02T00:00:00Z"
}
],
"policy_version": "2026-10-15.1"
}