Skip to main content
You may have landed here from a 410 response — this page names the replacement for every retired endpoint. If you are moving from another provider to Sideren, start with Migrating from other providers instead.
Your base URL, your API keys and your request shapes do not change on the v2 core. What changes: a set of legacy endpoints is gone for good, every model has one public id, errors carry more precise statuses, and a few new headers tell you — and let you control — what happened on each request.

Retired endpoints (410 Gone)

The following surfaces are retired. A request to any of them — any method, any sub-path — returns 410 with a JSON error body whose message names the replacement, plus a link: <...>; rel="help" header pointing here. A 410 is permanent: don’t retry it, move the call.
Example 410 body
Everything else keeps working: Chat Completions, Messages, Responses, Embeddings, count_tokens, GET /v1/models and Idempotency-Key. The per-endpoint notes are on Retired endpoints.

One public id per model

Every model has one public id. Closed-weight models are called by their plain name (gpt-6.1-sol, sonnet-4.6); open-weight models are called @sdn/<name> (@sdn/glm-5.3). The older spellings (sdn-glm-5.3 and the bare glm-5.3) keep resolving to the same model, and the response echoes the id you sent; canonical ids appear in x-sideren-requested-model. You don’t have to change anything day one — but new tooling should write public ids, and GET /v1/models lists them that way, with the older spellings under each entry’s aliases. In YAML, quote an id that starts with @: model: "@sdn/glm-5.3".
If the model you ask for can’t be served (a disabled id, for example), Sideren serves a similar available model and discloses it — unless exact mode is on. With exact mode (per key, or the x-sideren-exact header below), you instead get a 404 model_unavailable: non-retryable, with an alternatives list containing only models your plan can actually serve. Don’t auto-retry it — pick an alternative. The same 404 is also returned without exact mode when no usable alternative exists (every candidate is unavailable or outside your plan) — there is nothing to fall back to, so refusing is the honest answer.

Errors say why, by cause

Statuses map to causes, so your existing retry logic keeps working without configuration — but only retry what can succeed: The 16 MiB limit applies to Chat Completions, Responses, and Messages request bodies before upstream dispatch. The error message names the limit. Two behaviors worth knowing beyond the table:
  • No hung connections. Before admitting a request, Sideren predicts whether it can start (and finish, for non-streaming) inside the time your client will actually wait. When it can’t, you get the immediate 429/503 with retry-after from the table — not a connection that dies later. See Reliability.
  • Streams keepalive. While a queued stream waits, Sideren sends SSE keepalive traffic so client idle timeouts don’t fire; first-byte timing is bounded per client profile.
Full status/code tables and retry recipes: Errors. retry-after semantics: Headers.

Disclosure headers on the response

The v2 core tells you what actually happened. All are read-only facts, all documented on Headers: The rate-limit headers replaced the ad-hoc x-sideren-rpm-* names: those are still sent as deprecated aliases for one release, then removed — move parsers to the names above.

Opt-in request headers

Three switches are off by default and opt-in per request (or per key, in your dashboard’s key settings): Session affinity headers are optional and separate — x-sideren-session (your stable id for one conversation), x-sideren-principal (your id for the end user, when one key serves many), x-sideren-branch (a fork of a conversation) and x-sideren-client (name/version). They keep an agent loop’s turns on a warm cache. The setup helper stamps them for you in the tools it configures.

Idempotency-Key

Send an Idempotency-Key (a fresh UUID per logical request) on any POST, and a retried request is answered from the first attempt instead of running the model — and billing it — twice. Keys are remembered for 24 hours, scoped to your API key and matched against a canonical hash of the body: Details, edge cases and what idempotency can’t undo: Idempotency.

Stateful Responses

POST /v1/responses with store: true persists the response under your key; later turns chain on it with previous_response_id and send only the new input. Stored responses — and only those you asked to store — are kept for up to 1 year, scoped to the key that created them, and you can delete them at any time from the dashboard. Request/response content retention, deletion and zero-retention keys are covered in our privacy policy; the API surface on Responses. For work that should outlive its connection without holding one open, use background: true and read the result back with GET /v1/responses/{id} — the replacement pattern for the retired batches surface.

A five-point client checklist

1

Grep for retired paths

grep -rn 'v1/completions\|/batches\|agent-runs\|/states\|/artifacts\|tool-connectors\|tool-catalog' src/ — anything that hits these needs the replacements above before v2, and gets a helpful 410 after.
2

Retry only what can succeed

429 and 503/529 with retry-after yes; 400, 402, 403, 404 and every 410 no. The official SDKs already follow this — hand-rolled clients should match Errors.
3

Read the disclosure headers

Log x-sideren-served-model next to the id you sent; branch on x-sideren-dropped-tools and x-sideren-reasoning-continuity when they appear.
4

Put idempotency keys on every POST

Especially agent loops and payment-adjacent calls. One UUID per logical request.
5

Prefer public model ids

Older spellings still resolve, but write public ids (@sdn/glm-5.3, gpt-6.1-sol) in new configs and read the catalog at runtime with GET /v1/models.