Skip to main content
Every LLM request Sunra accepts gets a Sunra-issued id — the same one whether you called Chat Completions, Messages, Responses, or Embeddings. This page documents where that id shows up, how to use it to reconcile a request after the fact, and a breaking change to where the id field in the response body points.

The x-sunra-prediction-id header

Every response from api-llm.sunra.ai — success, failure, streaming or not — carries an x-sunra-prediction-id header once the request has cleared authentication, been routed to a model, and had its record durably persisted:
cURL
The header name says prediction rather than completion — it reuses the same header Sunra’s multimodal API sets on predictions. Both APIs identify a unit of work the same way; the name is not specific to images or video.
The header is exposed for browser callers too (Access-Control-Expose-Headers includes it), so fetch in a browser can read it without a server-side proxy. When it’s absent. Persisting the completion record is the one thing that has to happen before an id exists to report. If that persistence step itself fails — a rare internal error, distinct from the request or the model failing — the response is a 5xx with no x-sunra-prediction-id header, because there is nothing to report yet. Every other failure (rejected input, an upstream provider error, insufficient credit, a stream that gets aborted) happens after the record exists, so the header is present on those.

Errors carry the id too

Once the completion record exists, every error response also carries the id in the body — not just the header. This covers 4xx/5xx responses, a non-2xx JSON body from the upstream provider, an in-stream error event on an otherwise-200 SSE response, and the stream abort frame. Where the id lands depends on the shape of the error body, because Sunra never restructures an error shape to fit a new field — it slots the id into whichever shape is already there:
Object-shaped error
Non-object error shape
The stream abort frame gets the same treatment — the id sits inside the frame’s own error object:
As with the header, a pre-persistence failure carries no prediction_id anywhere in the body — there was never an id minted for that request.

The id field is switching to a Sunra-issued value

Breaking change. Effective date to be announced — this section will be updated with the exact cutover time once it ships. Watch for Sunra’s migration notice before this lands; see Migrating existing integrations below.
Today, the id in a Chat Completions, Messages, or Responses body is the upstream model provider’s own identifier, forwarded as-is. Its format varies by provider and by protocol — chatcmpl- on some Chat Completions providers, msg_ on Messages, resp_ on Responses, or something else entirely depending on who served the request. After this change, id becomes the same Sunra-issued value as the x-sunra-prediction-id headerchatcmpl_ followed by a 24-character identifier — on every protocol, including /v1/responses (which will no longer return a resp_-prefixed id): Only the envelope id changes. Any id nested inside the generated content itself — a tool call id, a reasoning item id, a message item id inside output — is untouched. SSE’s own protocol-level id: field (used for reconnection, distinct from anything inside the JSON payload) is also untouched. The upstream provider’s id is not discarded — it moves to provider_response_id, retrievable through GET /completions?completion_id= below, where it always has been for reconciliation purposes.

Embeddings: no id field

The Embeddings protocol has never had an id field, on Sunra or on the API it mirrors, and this change does not add one — introducing a field outside the documented response shape would itself be a breaking change for a strict response parser. For an embeddings request, the x-sunra-prediction-id header is the only place to find the tracking id.

Looking up a completion later

Use an id — from the header, or from the body id once the switch above ships — to fetch the completion’s full record:
cURL
The fields most relevant to reconciliation: This is the same endpoint whether the completion predates or postdates the id cutover — pass whichever id you have (a Sunra chatcmpl_ id, or a provider-native id captured from a response before the switch) and it resolves the same record.

Continuing a conversation: previous_response_id

On /v1/responses, pass the id you got back from a prior response as previous_response_id to continue that conversation:
Send exactly the id Sunra gave you. The gateway resolves it to whatever the upstream provider needs internally, so continuation keeps working across the id field’s switch to a Sunra-issued value — you never need to know which upstream shape is behind a given response. An id Sunra doesn’t recognize — mistyped, belonging to a different organization, or one it never linked a continuation for — is rejected with 400 invalid_request_error rather than silently starting a fresh conversation.
Transition period. Sunra also still accepts the upstream provider’s own native response id (a pre-cutover id value, e.g. resp_...) in previous_response_id, so continuations started before the switch keep working. This fallback is temporary and will be removed once the migration window closes — send the id Sunra returns rather than relying on it.
If linking fails. In rare cases the gateway cannot record the mapping needed to translate previous_response_id for one specific response (an internal write failure). That response still delivers normally and is billed normally — nothing about the conversation you already had is affected. The only consequence is narrow: a follow-up request that names that one response’s id as previous_response_id gets 400 invalid_request_error instead of continuing. Start a new conversation (omit previous_response_id) and carry on from there.

Migrating existing integrations

This section is for callers who already parse or store the id from a Chat Completions, Messages, or Responses response, ahead of the breaking id change above. Who is affected:
  • Anything that parses id to infer the upstream provider or model family — its format is provider-specific today; after the change every provider returns the same Sunra-issued shape.
  • Anything that stores id and later looks it up in the provider’s own dashboard, logs, or billing export — that value is still available, just no longer in the response body (see below).
  • /v1/responses callers using the returned id as previous_response_id for multi-turn conversations. This keeps working — the gateway translates transparently, see above — but stop assuming the value looks like resp_...; treat it as an opaque Sunra token.
What doesn’t change:
  • x-sunra-prediction-id has carried the Sunra-issued value since it shipped and is unaffected by this cutover — a caller who already reads the header sees the same value the body now also carries.
  • The upstream provider’s id is still recorded and still retrievable, just relocated from the body to provider_response_id via GET /completions?completion_id=.
Reconciling across the cutover. Whichever value you have on hand — the header, or a stored body id from before or after the switch — GET /completions?completion_id= resolves it to the full completion record, including the upstream provider’s own id. Use it to bridge historical data that was keyed on the old provider-native ids. Timeline. Treat id as an opaque, Sunra-owned token from here forward — stable in shape, not meaningful to parse — and use GET /completions whenever you need the value a specific upstream provider actually assigned.