Versioning and change

Every partner-facing response tells you which version of this surface answered it. Additive changes ship without notice; anything that could break a correct client needs a new version and 90 days.

The header

X-Peritus-Api-Version: 1

On success and error responses alike, including a 429 and a 404. Log it, assert on it, and quote it to support.

Versions are whole numbers, issued in order. 1 is the first.

Your two pins, and the header that overrides them

Live and test are pinned separately. A call authenticated by your API key — everything on this surface except /embed/…, /partner/admin/…, and the Game API — is answered on that key's own environment's pin when it sends no X-Peritus-Api-Version request header. Try a new version in test without moving live.

POST /partner/admin/api-version moves one environment's pin, from the portal or from your own tooling against the same Firebase-authed admin surface:

POST /partner/admin/api-version Authorization: Bearer <admin token> { "environment": "test", "version": 1 } 200 { "live": 1, "test": 1 }

A version outside what this build serves is refused, 400 unsupported_api_version, and nothing is written. Moving backwards is a plain, unrefused write — the rollback for an upgrade that turned out to break something.

Naming a served version in that same header as a request header uses that version for the one call it's sent on, whatever your account is pinned to. A name this build cannot serve gets 400 unsupported_api_version instead of any version at all. 1 is what this build serves today.

/embed/… and /partner/admin/… carry the response header too, but always at this build's current version — neither authenticates by API key, so neither has an account pin for it to reflect.

Which responses carry it

SurfaceStamped
/partner/… — the session mint, the results feed, and the /partner/admin/… routes the portal drivesYes, including its own 404s and 429s
/embed/… — the frame documentYes
/internal/… — our own ops consoleNo
The player-facing Game API your embedded session callsNo

/internal/… is not a contract with anyone. The Game API is excluded because a partner's embedded player travels the same paths a first-party player does — the same /me/… and /matches/… our own frontend calls. One call to POST /partner/sessions answers the version question for your whole integration.

What may change without notice

Any of these may ship at any time, on the current version:

  • A new field on a response.
  • A new reason code.
  • A new value in an existing enum-like field.
  • A new endpoint.

What that requires of your client

Those changes are additive: a correctly written client is never broken by one. “Correctly written” means exactly two things, and they are requirements rather than suggestions.

  1. Ignore fields you do not recognise. Do not fail to parse a response because it grew a key, and do not assert on the full shape of a JSON object.
  2. Treat an unrecognised reason as the generic failure its HTTP status already describes. A 403 carrying a code your build has never seen is still a 403: refused. Branch on the codes you handle specially and fall through to the status for everything else.

What may not change without a version bump and 90 days' notice

These are breaking, and each one needs a new version and 90 days' notice, with the old behaviour kept working for the whole period:

  • Removing or renaming a field.
  • Removing a reason code, or changing what an existing one means. A code that keeps its spelling but starts describing a different condition is still a break.
  • Changing a field's type.
  • Changing the HTTP status for an existing condition.
  • Tightening validation, so that a request which worked now fails.

Notice is a changelog entry naming the new version, what changed, and when the 90 days start and end. The changelog is below, and the whole document is at /partner-api-changelog.md.

The changelog

One version has been announced, and it is the current one: 1. No notice period is running yet.

Each entry says what moved, when the ninety days started and when they end. Read the full text at /partner-api-changelog.md — published verbatim.

Where the contract itself lives

The version, this policy and every reason code are one document. The error catalogue on this site is generated from that same document, published at /partner-api-contract.md, and every page under /docs is also available as markdown beside it (this one is /docs/versioning.md), with /llms.txt as the index.