Versioning and beta flags
The Syntic API changes over time. Versioning lets it change without breaking the code you already run, and beta flags let you try features before they are final. Two request headers do the work:
| Header | Value | Purpose |
|---|---|---|
syntic-version | A date, such as 2026-11-01 | Which behaviour of the stable API you want. |
syntic-beta | One or more flag names, comma separated | Turns on preview features. |
Both are optional for stable endpoints. Preview endpoints require their syntic-beta flag.
What counts as a breaking change
A new dated version is published only for changes that could break working code:
| Breaking (new version) | Not breaking (shipped to every version) |
|---|---|
| Removing or renaming a field, endpoint or event type | Adding a new endpoint |
| Changing a field’s type or meaning | Adding optional request fields |
Changing a default (for example, the default of stream) | Adding response fields or new event types in a stream |
| Changing the error format or an existing error code | Adding new error codes within an existing type |
| Making an optional field required | Adding new enum values to fields documented as open-ended |
| Tightening validation so previously accepted requests fail | Raising limits |
Write your client to ignore unknown fields and unknown event types; then only dated versions can affect it.
syntic-version
syntic-version: 2026-11-01- Default per key. Each API key is pinned to the latest version on the day it is created. A request without the header uses its key’s pinned version, so a deploy never changes behaviour underneath you.
- Override per request. Send the header to use a different version for one request: newer to try an upgrade, older to keep legacy behaviour in one code path.
- Keys created before versioning launches are pinned to
2026-06-01, which is today’s behaviour exactly. - The version a request used is echoed in the response header
syntic-version. - An unknown date fails with
400 invalid_request, codeinvalid_version.
Published versions
| Version | Changes from the previous version |
|---|---|
2026-06-01 | The original /v1 behaviour: flat error bodies, stream defaults to true, sampling fields accepted and ignored, upstream errors passed through as upstream_error. |
2026-11-01 | Errors use the error envelope. stream defaults to false. Unsupported sampling fields return 400 unsupported_parameter instead of being silently dropped. Normalised finish_reason values. |
Upgrading
- Read the changes for each version between your pinned one and the newest.
- Send
syntic-version: <new>from a test environment and run your tests. - Roll the header out to production.
- Optionally, create new keys (which are pinned to the latest version) and retire the old ones; then you can drop the header.
syntic-beta
syntic-beta: agents-2026-11-01, webhooks-2026-11-01Preview features are named by a flag. Without the flag, a preview endpoint answers 400 invalid_request with code beta_required, and preview request fields on stable endpoints are rejected with unsupported_parameter. An unknown flag answers 400 unknown_beta, so typos do not go unnoticed.
| Flag | Covers |
|---|---|
agents-2026-11-01 | /v1/agents, /v1/sessions, /v1/agents/executions, /v1/environments, /v1/memory_stores, /v1/vaults, /v1/deployments, /v1/skills |
admin-2026-11-01 | Every /v1/organizations/* endpoint of the Admin API |
webhooks-2026-11-01 | /v1/webhooks |
token-exchange-2026-11-01 | POST /v1/oauth/token (workload identity) |
Other preview features list their own flag on their page. The flags in force are echoed in the response header syntic-beta.
Beta features can change shape between flag versions without a new syntic-version. When a feature becomes stable its flag keeps working for 90 days and is then ignored, so you can remove it at your own pace.
Deprecation policy
- A
syntic-versionis supported for at least 12 months after a newer one is published. - Deprecations are announced in Release notes, by email to organization Owners, and in the response header
syntic-deprecationon affected requests, at least 6 months before removal. - A retired version is never removed silently: requests pinned to it are moved to the oldest supported version, and each response carries a
syntic-deprecationheader saying so. - Models follow their own schedule on Deprecations.
Examples
curl -sS -i https://app.syntic.ai/v1/chat/completions \
-H "Authorization: Bearer $SYNTIC_API_KEY" \
-H "Content-Type: application/json" \
-H "syntic-version: 2026-11-01" \
-d '{"model": "Amara Quick", "messages": [{"role": "user", "content": "Hi"}]}' \
| grep -i '^syntic-version'The official Python and TypeScript SDKs send the version they were built against automatically.
Errors
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request_error | invalid_version | syntic-version is not a published date. |
| 400 | invalid_request_error | beta_required | A preview endpoint or field without its flag. |
| 400 | invalid_request_error | unknown_beta | A flag name that does not exist. |
Build notes for the platform team
- Decide and ship this before the second public endpoint, so every later endpoint is born versioned.
- Store
pinned_versionon the key row at creation. Resolve the effective version once per request in the shared request wrapper and pass it down. - Keep version differences in small adapters at the edges (request parsing, response and error shaping), never scattered
if versionchecks in business logic.