Guides
What the gateway keeps about your requests, the switch that turns content storage off, the policy that restricts routing to zero-retention providers, and the response headers that name the provider behind every answer.
The serving path is content-free. The request ledger that meters every call records metadata and refuses prompt or response bodies by database constraint. Content exists only in the stores below, each with its own window. Captured prompts, captured responses and Responses API continuations are governed by one organization-wide switch; batch files and the replay window are not.
| Store | What it holds | How long | Governed by the content switch |
|---|---|---|---|
| Request ledger | Metadata only: request id, model slug, the provider and deployment of each attempt, route depth, token counts, cost, timestamps, status and failure class. The tables refuse content by database constraint. | Indefinitely (it is the billing record). | No. Always recorded. |
| Captured prompts and responses | The request's messages (up to 1 MiB) and the entire response as it was relayed to you (up to 4 MiB, every streamed frame included). | 30 days from capture; an hourly job deletes older rows. | Yes. Written only while the switch is on, and never for a request served on your own provider key. |
| Responses API continuations | The prior conversation behind a response id, so previous_response_id can be honored on any worker (up to 4 MiB). | 30 days from the last turn that referenced it. | Yes. Nothing is stored while the switch is off. |
| Batch files | The input, output and error JSONL files of /v1/batches jobs. | 48 hours after upload if no job used the file; otherwise until 24 hours after the referencing job's expiry. | No. Batch files follow their own window. |
| Idempotency-Key replay window | The original response bytes for a repeated Idempotency-Key. | 24 hours, in the memory of the worker that served the request. Never written to disk. | No. |
Requests served on your own provider key (bring your own key) never leave content on the platform on any plan; see Customer-managed keys. The privacy policy lists every store, who can read it, and where it is held.
One flag per organization, capture_prompt_content, controls captured prompts, captured responses and Responses API continuations together. It lives in the app under Settings → Organization → Privacy, where an organization admin toggles “Go 100% private”. Members see the state read-only.
403 and reason: needs_subscription.previous_response_id on /v1/responses cannot be resolved, because the prior turns are not stored. The request gets an explicit error asking you to resend the full conversation. Send the whole input on every turn instead.Every actual flip is written to the organization audit log as telemetry.capture_enabled or telemetry.capture_disabledwith the admin as the actor; the automatic Pro flip uses the same action string with a system actor. The switch is also readable and writable through the app's own route, GET / PUT /api/orgs/<org_id>/telemetry-settings with body {"capture_prompt_content": false}. That route takes a signed-in session; it is not admitted for xpl_ API keys.
The content switch governs what the platform keeps. A separate provider policy governs which upstream providers your requests may reach. It is one row per organization with three fields: allowed_providers (a list of provider names, or null for all), require_zdr and require_no_training. With no row, every route in the catalog is eligible.
The policy is applied when a request is routed, at rung granularity and to every lane, including rungs on your own provider keys. Each rung's posture is resolved from a curated matrix keyed by provider and a pattern over the provider's model id, most specific pattern first. A provider or model the matrix does not cover counts as non-compliant. Rungs that fail the policy are removed from the route before any dispatch, so a non-compliant provider is never attempted, not even as a fallback. When no rung survives, the request is refused with HTTP 403, code model_not_granted, type permission_error, and the message “No route for this model satisfies your organization's provider policy” naming the requirement that removed every rung.
Settings → Provider policy (/settings/data-controls) is an Enterprise surface: it exists only for organizations with the data_controls capability and returns 404 otherwise. Admins write the policy; members read it. The same surface is GET / PUT / DELETE /api/orgs/<org_id>/provider-policy in the app (signed-in session, not xpl_ keys); PUT replaces the whole document and every change is audit-logged. Licensing gates management only: a policy that exists keeps being enforced by the gateway whether or not the capability is still licensed. A change reaches the gateway on its next catalog refresh without a restart.
The matrix below is the platform's reading of each provider's published data-handling terms for its default API, not an agreement we hold with the provider. Each row carries the source it is based on and an effective date where the provider publishes one; the full matrix with source notes is GET /api/orgs/<org_id>/provider-data-controls in the app for any member.
| Provider | Zero data retention | No training |
|---|---|---|
| bedrock | Yes, except wire ids matching *anthropic.claude-fable* and *openai.gpt-5* | Yes |
| fireworks | Yes | Yes |
| experiential_cloud | Yes | Yes |
| zai | Yes | Yes |
| novita | Only wire ids matching qwen/*, zai-org/*, moonshotai/*, deepseek/*; other Novita rungs are not | Yes |
| modal, local (your own server) | Yes | Yes |
| openai | No | Yes |
| azure_openai | No | Yes |
| anthropic | No | Yes |
| gemini | No | Yes |
| vertex | No | Yes |
| tencent | No | Yes |
| qwen | No | Yes |
| cerebras | No | Yes |
| wafer | No | Yes |
| xai | No | Yes |
| openrouter | No | No |
| deepseek | No | No |
require_zdron, every OpenAI, Azure OpenAI, Anthropic, Gemini and Vertex rung is removed, along with OpenRouter and the other providers marked “No” above. A model whose waterfall has no surviving rung is refused with the 403 above rather than served elsewhere. Check a model before turning the policy on: GET /api/models/<slug>/providers stamps each rung with its resolved zero_data_retention, and GET /api/models carries a retention verdict per model (zdr_all_rungs, zdr_enforceable, not_zdr) over the platform-funded lanes it actually routes. /v1/models does not carry the verdict.Every completion response carries headers naming the rung that produced it, on /v1/chat/completions, /v1/responses and /v1/messages, streaming or not. The route headers are stamped only after a provider has committed to the request, so they describe the rung that actually answered, never a rung that was tried first and failed.
| Header | Value |
|---|---|
| x-request-id | The gateway request id. Pass it to the lookups below. |
| x-gateway-provider | The catalog provider name of the rung that served the response (for example azure_openai, bedrock, novita). A request on your own key names your provider. A platform-hosted lane presented as Experiential Cloud reads experiential_cloud here and in the body. |
| x-gateway-route-depth | The zero-based position of the serving rung in the route the gateway computed for your organization. 0 is the first rung. |
| x-gateway-route-reason | How the route was chosen: direct for a catalog route; reasoning_continuation when a Responses request continued sealed reasoning on the rung that issued it. |
| x-gateway-canonical-model | The exact model identity the requested slug resolved to. |
| x-gateway-alias / x-gateway-alias-revision | The slug you asked for and the catalog revision that served it. |
The deployment id of the rung is a server-internal identifier and is not returned. Read the provider from the header and the lookups below.
curl -sS -D - -o /dev/null "https://api-pr-1921.preview.experientiallabs.ai/v1/chat/completions" \-H "Authorization: Bearer $EXPLABS_API_KEY" \-H "Content-Type: application/json" \-d '{"model": "gpt-5.5", "messages": [{"role": "user", "content": "ping"}]}' \| grep -i '^x-request-id\|^x-gateway-'
x-request-id: <request id>x-gateway-alias: gpt-5.5x-gateway-alias-revision: <catalog revision id>x-gateway-canonical-model: <exact model id>x-gateway-provider: azure_openaix-gateway-route-depth: 1x-gateway-route-reason: direct
The same provider name is stamped as a top-level provider field beside id and model on non-streaming Chat, Responses and Messages bodies, and on the final usage-bearing frame of a stream (the message_delta event on the Messages surface), together with usage.cost and usage.is_byok. A request sent with an Idempotency-Key carries the headers but not the body fields, so its replays stay byte-identical.
GET /api/v1/generation?id=<x-request-id>returns one request's provider_name, cost and token detail.GET /api/gateway/usage/events lists your requests newest first; each row carries provider(the winning attempt's provider), lane (platform_funded or pass_through) and attempt_count.GET /api/v1/usage, the settled export for billing syncs, carries provider on every row.# provider_name is the catalog provider of the rung that answeredcurl -sS "https://api-pr-1921.preview.experientiallabs.ai/api/v1/generation?id=$REQUEST_ID" \-H "Authorization: Bearer $EXPLABS_API_KEY"# provider, lane and attempt_count per request, newest firstcurl -sS "https://api-pr-1921.preview.experientiallabs.ai/api/gateway/usage/events?org_id=$ORG_ID&limit=20" \-H "Authorization: Bearer $EXPLABS_API_KEY"
A model slug resolves to an ordered list of rungs. The gateway tries them in order and fails over on capacity and transport errors until one rung commits to the request. Failover happens only before that commitment: once a rung has committed, the response comes from that rung and the headers and body name it.
x-gateway-route-depth tells you where the serving rung sat in your route. 0 is the first rung.attempt_count on the usage event tells you how many dispatches the request took. A value above 1 means at least one earlier rung failed on that request before the serving one. A depth above 0 with a single attempt means the gateway placed the first attempt on a later rung rather than failing over.What the tenant surfaces do not expose today: the provider of each failed attempt, the failure reason per attempt, and the reason a rung was reordered or skipped before dispatch. Those are recorded in the ledger and are readable by platform operators only.
A provider connection stores your provider credential in the database vault; the connection row keeps the provider name, the non-secret configuration you entered (such as a base URL or region) and the last four characters of the credential. No API returns the secret; the connection list shows the last four characters only. The secret is released to the serving process when a rung on that connection is dispatched.
lane: pass_through in the usage stream and reports usage.cost: 0, usage.is_byok: trueand the provider's own attributed charge in usage.cost_details.upstream_inference_cost. The provider bills you directly.x-gateway-provider and the body's provider name your provider. The provider policy applies to rungs on your key as well.x-gateway-provideragainst the matrix. Because the served rung's provider model id is not returned, a per-model exception in the matrix (for example the Bedrock or Novita rows above) cannot be resolved from the response alone.The privacy policy and security page state the same stores and windows as commitments. Models covers the catalog's retention verdict and regional availability, and Cost API covers the per-request lookups in detail.