Summary: 7Mind versions its HTTP APIs through two HTTP headers rather than URL prefixes: clients identify themselves and their build via user-agent, and may optionally request a specific response version via accept. The convention is declared once in api-contracts and is expected to be honoured by every client and server in the system.
Sources: direct code inspection (contracts/shared/common.tsp in api-contracts); cross-references a Notion document linked from the contract
Last updated: 2026-05-15
The two headers
Both headers are defined as the VersioningHeaders alias in contracts/shared/common.tsp.
user-agent (always sent)
Format: <APP>/<VERSION>+<BUILD NUMBER> (<META>...)
APP— short app name, e.g.7sleep,7mindVERSION— semantic version of the running app, e.g.1.2.3BUILD NUMBER— monotonic build number, e.g.32META— optional additional metadata (see the linked Notion page for accepted forms)
Example: 7mind/4.12.0+8421 (ios; 17.4)
The server uses this to decide which behaviour to deliver when no explicit accept version is given. Clients must send it on every request.
accept (optional explicit version request)
Format: application/vnd.<APP>.api.<RESPONSE VERSION>+json
APP— the app name (matches the one inuser-agent)RESPONSE VERSION— the requested version label, e.g.v1,v2
Example: application/vnd.7mind.api.v2+json
When omitted, the server chooses a default based on the user-agent — so an old mobile build keeps receiving the response shape it expects without code changes on the client.
Why headers, not URL prefixes
The decision is recorded in Notion (linked from the contract). The short version: header-based versioning lets the same URL serve multiple response shapes, which makes rolling out a new version transparent for clients that do not opt in, and avoids the routing-table explosion of /v1/..., /v2/... URL trees.
What agents should know
- When you add a new endpoint, do not invent a new URL prefix to signal a version. Either evolve the existing response shape backwards-compatibly, or declare a new response version and have the server branch on the
acceptheader. - The
user-agentis the canonical client identifier across elixir-backend log lines, analytics events, and feature gates. Do not synthesise it from other sources. - Clients that omit a valid
user-agentshould be assumed to be the latest version on the server side — the contract does not document a fallback behaviour, so treat missing values defensively. - The header convention is declared in api-contracts but is not enforced by the contract itself — it is enforced by client code and server middleware. Verify both sides when changing behaviour.
Where it lives
- Declaration:
contracts/shared/common.tsp(Shared.Common.Requests.VersioningHeaders) in api-contracts - Client-side application: 7mind-mobile-apps-monorepo and nuxt-website should build these headers on every outgoing request. Exact code paths TBD.
- Server-side application: elixir-backend parses the headers in the public API layer. Exact module path TBD.
Related
- api-contracts — where the convention is declared
- typespec-contracts — the broader contract-first approach
- elixir-backend — server side of the version negotiation
- 7mind-mobile-apps-monorepo — one of the clients expected to send the headers
- nuxt-website — another client expected to send the headers