Skip to content

FootballMatch

Object type

A football match/fixture (BP1 football_matches). Provider ids resolve via the crosswalk. status is the precise lifecycle state; lifecycle is the coarse cross-sport denominator derived from it. Backed by the football_matches table.

Implements: SportEvent

FieldArgsTypeDescription
id—ID! required—
sport—Sport! required—
competition—Competition! requiredNon-null here (covariance-legal — satisfies the nullable interface field).
venue—Course—
matchday—Int—
leg—Int—
homeTeam—Team! required—
awayTeam—Team! required—
scheduledTime—DateTime! required—
kickOffTime—DateTime—
fullTimeAt—DateTime—
status—FootballMatchStatus! required—
lifecycle—EventLifecycle! requiredCoarse cross-sport lifecycle, derived from status.
period—FootballMatchPeriod—
minute—Int—
addedMinute—Int—
homeScore—IntHome goals. Derived by counting the match’s scoring events (goal / penalty_scored, with own_goal credited to the opposing side), so an operator logging a goal moves the score with no separate score-edit mutation. When derivation applies, the live score reflects the recorded event detail rather than the raw feed score if the two diverge. Falls back to the ingested score column — which may itself be null — in three cases, because a partial tally is worse than a missing one: 1. The match has no scoring events yet (a feed score with no event detail, or a fixture not yet under way). 2. Any scoring event cannot be credited to a side, i.e. it has no participation, a dangling one, or one whose role is neither HOME nor AWAY. Counting only the attributable goals would silently under-report the score. 3. The match is PROVIDER-controlled — an active crosswalk maps it, so a feed owns its live data. A feed stream can be non-cumulative (Opta’s F50 sends one file per event), so a lost push is missing state that the events which DID arrive cannot reveal, and no predicate over the event set can prove such a set complete. This is asked of OWNERSHIP rather than of the events because stream receipt is not reliably visible in the rows: a period marker or an out-of-scope family is skipped before anything is written, and an event that loses newest-wins to a cumulative row is not flagged either. Consistent with provider data being fixed at source: for a feed-owned fixture the provider’s own score is the authority. An OPERATOR-controlled match derives normally, so an operator logging a goal still moves the score. Consequence for clients: a non-null score is either fully derived from the events, or the stored score column as last written — never a partial count. Do NOT infer the writer from which fallback applied. Only a feed-owned fixture is PROVIDER-controlled, but that does not make a case-3 value a feed value: an operator can create a fixture (no crosswalk, so control is OPERATOR), set its score with setFootballMatchScore, and a mapping can later be repointed onto that match — flipping control to PROVIDER with the operator’s number still in the column. If the mapping resolves after full-time, no further feed score arrives and that value is served indefinitely. Cases 1 and 2 likewise occur on OPERATOR matches. So read a non-derived score as the stored value, whose writer is the match’s own source, and never as “the provider’s number”. In every case it is not an error for this to disagree with the number of goal events you can query.
awayScore—IntAway goals. Same derivation and the same three fallback cases as homeScore.
homeScoreHalfTime—Int—
awayScoreHalfTime—Int—
homeScoreExtraTime—Int—
awayScoreExtraTime—Int—
homeScorePenalties—Int—
awayScorePenalties—Int—
attendance—Int—
referee—Individual—
allowExtraTime—Boolean! requiredWhether this fixture may go to extra time (operator-set; league fixtures false).
allowPenalties—Boolean! requiredWhether this fixture may be decided by a penalty shootout (operator-set; league fixtures false).
extraTimePlayed—Boolean! requiredWhether the match actually played extra time (sticky; set on entry to an ET phase). Lets the lifecycle timeline reconstruct the realised path — e.g. ET → penalties — even once COMPLETED.
penaltiesPlayed—Boolean! requiredWhether the match actually went to a penalty shootout (sticky; set on entry to a penalties phase).
startedOnce—Boolean! requiredWhether the match has ever kicked off (sticky; set on entry to any post-kick-off status, never cleared). Distinguishes a match that has never started from one an operator has reverted back to SCHEDULED — the operator lane never writes kickOffTime, so that field can’t answer it.
weather—String—
officials—JSON—
abandonedReason—String—
postponedReason—String—
rescheduledMatch—FootballMatch—
createdAt—DateTime! required—
updatedAt—DateTime! required—
version—Int! required—
participations—[FootballMatchParticipation!]! requiredExactly two participations (HOME, AWAY).
eventsincludeDeleted: Boolean
type: FootballMatchEventType
[FootballMatchEvent!]! requiredIn-match event stream, ordered by clock; deleted events excluded unless includeDeleted=true.