Help Developers
API versioning
The URL never carries a version. Every endpoint is at the host root, and you choose the API version with a request header:
GET https://api.substratalapps.com/users/me
Substratal-Version: 1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs…
Older material used paths like https://api.substratalapps.com/v1/users. Those paths no longer exist. They return 404 not_found, with no redirect. Drop the /v1 and send the header instead.
Rules
| Rule | Detail |
|---|---|
| The header is required | Without it, every versioned endpoint returns 400 api_version_required, with details.supported listing the versions the API serves. No client ever lands on a version it didn't ask for. |
| Versions are whole numbers | 1 is the only version today. |
| Unknown versions are rejected | 400 unsupported_api_version, with details.supported. |
| Every response echoes it | Versioned responses carry Substratal-Version: 1. |
| A few endpoints are exempt | GET /health, POST /auth/oauth/token, /.well-known/* (JWKS, OpenID configuration) and SCIM under /scim/v2 accept the header but don't need it. Sending it everywhere is simplest. |
| Additive changes don't bump the version | New endpoints, new optional fields, new enum values and new error codes for new conditions ship within a version. Your decoders must ignore unknown fields and treat unknown enum values generically. |
Deprecation and sunset
When a new version ships, the old one keeps working for at least six months. During that window, every response to a request that names the old version carries:
Deprecation: @1798761600
Sunset: Sat, 01 May 2027 00:00:00 GMT
Deprecation(RFC 9745) means the version you sent is deprecated.Sunset(RFC 8594) is the date it stops working. After it, requests naming that version get400 unsupported_api_version.
The Substratal Hub apps act on these headers. They show Update available once a day while a version is deprecated, and a blocking Update required once it's unsupported. See GLB-03 System states.
What counts as breaking
Removing or renaming a field, endpoint or query parameter. Changing a field's type or format. Making an optional request field required. Changing the status or error code for an existing condition. Changing a default that callers rely on. Anything else is additive.
Versions that are separate from the API version
| Version | What it is | Where it's set |
|---|---|---|
Substratal-Version |
The REST API contract | The request header |
openapi.yaml info.version (for example 1.0.0-draft.9) |
The revision of the machine-readable document | The file. It moves on every additive change. |
Webhook payload version (a date such as 2026-10-05) |
The shape of payloads one webhook subscription receives | api_version on the subscription. The Hub calls it Payload version. |
| MCP protocol version | The Model Context Protocol handshake | Negotiated by MCP clients during initialize |
API reference by version
Each API version has its own interactive reference in this help center, built from that version's openapi.yaml. See API reference versions.