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.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
error object:
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
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 header — chatcmpl_ 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 bodyid once the switch above ships — to fetch the completion’s full record:
cURL
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:
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.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 theid from a Chat Completions, Messages, or Responses response, ahead of the breaking id change above.
Who is affected:
- Anything that parses
idto 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
idand 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/responsescallers using the returnedidasprevious_response_idfor multi-turn conversations. This keeps working — the gateway translates transparently, see above — but stop assuming the value looks likeresp_...; treat it as an opaque Sunra token.
x-sunra-prediction-idhas 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_idviaGET /completions?completion_id=.
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.