Request ids and metadata
Correlate a request with your own logs, and see how it was served.
Ids on every response
| Header | What it is |
|---|---|
x-op-request-id | Your request id if you sent one, otherwise one we generate. Sent on every response, errors included |
x-op-generation-id | The generation's id (gen_...), the same as the response's id. Sent once a generation exists |
Send your own id to find a request in your logs and ours:
curl https://api.opinference.com/v1/chat/completions \
-H "Authorization: Bearer $OP_API_KEY" \
-H "Content-Type: application/json" \
-H "x-op-request-id: checkout-7f3a" \
-d '{"model": "openai/gpt-oss-120b", "messages": [{"role": "user", "content": "Say hi."}]}'A request id may be up to 128 bytes. A longer one is refused with 400 invalid_request; it is
not truncated.
Quote the generation_id or request id when you contact support.
Status headers
Two headers appear only when something is degraded, and are never sent as false:
x-op-snapshot-stale: true: the gateway is serving from configuration that is older than usual, so a very recent change to your key or prices may not apply yet.x-op-revocation-degraded: true: the gateway could not confirm recent key revocations.
op_metadata on chat
Send x-op-metadata: enabled to receive op_metadata, describing how the request was served:
"op_metadata": {
"generation_id": "gen_...",
"attempts": [{"outcome": "ok", "status": 200, "latency_ms": 1144}],
"finish_reason": "stop"
}| Field | Meaning |
|---|---|
generation_id | The generation's id |
attempts | One entry per endpoint tried, in order, with its outcome and status |
finish_reason | Why the generation ended, including error |
truncated | true when the stream ended before the generation completed. Absent otherwise |
On a non-streaming response op_metadata is a top-level field. On a stream it rides on the last
chunk, beside usage.
op_metadata on media jobs
A job always carries op_metadata, without the header:
| Field | Meaning |
|---|---|
generation_id | The generation's id |
requested_model | The model you asked for |
retention_class | The retention class the job runs under. See Data retention |
region | The region the job runs in |
policy | Notes on your request, such as option_ignored:max_price for a field that was accepted and had no effect |
Session affinity
Send "op": {"session_id": "..."} with the same value across the turns of one conversation. The
gateway then prefers the endpoint that served the previous turn, so a prompt cache on that
endpoint keeps working. It is a preference, not a pin: if that endpoint is unavailable, another
serves the turn.
Tags
op.tags is accepted (up to 8 tags, each up to 32 characters) and has no effect today.