Sideline Exchange/
Dashboard →

Reference

Glossary

Every word the API, the console and these documents use in a particular way — defined once, and used identically in all three.

The model

Observation

What one source said about one thing at one time — the evidence, never edited and never deleted.

An observation records a claim: source, type, external id, when it was observed, a confidence, and the data itself. Observations are append-only. Correcting the hub does not mean changing an observation; it means adding a new one from a source ranked high enough to win. Every payload is archived raw before anything parses it, so a run can be replayed after a parser improves.

See alsoCanonical entityProvenanceSourceConfidence

Canonical entity

The hub’s single answer for a real-world thing — derived from observations by policy, never hand-edited.

Canonical rows (a fixture, a team, a venue) are what consumers read. Each field holds the value from the observation that won it under the conflict policy, plus a provenance entry naming that observation. Nothing writes a canonical field directly — not an operator, not a support ticket.

See alsoObservationProvenanceConflict policy

Provenance

Per field, the observation whose value won: which source, when it was observed, at what confidence.

Provenance is part of the public API, not an internal audit table. A fixture response carries a provenance object keyed by field path — start, venue.field — so “where did this kickoff time come from?” is answerable without asking anyone.

See alsoObservationConflict policyAuthority rank

Conflict policy

How a field is decided when sources disagree: authority rank first, then recency, then the source’s own confidence.

The policy runs per field, not per record — which is why a public source can fill in a field number the host left empty without touching the host’s kickoff time. A lower-ranked source never overwrites a higher-ranked one; it only fills gaps.

See alsoAuthority rankConfidenceProvenance

Authority rank

The trust order over source classes, 1 (most authoritative) to 6. The lowest rank present wins the field.

Rank 1 authoritative push, 2 partner API, 3 host feed, 4 owner correction, 5 public source, 6 crowd. Rank is a property of the source class, fixed when the source is registered, and it is the only lever that settles a disagreement — there is no manual override.

See alsoSource classConflict policy

Source class

What kind of source this is, which fixes its authority rank.

Authoritative push (the host platform pushing its own data), partner API (a platform the hub polls), host feed (iCal or CSV a club publishes), owner correction (a club admin fixing their own record), public source (a schedule its organiser publishes openly), crowd (a parent reporting a score).

See alsoAuthority rankSource

Confidence

How sure the source is about this observation, 0 to 1. It breaks ties inside a rank, never across ranks.

Confidence is the source’s own claim about itself: a structural parser that read a clean table sends a high number; an extractor that inferred a kickoff from prose sends a low one. A confident public source still loses to a hesitant host push, because rank is checked first.

See alsoConflict policyAuthority rank

Version

A counter on a canonical entity, incremented on every applied change — what change events and standings cite.

See alsoChanged fieldsDelta sync

Changed fields

The field paths an applied change actually moved, carried on the change event so consumers can react narrowly.

See alsoDelta syncCloudEvent

Ingestion

Source

A registered origin of observations, with a key, a class and therefore a rank.

Every observation names its source; a push from an unregistered source is refused with an unknown_source problem. Sources are per mode: a source key registered in test mode does not exist in live mode.

See alsoSource classAuthority rankTest and live mode

Batch

One push of up to 1,000 observations, recorded with what was accepted, what was rejected, and where the raw payload was stored.

Validation is per observation: one malformed record costs that record, not the batch. The batch is accepted (202) if at least one observation is valid, and rejected outright only if none is. Processing is asynchronous — a 202 means stored and queued, not applied.

See alsoIdempotency keyReceiptRaw payload

Idempotency key

A caller-chosen string that makes a retry safe: replaying a batch with the same key returns the original receipt instead of applying twice.

Required on every push. Choose something derived from the payload or the job that produced it, not a fresh UUID per attempt — a new key on a retry defeats the purpose.

See alsoBatchReceipt

Receipt

The 202 answer to a push: the batch id, how many observations were accepted, and the pointer and message for each one rejected.

