Skip to main content

API versioning

The public API uses dated versions, the same scheme as Shopify, so a version you build against won't shift under you. Dated versions are the coarse boundary for breaking changes; within a version the schema still evolves additively.

Version names​

A version is named YYYY-MM, where the month is a quarter start: 2026-01, 2026-04, 2026-07, 2026-10. A new dated version is cut only when there is a breaking change — quarters with no breaking change are skipped, so versions are relatively rare.

There is also an unstable version that tracks the leading edge, for previewing changes ahead of a stable release. Don't build production integrations against it.

Selecting a version​

Two ways, in order of precedence:

  1. URL path (recommended): put the version in the endpoint — …/backend/<subdomain>/api/2026-07/graphql. It's explicit, cache-friendly, and copy-pasteable.
  2. Request header: send X-Api-Version: 2026-07 against the bare …/backend/<subdomain>/graphql endpoint.

If you omit the version — or name one that is unknown or past its sunset — the request is served by the oldest still-supported version, never the newest. You are never silently upgraded onto a breaking change. Pin a version explicitly for any integration you intend to keep.

Every response echoes the version that served it in an X-Api-Version header, so you can always tell which contract answered — and detect drift if you relied on the fallback.

Support window​

Each stable version is supported for at least 12 months, with at least 9 months of overlap with the next one. In practice two to three versions are live at any time, which is a comfortable window to migrate in. A version's sunset date is published the day it ships.

What counts as a breaking change​

Within a single version we may make additive changes, and your client must tolerate them:

  • adding a new type, query, or mutation;
  • adding an optional argument to an existing field;
  • adding a field to an object type;
  • adding a value to an enum (so never assume an enum is closed).

A new dated version is reserved for genuinely breaking changes: removing or renaming a field or type, tightening nullability, or changing the meaning of an argument or a default. Those never happen inside an existing version — the version you pinned keeps its behavior until its sunset date.

Deprecations​

Deprecations are signalled two ways, so you learn about them before anything breaks:

  • In the schema. A field being retired is marked @deprecated with a reason that names its replacement. Introspection and the GraphQL Playground surface this to every client automatically.
  • In the response. When a request actually resolves a deprecated field, the response carries an X-Api-Deprecated-Reason header (and a matching extensions.deprecations entry) naming the specific deprecations it touched — so a deprecation shows up in your logs the moment you hit one, without your having to go looking for it.

A deprecated field is kept for a published minimum period before it is removed in a later dated version.