Skip to main content
Version: 1.7.0

DVARA headers — request and response reference

DVARA is an AI governance platform, so every /v1/* request is already audited with a server-generated trace ID. The headers below let you authenticate, correlate the audit trail with your own request identifiers, and read the signals DVARA emits back on the response.

Request headers

Authorization: Bearer gw_…

Required on every data-plane request. The API key is minted in the DVARA Flightdeck (/portal/keys for workspaces, /workspaces/{id}/keys for operators) and starts with gw_. The full secret is shown exactly once at creation time — only a SHA-256 hash is persisted server-side. See Data plane authentication for rotation and revoke flows.

A key that is presented must be valid, whatever the posture. dvara.llm-gateway.data-plane.require-api-key governs one narrower question — whether a request may arrive with no key at all — and the two cases return different codes:

requestrequire-api-key=false (default, development)require-api-key=true
no Authorization header200, served as anonymous401 api_key_required
a key absent from the store401 invalid_api_key401 invalid_api_key

Measured on 1.7.0 in both postures. The second row is what changed in 1.7.0: a wrong key used to be served as anonymous under the permissive default, which was the one credential failure a caller could not detect — the response was a 200 while the request carried no workspace, so budgets, PII action, rate-limit overrides and strict-BYOK silently did not apply. Sending no key and sending a wrong key are different acts, and only the first is a development convenience.

X-Trace-ID

Pass X-Trace-ID for distributed tracing correlation. DVARA resolves the trace ID in this order: (1) client-supplied X-Trace-ID / X-Trace-Id header, (2) the OTel trace ID from the current span when OpenTelemetry tracing is active, (3) a random UUID. The chosen value lands on the audit event, the SLF4J MDC, and is echoed back as the X-Trace-ID response header.

# Python (OpenAI SDK)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
extra_headers={"X-Trace-ID": "my-trace-123"},
)
// TypeScript (OpenAI SDK)
const response = await client.chat.completions.create(
{
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
},
{ headers: { "X-Trace-ID": "my-trace-123" } },
);
// Java (LangChain4j)
OpenAiChatModel model = OpenAiChatModel.builder()
.baseUrl("http://localhost:8080/v1")
.apiKey("your-dvara-api-key")
.modelName("gpt-4o")
.customHeaders(Map.of("X-Trace-ID", "my-trace-123"))
.build();

The same trace ID will appear on:

  • The GATEWAY_RESPONSE audit event (one per request through the data plane), and any other event types fired downstream by policy, PII, guardrail, MCP, or admin paths — trace_id lives on the access log line surrounding the event, so a single grep on the trace ID reconnects every layer
  • The X-Trace-ID response header DVARA sends back to you
  • The OTLP span emitted for the request (when tracing is enabled)

X-Session-Id

Pass X-Session-Id for agent session tracking. DVARA groups requests sharing a session ID into a single agentic session, which activates loop detection, approval gates, and session-level audit grouping.

response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Continue our conversation"}],
extra_headers={"X-Session-Id": "agent-session-456"},
)
const response = await client.chat.completions.create(
{
model: "gpt-4o",
messages: [{ role: "user", content: "Continue" }],
},
{ headers: { "X-Session-Id": "agent-session-456" } },
);
OpenAiChatModel model = OpenAiChatModel.builder()
.baseUrl("http://localhost:8080/v1")
.apiKey("your-dvara-api-key")
.modelName("gpt-4o")
.customHeaders(Map.of("X-Session-Id", "agent-session-456"))
.build();

Sessions appear in the DVARA Flightdeck under Agents → Sessions, where you can see loop-detection status, kill a runaway session, or drill into every request the session produced.

Response headers

DVARA stamps response headers to signal in-band conditions that don't justify a non-2xx but a well-behaved client should react to. None of these break the OpenAI wire format; they layer on top.

HeaderWhen emittedWhat it means
X-Trace-IDAlwaysThe trace ID DVARA resolved for the request — echo it in your application logs to grep across the audit, tracing, and provider-log layers.
X-Cache: HIT / MISSAlwaysWhether the response came from the semantic cache rather than the provider. A HIT books $0 — the served tokens are still recorded, but no upstream call happened so no cost record is written. Note the default matching: DVARA uses vectors as a prefilter but serves only on an exact cache-key match unless cache.semantic.similarity-serving is on, so a HIT means the same request, not a similar one.
X-Gateway-Strict-Downgraded: trueresponse_format: json_schema with strict: true against Anthropic or AWS BedrockThe underlying provider cannot enforce strict JSON Schema. DVARA still issues the tool-use rewrite, but a non-conforming response will not be rejected upstream — validate on the client if strictness is load-bearing.
X-Gateway-Failover-Blocked: capability_mismatch503 failover_capability_mismatchThe primary provider failed and no fallback on the route supports the requested capability (e.g. all fallbacks are vision-blind for an image request). Add a capable fallback to the route or change the request.
X-License-WarningLicense is EXPIRING_SOON (≤30 days) or GRACE_PERIOD (expired, within 14-day grace)The gateway is still serving traffic but the operator should renew. Surface this to SRE alerting so it doesn't fall to a degraded state.
X-Budget-Remaining-Pct, X-Budget-Remaining-TokensEvery request from a workspace that has a budget cap — not only once a threshold is crossedPercentage of the cap still unspent, and roughly how many more tokens that buys at this model's price. Measured on 1.7.0: a workspace 0.4% into its cap gets X-Budget-Remaining-Pct: 100. Absent entirely when no cap governs the workspace, which is how you tell "no cap" from "cap with room left".
X-Budget-Warning: trueA policy rule returned WARN_AGENTDespite the name, this is not a budget signal. It is set when the policy engine warns rather than denies, and it fires with no budget cap configured at all. If you are alerting on budget pressure, read X-Budget-Remaining-Pct; if you are surfacing policy warnings to an agent, read this.
X-Context-Window-Warning, X-Context-Window-UtilizationApproaching the model's context windowThe estimated input tokens are over the per-workspace guardrail.context.warning-threshold-pct (default 70%). At the hard threshold a 400 context_window_exceeded is returned.
X-Gateway-Pii-UnresolvedA response contained PII placeholders that could not be turned back into real values, and pii.auto-detokenize-response is onThe count of placeholders still in your reply. DVARA replaces personal data with a placeholder before sending your prompt to the provider, and swaps the real values back in on the way out. This header says how many it could not swap back — so the text you received still contains {{PII_TYPE_…}} markers rather than the original values. Only placeholders that were in your request are counted, so a marker the model invented does not inflate it. The header carries a count and nothing else: never the placeholder, never the value it stood for. Treat any non-zero value as a data-quality signal on that response — there is no human in this path to notice it for you.
Retry-After, X-RateLimit-Retry-After-Seconds429 rate_limit_exceeded or 429 priority_throttledStandard rate-limit backoff envelope on every 429 — Retry-After is the canonical HTTP header, X-RateLimit-Retry-After-Seconds is the same value in seconds-only for SDKs that don't parse Retry-After. Honor either to avoid hammering the window.
X-RateLimit-Tokens-Limit, X-RateLimit-Tokens-Remaining, X-RateLimit-Reset429 rate_limit_exceeded when the token-budget branch trippedAdditional headers on the token-budget reject path (not the request-count reject path). The limit + remaining tell the client the per-key token budget and how close it was; X-RateLimit-Reset is the ISO-8601 instant the 60-second sliding window resets. Distinguish a token-budget 429 from a request-count 429 by checking these headers' presence, or by reading error.rate_limit.limited_resource in the body.

The HTTP error envelope ({"error": {"type": "...", "code": "...", "message": "...", ...}}) is documented separately in Error handling.

Why this matters for governance

Trace IDs and session IDs are the join key between:

  1. Your application's structured logs
  2. Your tracing backend (Jaeger, Tempo, Honeycomb)
  3. DVARA's tamper-evident audit trail
  4. The upstream provider's request logs (via propagation)

Without them, when a policy fires a denial at 3 a.m. you know what was blocked but not which customer request triggered it. With them, one grep on the trace ID reconnects every layer of the stack.

Next steps