See alsoBatchProblem document

Raw payload

The unmodified bytes of everything ingested, archived to blob storage before any parsing.

Kept so that a parser fixed in March can be replayed over January. Replay is a designed property of the pipeline, not a rescue operation — which is why the batch row carries the blob path.

See alsoBatchSnapshotReplay

Replay

Re-running an improved parser over payloads already archived, rather than re-fetching from the source.

See alsoRaw payloadSnapshot

Feed

An iCal or CSV schedule the hub polls — or that you upload — registered with the things a calendar cannot say about itself.

A calendar file does not know its own sport, team or time zone, so those are supplied at registration. The hub polls politely: conditional requests, content hashing, backoff on failure. Everything fetched goes through the same validation a partner push does. A feed is a rank-3 source: evidence, not gospel.

See alsoConnectorPoll intervalSource class

Connector

A versioned structural parser pointed at a published schedule, with run history, drift detection and an agreed request budget.

Connectors are the public-source tier. Every payload is snapshotted to the lake under the run id, and the parser reads the snapshot rather than the network, so any run can be replayed against a newer parser. Each source is read within a budget agreed with the site that publishes it.

See alsoDriftTargetCatalogSnapshotParser

Parser

The named, versioned code that turns one fetched document into observations.

The version is recorded on every run, so “which parser produced this?” is answerable years later — and so a fix can be replayed over the snapshots the old version misread.

See alsoConnectorRunReplay

Run

One execution of one feed or connector: when it started, how long it took, what it yielded, and any problems.

See alsoYieldDriftSnapshot

Yield

How many observations a run produced. A yield that collapses against its own history is one of the signals drift detection watches.

See alsoDriftRun

Drift

The source changed shape under the parser. The run’s output is held, never applied, until an operator fixes the parser or accepts the new shape.

Three signals raise it: the layout fingerprint changed, the run yielded nothing, or the yield collapsed against its own history. The ordering is the point — the hold happens before apply, so a site redesign costs a held run rather than a corrupted season.

See alsoLayout fingerprintAccept new shapeConnector

Layout fingerprint

A hash of the structural shape of a fetched page — what drift detection compares this run against the last.

See alsoDrift

Accept new shape

Declaring the source’s new layout to be the baseline, which clears the hold and resumes the connector on its next run.

Accepting also discards the stored conditional-request validators; otherwise the next fetch answers 304 and the connector never sees the page it was just told to re-learn.

See alsoDriftLayout fingerprint

Snapshot

The exact document a run fetched, stored in the lake under that run’s id.

Extraction may only read snapshots — it never fetches for itself. That rule is what makes a parser fix replayable over history instead of only forward.

See alsoRaw payloadReplayRun

Catalog

A connector’s index of everything it could sync — the list of tournaments a site publishes, which becomes the denominator for coverage.

See alsoTargetCoverage

Target

One thing inside a catalog that is kept in sync — one tournament out of thousands — with its own state, schedule and kill switch.

See alsoCatalogTarget stateCoverage

Target state

Where one target stands, in a vocabulary that separates what is ours to fix from what is not.

Unpublished is decided before failing, deliberately: a catalog listing a tournament months before the host posts a schedule is the common case, and it is not a fault. Only stale and failing count as ours.

See alsoTargetCoverage

Coverage

Per week: how many catalogued targets play, how many the host published, how many the hub pulled, and how many are fresh.

The catalog is the denominator, so the number cannot be flattered by ignoring what was never fetched. Published is the host’s doing; pulled and fresh are the hub’s. Fresh below published is the gap worth acting on.

See alsoCatalogTargetFreshness SLO

Freshness SLO

How recently a target must have synced to count as current — tighter the closer its games are to being played.

See alsoCoverageTarget state

Poll interval

How often the hub re-fetches a feed or target. Conditional requests make an unchanged fetch nearly free.

See alsoFeedETag

Supply tier

