Skip to main content
Version: 1.13.0-dev

DVARA headers — request and response reference

DVARA is an AI gateway that governs every call, 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. Create the API key from API Keys in DVARA Flightdeck. Flightdeck applies the signed-in user's role and active workspace. The key starts with gw_, and the full secret is shown exactly once; only a SHA-256 hash is persisted. See Data plane authentication for rotation and revoke flows.

Every /v1 request must carry a valid key. A missing header returns 401 api_key_required; a key absent from the store returns 401 invalid_api_key. Revoked and expired keys return their corresponding 401 codes. The former require-api-key switch was removed in 1.8.0.

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.

A supplied trace ID must contain at most 128 letters, digits, or ._:-. DVARA replaces an invalid value with a new trace ID rather than reflecting it into logs.

# 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 to tie a client's calls to one agent session. On /v1 the id goes into DVARA's logs and, on the Enterprise platform, into the call's session tag. A session killed in Flightdeck is then refused with 403 session_killed on every plane. Loop detection and approval gates run on MCP tool calls and A2A hops in the same session. They do not run on model calls.

A supplied session ID uses the same 128-character and [A-Za-z0-9._:-] contract. DVARA ignores an invalid session ID, so the request is not joined to that session.

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();

Kill a session in Flightdeck under MCP → Sessions (platform roles) or Agents → MCP Sessions (workspace roles). The page lists sessions that made MCP tool calls. A session that only made model calls has no row there, so kill it by its workspace and id with Kill a session by id on the same page.

X-Dvara-End-User and X-Dvara-Tags (MCP and A2A)​

Name the customer a tool call or an agent call is for, and tag it, so its activity adds up with that customer's model calls. This is the MCP and A2A version of the chat request's user field and metadata.tags.

X-Dvara-End-User: cust-42
X-Dvara-Tags: customer=acme,booking=B-1042

You can send the same values inside the protocol message instead. In MCP, put them in params._meta. In A2A, put them in params.metadata or the message's metadata. The keys are dvarahq.com/end_user (a string) and dvarahq.com/tags (an object). A header wins when both name the same tag.

  • At most 16 tags. A key is up to 64 letters, digits or _ . : -. An end user or a tag value is up to 128 letters, digits or _ . : @ + / = -.
  • DVARA refuses a value it cannot accept: MCP answers -32602 (MCP_ATTRIBUTION_INVALID), and A2A answers invalid params. It never drops a value without telling you.
  • DVARA records the values as tags: your tags, the end user as user, and the session as session. These are the same tags a model call gets, so one tag value reads the same across model calls, tool calls and agent calls.
  • These values are what your application says. They do not prove who the caller is. Send an opaque customer id, not a name or an email address.

X-Cache-Control: no-cache​

Send X-Cache-Control: no-cache to skip the response-cache lookup on one request, so DVARA calls the provider. See Bypassing the cache.

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.

HeaderDistributionWhen emittedWhat it means
X-Trace-IDBothAlwaysThe 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 / MISSBoth for exact cache; Enterprise for semantic matchingCache configuredWhether the response came from a cache rather than the provider. A HIT avoids the upstream call. Semantic similarity matching is Enterprise-only.
X-Gateway-Strict-Downgraded: trueBothresponse_format: json_schema with strict: true against Anthropic or AWS BedrockThe provider cannot enforce strict JSON Schema; validate on the client if strictness is load-bearing.
X-Gateway-Failover-Blocked: capability_mismatchBoth503 failover_capability_mismatchThe primary failed and no fallback supports the requested capability.
X-Budget-Remaining-Pct, X-Budget-Remaining-TokensEnterpriseA workspace has a budget capRemaining percentage and estimated token buying power.
X-Policy-Warning: trueBothA policy returned WARN_AGENT (from 1.10.0)Any policy warning. Prefer this header.
X-Budget-Warning: trueBothA rule on budget use returned WARN_AGENTSet only for a warning from a rule on budget use, from 1.10.0. Through the 1.9 releases it was set for every policy warning. Read X-Policy-Warning for any warning.
X-Context-Window-Warning, X-Context-Window-UtilizationBothApproaching the context windowEstimated input tokens crossed the configured warning threshold.
X-Gateway-Pii-UnresolvedEnterpriseResponse detokenization left placeholdersCount of unresolved request placeholders in the reply.
Retry-After, X-RateLimit-Retry-After-SecondsBothA rate limiter returns 429Backoff time in the standard and seconds-only forms.
X-RateLimit-Tokens-Limit, X-RateLimit-Tokens-Remaining, X-RateLimit-ResetBothToken-budget branch returns 429Active token limit, remainder, and reset time.
X-Gateway-Model-DowngradedEnterpriseBudget pressure swapped in a cheaper modelBoth models, as <requested> -> <served>.
X-Dvara-Routing-Tier, X-Dvara-Routing-Complexity, X-Dvara-Routing-Requested-Model, X-Dvara-Routing-Model, X-Dvara-Routing-ReasonEnterpriseIntelligent routing chose the modelThe tier that served the request, the tier the classifier gave it, the model you asked for, the model routing chose, and the classifier's reason (cut to 200 characters). See See what the router decided.
X-Gateway-Params-Not-AppliedBothAn Anthropic call on API version 2026-10-21 left out sampling parametersThe parameters Anthropic was not sent, such as temperature, top_p.
X-Gateway-GroundingBothGrounding detection is on for the workspacegrounded, ungrounded, or unchecked when the request carried no source document. See Hallucination detection.

From 1.8.2 DVARA no longer sends X-License-Warning. Licence expiry never changes a response, so it is reported in DVARA Flightdeck, in LICENSE_* audit events, and on GET /actuator/license instead. See Get and apply a license.

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​