Changelog
All notable changes to the OpenBook standard are recorded here. Format follows Keep a Changelog; versioning follows VERSIONING.md.
[Unreleased]
Added
- Examples page —
docs/examples.mdwalks the existingexamples/documents insequenceorder (GTFS-style sample feed, not a sandbox).publisher.example.jsonlistsbigbookso it matches the market and odds samples. No wire change. docs/protocol-comparison.md— technical comparison of GTFS, GBFS, MQTT, WIS2, FIX, ISO 20022, OpenRTB, Betfair Stream, Sportradar UOF, OsmChange, CAP and ODF against the OpenBook wire (what is adopted, shape-only, later, or rejected).
Changed
- Site layout — header, homepage and doc pages share one wrap width so the logo lines up with the page; the crumb sits with the title; TOC numbers share a gutter.
- Site nav — shorter on-this-page labels (drop the slogan after
:/(); numbered TOC rows align; top nav uses a current-page chip. Spec headings unchanged. - Docs readability — three tracks: a non-technical
docs/guide.md, a humandocs/taxonomy.mdfor shared lists, and a table-and-diagram rewrite ofspec/openbook.md(no wire change). Vocabularies stay the id lists. Guide has a Saturday walkthrough; the decision log has a theme map; homepage has a reading path. Still site/docs only. - Q11 — names on the participant: required
name; optionalshortName,names,nameLatin,alternateName. Teams MAY addlocation,nickname,registeredName,abbreviation. Persons MAY addgivenName/familyName; noabbreviation. Fixtureparticipants[]copiesname.playerhas no name fields. - Logged catalog answers on the wire: league/venue
shortName/registeredName; PlacetimeZone,latitude,longitude; publisherinLanguage/registeredName; leaguegender(men·women·mixed·open) andageGroup; fixturesurface; participantseed. - Q88 — optional
throwsandbatsonplayer(left·right·both). - Q80 —
lineuplive object: fixture-keyed rosterplayerids. - Plan: cover the Pinnacle Lines API (
docs/still-to-do.md). No wire change in that note. - Q97 — Pinnacle specials are markets; no new object (log only).
- Q98 — optional
basisonmarketandodds/change(samescoreUnitlist as score/grade). Omit = sport/leagueprimaryUnit. Identity includesbasis. Not a newmarket:*id. - Q99 — spec only: period offline is a
marketStatusfan-out; settled stays segmentdown+grade. No new fields. - Q100 — no parlay/teaser flags on the fixture (log only).
- Q101 — one fixture;
eventStatusis live.superEventis not a live/pregame pair. - Q102 — keep
sport:*ids; map vendor integers withidentifier/sameAs(log only). - Q103 — market
limitis enough; Get Line is out of scope (log only). - Q104 — typed prop outcomes (CS two counts, HT/FT two results, player on the outcome). Field names not in this pick (log only).
- Q105 — names:
homeTotal/awayTotal;halfTime/fullTime;playeron the outcome;sidetokens odd, even, none, home-or-draw, away-or-draw, home-or-away. Wired with Q106–Q117. - Q106–Q117 — those extras on
market,odds/change, andgrade. One market many rows; player is an id; HT/FT pair; listed CS both totals; listed winning margin who+number; no mixed boards;noneis listed; prop-row pass closed. - Q118–Q125 — winning-margin plus-bands:
atLeast(JSON number; 3 means 3 or more) onmarket,odds/change, andgrade. Plus-band row isparticipant+atLeast(not outcomeline); exact margin keepsline; leftoverotherstill allowed; pass closed. - Q126–Q133 — player yes/no rows (anytime scorer / to score): same
playerid; always present; leftoverothernot used;nooptional; one market, many rows; no marketline; no new field. Pairing onmarket/odds/change/grade. Spec walk stopped. - Q134–Q147 — Q86 leftovers on the wire: catalog
stall(fixture,participant,orderas the gate) andtoss(fixture,participantwho won); liveseries(fixture-keyed lead;stageis the printed round). Not on the generic fixture. Notscore. NotcompetitionTypeseries. Win counts and elected bat/bowl wait. Spec walk stopped.
Removed
localName,additionalName,honorificPrefix,honorificSuffixon participant (pre-1.0; Q11). Native script isnameLatin.
Added
- Input bounds — shared primitives in
schema/common.schema.jsoncarrymaxLength/maxItems, so conformant parsers reject oversized input; covered byconformance/invalid/alternate-name-too-long.json. - Q96 — vendor mapping, starter CLI, and translate ABC are not this spec; planned names openbook-starter / openbook-translate (
docs/decisions.md). Repos not created in this change. - Q95 — protocol-fit pass closed; next work is a new area, not more take/don't-take pins from that comparison list (
docs/decisions.md). - Q94 — no spec-owned multi-publisher index; one discovery URL per publisher (Q49); an aggregator is itself a publisher (Q1) (
docs/decisions.md). - Q93 — FIX session is not the OpenBook session; Q33/Q46 stand (
docs/decisions.md). - Q92 — ISO 20022 is not the OpenBook model or encoding; Q13/Q38/Q44 stand (
docs/decisions.md). - Q91 — JSON Patch (RFC 6902) is never an alternate change encoding; Merge Patch (Q8) stands (
docs/decisions.md). - Q90 — no GBFS-style data wrapper; discovery stays
{ lastUpdated, ttl, feeds }at the root (Q49); objects and change messages stay themselves (docs/decisions.md). - Q89 — JSON (
application/json) is the required v1 encoding; additional encodings MAY exist later as optional bindings; scaffolding stays JSON (docs/decisions.md). - Security model —
SECURITY.mdstates what the standard secures (closed schemas, canonical-id integrity) and what it delegates to deployments (TLS, authn/authz, rate limiting, schema-fetch integrity). - Feed monitoring —
spec/openbook.md§5.3 names the liveness, continuity, freshness, and conformance signals a consumer alarms on. - Q32 — FULL-TRANSITIVE compatibility within a frozen major (
VERSIONING.md). - Q33 — Level L delivery/recovery: all eight guarantees MUST (
spec/openbook.md§5.1). - Q34 — catch-all
unknown/other; consumers MUST tolerate unrecognised values. - Q35 — never reuse frozen ids, list-values, or field names;
vocabularies/deprecated.md. - Q36 — machine-readable deprecation (reason, replacement, sunset); removal only at MAJOR after the window.
- Q37 — closed when you write, open when you read;
x_still vendor extras. - Q38 — camelCase is canonical; current-doc snake_case drift fixed.
- Q39 — odds and lines are decimal strings; money is
{amount, currency}; decimal odds only on the wire. - Q40 — conformance gate is spec + schema + language-agnostic corpus (
conformance/); the Python validator is one runner. - Q41 — GBFS-style ops principles (
ttl, one discovery URL, co-serve versions); two independent implementations freeze 1.0 only. - Q42 — AsyncAPI describes the push streams (
spec/asyncapi.yaml); CloudEvents and DNS-style ids deferred. - Q43 — off the board is
marketStatus; outcome removal is Merge Patchnull;odds: "0"is not a takedown. - Q44 —
baseCurrencyonce per feed; money is{amount}; another currency is another subscription. - Q45 — priced markets MUST carry
limit; sport/league defaults optional; most specific wins. - Q46 —
snapshotCompleteandheartbeaton the wire; publisherheartbeatMs; pull stalesinceis HTTP 410 + RFC 9457. - Q47 — optional envelope
conflated: truewhen ticks were dropped. - Q48 —
ttlinteger seconds (GBFS); optional on publisher, required on discovery. - Q49 — GBFS-shaped discovery document (
schema/discovery.schema.json). - Q50 — one-way docs-vs-schema name CI in
tools/validate.py(spec/docs names MUST exist on a schema; extra schema fields allowed). - Q51 — no consumer-view schema file.
- Q52 — CloudEvents wrap never.
- Q53 — DNS-style ids never; Q4/Q5 stand.
- Q54 — no OpenAPI file in this repo;
since=/ 410 stay in the spec. - Q55 — later PR: schema-diff CI at 1.0+ only.
- Q56 — MCP servers and additional plugins are discovery feeds (
kindmcp/plugin, plusid/schemaUrl). OpenBook does not wrap MCP or ship its schema; payloads stay OpenBook documents. - Q11 / Q57 — names decided (log only): board
name; optional team location/nickname/registeredName; person given/family;shortName; team-onlyabbreviation;names/nameLatin; fixture copiesname. Cite ISO or none. - Q59 — league/venue use the team name package; sport/market/segment
nameonly. - Q60 — season
nameis display; dates are Q9. Stagename+ optional dates. Publishername+ optionalregisteredName. - Q62 — fixture
locationstays nested Place; GeoNames optional; no first-class venue object in this walk. - Q64 — optional IANA
timeZoneon Place; timestamps stay Q9. - Q66 — fixture
nameoptional display; participants +startDateare facts. - Q68 — optional publisher
inLanguage(ISO 639-1); barenameis in that language. - Q69 — Place is city + Q10 territory; no street/postal.
- Q70 — optional WGS 84 lat/long on Place.
- Q71 — no venue capacity field.
- Q72 — optional league category men/women/mixed/open; not on the person.
- Q73 — optional league
ageGroup(U21, …); growable vocab. - Q74 — no date of birth on the wire.
- Q75 — no height/weight; number/position stay on
player. - Q76 —
player.positionfree string; no ISO; vocab later. - Q77 — no kit/colour fields.
- Q78 — no home stadium on the team; match venue is fixture location.
- Q79 — no coach/manager object for now.
- Q80 — match XI is a later live object;
playerstays roster. - Q81 — no referee/officials for now.
- Q82 — omit encyclopedia fields (weather, TV, bios extras, stats dumps, etc.); Q74/Q75 stay omit.
- Q84 — optional fixture
surface(grass/clay/hard/…). - Q85 — optional
seedon the fixture participant row. - Q86 — generic fixture extras stop at surface + seed; no metadata bag.
- Q87 — catalog pass closed; next work is a new area, not more fixture keys.
docs/still-to-do.md— catalog names/place/genderon the wire; Q55 remains a later PR (1.0+).
- Schemas for the objects the spec names but had no schema:
season,player(roster membership),market(snapshot/update document),score(Q23) andgrade(replacessettlement; Q27/Q28). - Three statuses (Q25/Q30):
eventStatus, per-segmentsegmentStatus(downonce, terminal),marketStatus;statusReasonvocabulary. - Units on every score line (Q26):
scoreUnitvocabulary;primaryUniton sport and league ruleset. - Fixture-first topics (Q29):
openbook/v1/<publisher>/<sport>/fixture/<id>/<object>/<action>. - Corrections as errata (
correction: true), never a second down (Q31). vocabularies/segments.md— per-sport segment ids.- Examples:
score.example.json,grade.example.json.
[0.3.0-draft] — 2026-09-12
Breaking rename of the live wire around decisions Q14–Q21. Not frozen.
Changed
- Object/action streams:
openbook/v1/<publisher>/<object>/<action>/<sport>/<id>, keyed by fixture for fixture-scoped objects. Actions: snapshot · create · update · delete, pluschangefor odds only. - One change envelope (
schema/change.schema.json) replaces the per-message schemas:odds/changereplacesodds_change;fixture/updatereplacesfixture_change;market/update(CAP-stylemsgType/references) replacesmarket_status. - Odds push-first:
odds/changeSHOULD be pushed, asince=pull MAY be offered;market/snapshotfor recovery. - Hierarchy: sport → league (
competitionType, optionalorganizer) → season → stage (open, Q20) → fixture → segment. Participants belong to a sport, not a league. *Typenaming for small vocabularies:competitionType,participantType,marketType,stageType.
- Field names are camelCase and follow schema.org (Q13 d):
startDate,dateModified,datePublished,alternateName,sameAs(Wikidata URL, replaceswikidata),identifier(PropertyValue list, replacesexternal_ids),superEvent,eventStatus,location(Place);*Typevocabularies. Documents may carry JSON-LD@context/@type. - Participants: one object for teams and individuals (
participantType); every fixture participant carriesrole(home · away · neutral) andorder(Q22). Name model after vCard/X.520 and ODF (Q11):shortName,abbreviation,alternateName,localName,familyName,givenName… - Stages are recursive (Q20):
stage.schema.jsonwithparentandstageType(phase · group · round · matchday · leg · seriesGame). - Schema files renamed:
reference_participant→participant,reference_region→region,reference_sport→sport.
Added
schema/stage.schema.json;examples/participant.example.json,examples/stage.example.json.schema/change.schema.json,schema/league.schema.json;examples/fixture_update.example.json,examples/market_update.example.json.
Removed
schema/fixture_change.schema.json,schema/market_status.schema.jsonand their examples (folded into the envelope).
[0.2.0-draft] — 2026-09-12
Not frozen; the wire may change before 1.0.
Added
docs/decisions.md— the design decision log (Q1–Q9 decided; Q7 proposed; Q10–Q13 open): purpose, matching via standard facts, provenance, shared vs publisher-own ids, slug + URN id spelling, external ids, diffs everywhere with JSON Merge Patch semantics, sequence-basedsince, ISO 8601 everywhere.docs/building-blocks.md— the widely used standards OpenBook builds on (ISO 3166-1/-2, 639-1, 4217, 8601/RFC 3339, Wikidata, schema.org, RFC 7386, RFC 8141, UUID v7, JSON Schema, OpenAPI, AsyncAPI, CloudEvents, RFC 9457).docs/industry-patterns.md— review of public betting APIs (KIBL, Pinnacle, Betfair, Sportradar, GTFS-Realtime): patterns adopted and avoided.
docs/industry-patterns.md: OpenStreetMap (tag governance, id+version, OsmChange minutely diffs, Wikidata cross-refs) and the weather system (WMO WIS 2.0 MQTT pub/sub and topic hierarchy, OASIS CAP 1.2 alerts, METAR/TAF, GRIB/BUFR, NWS API). Decisions Q14 (stream grammar) and Q15 (alerts) opened.
Changed (the v0.2 spec rewrite)
- Fixtures, leagues, teams and players are publisher-own ids + standard facts (Q2/Q4/Q7); the v0.1 neutral minted fixture id is gone.
source+provenanceon every market (Q1/Q3);sequence+updated_aton every object;fixture_changeandmarket_statusmessages;since=as a sequence cursor; JSON Merge Patch semantics for all changes (Q8).- Wikidata QID as the shared entity id on leagues, participants, players, venues, territories — required when it exists, null otherwise (Q12).
- New schemas:
common,publisher,reference_region,reference_participant,fixture_change,market_status;fixtureandodds_changerewritten. New examples forfixture_change,market_status. - Proposed and implemented provisionally: stream grammar (Q14), CAP-shaped market_status (Q15).
- Region model per Q10: CLDR territories (ISO 3166-1/-2 +
XK/EU/UN) with CLDR localized names;ioc_code/fifa_code/wikidatacrosswalks.
[0.1.0-draft] — 2026-09-12
Initial scaffold. Not frozen; the wire may change before 1.0.
Added
- The two-tier model (reference + live) and core conventions (readable namespaced ids, ISO 8601 / 4217 / 3166, decimal odds).
- Reference objects: sport, region/location, league, season, participant, player, segment, market type, side, fixture.
- Live messages:
odds_change,score_change,settlement,market_status. - JSON Schemas for
reference_sport,fixture,market_type,odds_change. - Controlled vocabularies (starter): sports (with athletics disciplines), market types.
- Governance model (open spec / closed code, staged governance), versioning rules, contributing guide, and validating examples.