How data arrives: push (a partner posts), pull (the hub polls an API), feed (iCal/CSV), public source (a schedule published openly), correction (an owner fixes their own record).

See alsoSource classConnectorFeed

Identity

Identity resolution

Deciding which canonical entity an incoming observation is about, in four stages: known id, structured fuzzy match, embedding, threshold.

“Lakeside FC 2014B Blue” and “Lakeside 14B Blue” are one team, and two sources describing one game must become one fixture. Above the auto-merge threshold the external id is mapped onto the existing entity; in the review band a new entity is created and the pair waits for a human.

See alsoMappingReview queueAuto-merge thresholdExternal id

External id

What one source calls a thing, in that source’s own namespace. A canonical entity lists every external id that resolved to it.

See alsoMappingIdentity resolutionPrefixed ULID

Mapping

A row saying “this source’s external id means this canonical entity”. Merging repoints mappings; it never mutates a canonical row.

That is what makes a wrong merge one undo rather than an archaeology project: approval repoints mappings and sets a merged_into pointer, so reversing it restores exactly what was.

See alsoIdentity resolutionReview queue

Review queue

Proposed merges the resolver scored below the auto-merge threshold, shown with both sides, the facts and the evidence per signal.

See alsoIdentity resolutionAuto-merge thresholdEvidence

Auto-merge threshold

The score above which a merge happens without asking. Set from a labelled evaluation set, not from taste.

A test fails the build if precision at this threshold ever drops below 1.0 on the labelled set. Below the threshold and above the review floor lies the review band.

See alsoReview queueEvidence

Evidence

The per-signal breakdown behind a match score: name tokens, age group, gender, club, region, date and venue proximity, each with its own contribution.

Some signals are vetoes rather than weights. Sibling teams that differ only by colour — “2014B Blue” against “2014B White” — can never auto-merge however alike the rest looks.

See alsoReview queueAuto-merge threshold

The API

Test and live mode

Two isolated partitions of every table. The API key decides which one a request touches; there is no mode parameter to get wrong.

A test key writes to a sandbox you can reset from the dashboard; a live key touches production data, which has no reset. Sources, feeds, keys, webhooks and data are all per mode — a source registered in test does not exist in live.

See alsoSecret keyPublishable keyTest-mode reset

Secret key

sk_test_… / sk_live_… — full authority: push, read, manage webhooks. Server-side only, shown once at creation.

Only a hash is stored, so a lost key is rolled, never recovered. Rolling takes effect immediately.

See alsoPublishable keyTest and live mode

Publishable key

pk_test_… / pk_live_… — read-only, public-tier, safe to ship inside a web page. What the calendar widget uses.

A publishable key that attempts a write gets a 403 with publishable_key as the problem type.

See alsoSecret keyGrant

Test-mode reset

Wiping the test partition and starting again. Live data has no equivalent.

See alsoTest and live mode

ETag

A version tag on a response. Send it back as If-None-Match and an unchanged answer costs a 304 and almost no bytes.

Caching is layered: Cloudflare at the edge, Redis behind it, ETags on the wire, delta sync for the client’s own store. Cache keys always include mode and version, and authenticated non-public data is never cached at the edge.

See alsoDelta syncCursor

Cursor

An opaque bookmark into a stable ordering. Pass the one you were given to continue exactly where you stopped.

Cursors are keyset-based, not offsets, so a page never skips or repeats a row because something was inserted while you were reading. A cursor that no longer decodes returns invalid_cursor: start the page again without one.

See alsoDelta syncETag

Delta sync

GET /v1/changes — every applied change in order from your stored cursor, so you never re-download a season.

Filtering by type narrows what is returned, but the cursor still advances past everything, so changing your filter never loses your place. has_more tells you to keep paging before you sleep.

See alsoCursorWebhook subscriptionChanged fields

Problem document

The RFC 9457 shape every error uses: a stable type URI, a human detail, and for batches an errors array with the index and JSON pointer of each rejected observation.

See alsoReceipt

Prefixed ULID

