Skip to main content

Client settings cover the seam between your callers and your providers: what address clients dial, which of their headers survive the hop, and what Rolter attaches on the way out.

Edit them from Settings → Client Settings in the dashboard, or through the management API. Changes reach every gateway through the config snapshot, with no restart.


Base URL#

The address clients point their SDK at: the gateway’s own root, such as https://gateway.example.com. Set it when the gateway sits behind a load balancer or on a custom domain. The dashboard builds every connection snippet from it (the request on the Getting started card, the Playground’s Copy as code and the example request on this screen), so what you copy is what a caller can reach.

Enter it without /v1, since the snippets add the path themselves. A trailing /v1, the way the OpenAI SDKs write their base URL, is dropped rather than doubled.

Leave it empty and the dashboard shows no connection snippet: it asks you to save a base URL instead. The dashboard’s own /gw proxy is never offered as an address for your clients. It requires a dashboard session as Authorization: Bearer <session token> (or the admin token; a control plane in open mode needs none), which a client outside the dashboard does not have, and each call passes through the control plane on its way to the gateway. The Playground and the gateway status pill are the proxy’s callers: they send the session, and the virtual key goes in an x-rolter-gateway-key header, which the proxy forwards to the gateway as Authorization: Bearer <key>.

Every signed-in user’s snippets use the saved base URL, whatever their role. Only a superadmin can read client settings, but the address is not a secret (it is what clients already dial), so GET /api/v1/auth/me returns it as gateway_base_url (null when none is saved) for any session.

This value is advisory: the gateway never reads it, and setting it does not change what the gateway listens on.


Forwarded request headers#

An allowlist of inbound client headers passed through to the upstream provider. Anything not on the list is dropped at the gateway — that is the default, and an empty list means Rolter sends exactly what it sent before this setting existed.

Trace-context headers (traceparent, tracestate, b3) propagate whether or not they are listed, so distributed tracing cannot be broken by editing this list.

Some headers can never be forwarded, because forwarding them would hand a caller the gateway’s own credentials or corrupt the upstream request: authorization, x-api-key, api-key, host, content-length, content-type, transfer-encoding, connection and cookie. Listing one is rejected.

anthropic-* headers forward by prefix#

Every inbound header beginning with anthropic- is forwarded to an Anthropic-dialect upstream unchanged, without an allowlist entry — including values Rolter has never seen.

Anthropic extends its protocol through headers: a capability pairs an anthropic-beta value with body fields, and the pair travels together. A closed allowlist against a vendor that ships new capabilities as new header values means every new beta breaks until someone adds it by name, and it does not fail gracefully — stripping the header while the body passes returns a hard 400 (Extra inputs are not permitted), while capabilities such as extended context simply never take effect.

Note

The match requires the separator, so a header merely starting with those letters (anthropicfoo) is not in the namespace. These headers are also dropped again for a provider that does not speak the Anthropic dialect, so an OpenAI-shaped upstream never receives them.

anthropic-version is the one value Rolter resolves rather than copies: the client’s wins when it sends one, and the deployment’s configured anthropic_version is the fallback for requests translated from the OpenAI dialect, where the client stated none. Exactly one value is sent.


Injected upstream headers#

Static name/value pairs Rolter adds to every upstream request — a partner id, a routing tag, a billing dimension your provider expects.

Injected headers are applied before trace context, so a trace header of the same name still wins. Values are treated as deployment credential material: they reach the gateway through the snapshot, but they are never written to the audit log. The log records which header names changed, not what they were set to.

The same reserved list applies here.


Request ID header#

The header carrying the end-to-end request id. Rolter reuses the caller’s value when one is present, mints a UUID when it is missing or blank, and echoes it on the response so a client can find its own call in the logs. The same id is the request_id of the call’s row in LLM Logs and the MCP tool-call log, and it appears on the gateway’s log line for a failed request.

Default is x-request-id. Set another name, such as x-correlation-id, when your clients already send their id under it. The gateway then reads and echoes only that header: an x-request-id a caller sends is ignored, and none is added to the response. A change reaches every gateway with the next snapshot and applies from the next request, without a restart.

The id is not sent to the provider unless you list the same header under Forwarded request headers. A listed header carries the caller’s id, or the one Rolter minted, so the provider’s logs and yours share it. An MCP server receives it either way, because the MCP proxy passes the caller’s headers through.

The name must be a valid header name. Besides the reserved names above, it cannot be a header that carries a credential, session state or message framing, because the id is copied into the logs and written onto the response: x-goog-api-key, proxy-authorization, set-cookie, expect, te, trailer, upgrade, keep-alive and the other hop-by-hop headers are refused as well.


API#

Both endpoints are superadmin only: no deployment role reaches them. Every update is audited.

The read response also carries always_propagated, reserved and request_id_refused (every name refused as the request id header), so a client does not have to hard-code any of the lists. The dashboard checks the Request ID header field against request_id_refused before you save.

On the Client Settings screen each problem is shown under the field it is about, and the footer counts them. Save changes stays off until the form differs from what is saved, the footer says when there are unsaved changes, and leaving the screen with unsaved changes asks first. A saved change reaches the gateways on their next config poll, without a restart.