Every identifier says what it is: fx_ fixture, tm_ team, cmp_ competition, org_ organization, ven_ venue, src_ source, feed_, batch_, obs_.

The body is a ULID: sortable by creation time, safe to generate anywhere, no coordination required.

See alsoExternal id

Grant

An organization’s permission for a named consumer to read data that is not public-tier — participant rosters, for instance.

Without a grant the response says what is being withheld rather than pretending it does not exist: player_lines_withheld on a box score is the shape of an honest refusal.

See alsoPublishable keyOrganization

Usage

Calls by endpoint and mode over the period, with error counts and average latency — the same rollup billing would read.

See alsoTest and live mode

Rate limit

The ceiling on requests per key. Exceeding it returns 429 with a problem document; back off and retry.

Events

CloudEvent

The envelope every emitted event uses: specversion, type (oyss.*), subject (the entity id), time and data.

See alsoEvent typeWebhook subscription

Event type

What happened, as a dotted name: oyss.fixture.rescheduled, oyss.result.finalized, oyss.team.merged. Subscriptions may use globs.

See alsoCloudEventWebhook subscription

Outbox

Events written in the same transaction as the canonical change, then relayed separately — so an event is never emitted for a change that rolled back, or lost for one that committed.

See alsoCloudEventDispatch

Dispatch

The relay that drains the outbox: purging caches and scheduling webhook deliveries, out of band and with per-subscription fairness.

Fairness is the point: one dead endpoint cannot delay anyone else’s events.

See alsoOutboxWebhook subscriptionDelivery attempt

Webhook subscription

A URL, the event types it wants, and an optional scope filter. The signing secret is returned once, at creation.

Treat webhooks as a nudge, not the ledger. Answer 2xx quickly, do the work asynchronously, and reconcile against the change stream from your stored cursor.

See alsoSigning secretDelivery attemptDelta sync

Signing secret

The key every delivery is signed with, HMAC-SHA256 over the raw body. Verify before trusting a payload.

See alsoWebhook subscription

Delivery attempt

One attempt to hand one event to one endpoint: status code, duration, error, and when the next attempt is due.

A failed delivery retries with exponential backoff for 24 hours. An endpoint that never answers is disabled automatically — no successful delivery for 30+ minutes across 20+ attempts — with the reason recorded.

See alsoWebhook subscriptionAuto-disableRedeliver

Auto-disable

Switching off an endpoint that has stopped answering entirely, so the queue is not held hostage by a dead URL.

Re-create the endpoint once it is healthy, then reconcile the gap with delta sync.

See alsoDelivery attemptDelta sync

Redeliver

Sending an event again, on purpose, from the console — for an endpoint that was down or a consumer that lost the payload.

See alsoDelivery attempt

Dead letter

A message that failed processing enough times to be set aside rather than retried forever, kept with its error for redrive.

See alsoRedrive

Redrive

Putting dead-lettered messages back on the queue once the cause is fixed.

See alsoDead letter

Schedule data

Fixture

Anything schedulable: a game, practice, tryout, scrimmage or team event.

See alsoKindFixture statusTime status

Kind

What sort of fixture this is — game, practice, tryout, scrimmage or event. Non-games carry a title instead of two sides.

See alsoFixture

Fixture status

Where a fixture stands: scheduled, in progress, completed, postponed, cancelled or forfeit.

A cancellation is a status change, never a delete. A family that saw the game yesterday needs to see the cancellation today, so cancelled fixtures stay readable and are struck through rather than hidden.

See alsoFixtureTime status

Time status

How much to trust the clock: confirmed, estimated, or tbd for a fixture that has a date but no time yet.

A tbd fixture carries a date instead of a start instant, which is the honest shape — inventing a midnight kickoff to satisfy a timestamp column is how a schedule lies.

See alsoFixtureTime zone

Time zone

All instants are UTC; the venue carries an IANA zone so a local kickoff time can be shown correctly.

See alsoTime statusVenue

Competition

A tournament, league or season — the container a division and its stages belong to.

See alsoDivisionStage

Division

The bracket inside a competition, structured rather than named: age group, gender, level.

Structured because “2014 Boys Premier” and “U11B Premier” are the same division, and a string comparison will never know that.

See alsoCompetitionStage

Stage

A phase within a division — pool play, a bracket, a regular season. Standings are computed per stage.

See alsoStandingsDivision

Venue

Where a fixture is played, with an optional field or pitch within it and an IANA time zone.

See alsoTime zone

Side

A team’s part in a fixture, with a role: home, away, or participant when the format has no home side.

See alsoFixture

Organization

The club, league or governing body a team belongs to — and the party that grants access to its non-public data.

See alsoGrant

Standings

A stage’s table, computed from results and the stage’s own rules. Never edited: a wrong table means a wrong result.

Recomputed in the same transaction that lands a final result, which then emits oyss.standing.updated. Given the results and the rules there is exactly one right table.

See alsoTiebreakerTraceStage

Tiebreaker

The stage’s ordered rules for separating level teams — head-to-head, goal difference, goals for, and so on.

The rules are the stage’s, not the hub’s: the competition observation carries the points scheme and an ordered tiebreaker list. Unknown rule names are rejected at ingest rather than silently skipped. Where a host never published rules, a conservative default applies and the response says so.

See alsoStandingsTrace

Trace

The ordered rules that placed one row where it is, returned with the row — so “why are they second?” is answerable from the response.

See alsoStandingsTiebreaker

Box score

Per-fixture statistics in two tiers: team lines, which are public, and player lines, which need a grant.

Without the grant the response says player_lines_withheld rather than quietly returning less.

See alsoGrantStat line

Stat line

One row of statistics for one team or player in one fixture, in that sport’s schema.

See alsoBox score

Accounts

Account

A partner: an organization, its people, its keys, its sources and its usage.

See alsoOperatorOrganization

Operator

A Sideline role that sees the whole network — connectors, the review queue, the accounts directory — rather than one account.

The navigation follows the role; the management API enforces it per endpoint regardless of what the navigation shows.

See alsoAccount

Session

One signed-in browser, listed with when it was created and last seen, and revocable on its own.

Suspend

Switching an account off with a recorded reason: its keys stop working immediately and the reason is shown to its users.

See alsoAccount

Values

The strings a status or a class can actually be, and what each one means. These are the same sets the console renders in a badge — hovering one there says exactly what you read here.

Batch status

batch.status

How far a pushed batch has got. A batch is stored and acknowledged before it is applied, so received is a normal answer for a batch that arrived a second ago.

ValueMeans
receivedStored and queued. The raw payload is safe; nothing has been applied yet.
processingA worker is resolving and applying its observations right now.
doneEvery accepted observation was resolved and applied.
failedProcessing stopped on an error. The error is on the batch, and the raw payload can be replayed once the cause is fixed.

Feed and connector status

feed.status

The verdict on the last run. drifted is the one that stops the pipeline: output is held rather than applied.

ValueMeans
pendingRegistered but never fetched. It runs at its next scheduled poll, or immediately if you refresh it.
healthyThe last run fetched and applied cleanly.
degradedThe last run parsed, but the parser had something to say about it — some rows were skipped or incomplete.
failingThe last run could not be fetched, or could not be read at all. The error is on the row.
disabledTurned off — by you, or by the runtime after repeated failure. It will not be polled.
driftedThe page changed shape or the yield collapsed, so the run’s output is held. Nothing was applied: fix the parser, or accept the new shape.

Target state

target.state

Where one target inside a catalog stands. The vocabulary separates what is the hub’s to fix — stale and failing — from what is simply the world being itself.

ValueMeans
discoveredIn the catalog, never successfully fetched. Waiting for its first sync.
unpublishedThe catalog lists it, but the host has not posted a schedule yet. Not ours to fix, and not a fault.
syncingFetched, and inside the freshness SLO for how close its games are to being played.
staleThe last successful sync is older than the SLO allows. Ours to fix.
failingConsecutive failures against a target that used to work. Ours to fix.
dormantFinished and settled; nothing more will change.
excludedThe publisher’s terms, or an operator’s kill switch, says leave this one alone. The reason is recorded on the row.

Source class and rank

source.class

What a source is, and therefore how far it is trusted. Rank 1 wins every field it has an opinion about; rank 6 fills gaps nobody else filled.

ValueMeans
authoritativePush1 · Authoritative pushThe platform that runs the competition, pushing its own data.
partnerApi2 · Partner APIA platform’s API the hub polls with its blessing.
hostFeed3 · Host feedAn iCal or CSV a club or host publishes. Evidence, not gospel.
ownerCorrection4 · Owner correctionA club admin fixing their own record — an observation, not a hand-edit.
scrape5 · Public sourceA schedule its organiser publishes openly, read as evidence. Fills gaps; never overwrites a ranked source.
crowd6 · CrowdA parent reporting a score. Visible, attributed, and outranked by everything.

Fixture status

fixture.status

Nothing here is a delete. A cancelled game stays readable, because the family that saw it yesterday needs to see the cancellation today.

ValueMeans
scheduledOn the calendar and expected to be played.
inProgressin_progressBeing played now.
completedPlayed. A final result may or may not have been reported yet.
postponedNot played at the scheduled time; a new time may follow as a reschedule.
cancelledCalled off. The fixture stays in the API and in calendars, struck through rather than removed.
forfeitAwarded without being played. Standings count it like any other result.

Time status

fixture.time_status

How much to trust the clock on a fixture. Honesty here is what keeps a calendar from lying.

ValueMeans
confirmedThe source published this exact kickoff time.
estimatedDerived rather than published — a bracket slot, a typical start. Treat it as approximate.
tbdThe date is known, the time is not. The fixture carries a date instead of a start instant.

Fixture kind

fixture.kind

Not everything on a team’s calendar is a game, and pretending otherwise breaks the calendar.

ValueMeans
gameA competitive match, with two sides and a result.
practiceA training session. One side, a title, no result.
scrimmageA friendly. Two sides, usually no standings impact.
tryoutA selection session.
eventAnything else on the calendar — a team meeting, a photo day.

Review status

review.status

A proposed merge the resolver would not make on its own.

ValueMeans
pendingWaiting for a decision. Both entities exist separately until then.
approvedMerged: the mappings were repointed and a merged_into pointer set. One undo reverses it exactly.
rejectedLeft apart. The pair will not be proposed again on the same evidence.

API key kind

key.kind

Two kinds of key, and the difference is where they are allowed to live.

ValueMeans
secretsk_test_… / sk_live_…Full authority: push, read, manage webhooks. Server-side only. Shown once; only a hash is kept.
publishablepk_test_… / pk_live_…Read-only, public tier, safe inside a web page. A write attempt returns 403 publishable_key.

Supply tier

connector.tier

How the data got here. The tier decides which console page a source appears on, and how much it is trusted.

ValueMeans
pushA partner posts observations to the hub. The most authoritative route.
pullThe hub polls a partner’s API on a schedule.
feedAn iCal or CSV file, fetched by URL or uploaded.
scrapePublic sourceA schedule published openly by its organiser, read by a versioned connector with validation in front of it.
correctionAn owner fixing their own record, as an observation from a ranked source.

Account status

account.status

Whether an account’s keys work.

ValueMeans
activeNormal. Keys work in both modes.
suspendedSwitched off with a recorded reason. Keys stop working immediately and the reason is shown to the account’s users.

User role

user.role

What one person may do inside an account. Separate from the operator role, which is Sideline’s own.

ValueMeans
ownerEverything, including billing, keys and inviting people.
developerKeys, webhooks, data and the explorer. Not account administration.
viewerRead-only: the data and the logs, no keys and no changes.