Get Passthrough Route by ID
GET /admin/v1/passthrough_routes/{id}
GET /admin/v1/passthrough_routes/{id}Interactive request editor loads with JavaScript.
Authorization
AdminBearer Admin key from config.admin.admin_keys.
In: header
Path Parameters
Passthrough route resource ID, as assigned by the active resource source (a UUIDv5 derived from the entry name in file mode; the etcd key's ID segment otherwise).
Response Body
application/json
application/json
application/json
application/json
curl -X GET "http://127.0.0.1:3001/admin/v1/passthrough_routes/1d95ac57-7f27-46a4-b5a3-55d3c3ad0a12"OK
{
"id": "string",
"revision": 0,
"value": {
"display_name": "string",
"enabled": true,
"forward_client_headers": [
"string"
],
"name": "string",
"provider_key_id": "string",
"timeout_ms": 1,
"hosts": [
"string"
],
"path_prefix": null,
"preserve_host": true,
"target_url": "string",
"identity_header": null,
"auth_header_name": "string",
"auth_mode": "anonymous",
"anonymous_key_id": "string",
"source_cidrs": [
"string"
],
"credential_mode": "forward_client"
}
}Missing or invalid admin key
{
"error_msg": "string"
}Resource not found
{
"error_msg": "string"
}Configuration store operation failed
{
"error_msg": "string"
}Complete operation details and schema variants
GET /admin/v1/passthrough_routes/{id}
Get Passthrough Route by ID
Get an explicit passthrough route resource by ID.
Parameters
id(path, string, required): Passthrough route resource ID, as assigned by the active resource source (a UUIDv5 derived from the entry name in file mode; the etcd key's ID segment otherwise).
Responses
200: OKid(string, required): Resource ID, as assigned by the active resource source.revision(integer, required): Monotonic resource revision: the etcd mod_revision of the entry, or the load generation in file mode.value(object, required): Stored passthrough route configuration.- allOf variant 1
value.anonymous_key_id(string,null, optional): The API key this route's traffic runs as whenauth_modeisanonymous: itsallowed_routes, rate limits, budget and usage attribution all apply, so anonymous traffic keeps a stable, governable principal. Required foranonymous; ignored otherwise.value.auth_header_name(string,null, optional): Header carrying the gateway credential (API key or JWT) whenauth_modeisheader_key, e.g.x-aisix-api-key. LetsAuthorizationcarry the caller's own upstream credential. The header is stripped before forwarding. Lowercase-only so the forbidden credential-slot list in the coupling is exhaustive (matching is case-insensitive on the wire regardless). Required forheader_key; ignored otherwise.value.auth_mode(object, optional): How the gateway authenticates the caller on this route.- allOf variant 1
- oneOf variant 1: Standard gateway credential
- oneOf variant 2: Gateway credential in a dedicated header
- oneOf variant 3: Anonymous (bound principal)
value.credential_mode(object, optional): How the upstream credential is produced.- allOf variant 1
- oneOf variant 1: Inject the ProviderKey secret
- oneOf variant 2: Forward the caller's own credential
value.display_name(string, optional): Accepted as an alternative spelling ofname. Provide the label under exactly one of the two names.value.enabled(boolean, optional): Whether this route is active. A disabled route matches nothing.value.forward_client_headers(array, optional): Inbound client headers forwarded to the upstream even when this route would otherwise strip them, as single-*glob patterns matched case-insensitively against the header name ("authorization","x-trace-*"). Empty — the default — overrides no stripping.
A header the caller sends more than once is forwarded with every value preserved.
A route forwards the caller's headers by default, so this field only matters for the ones it removes: the ProviderKey's strip_headers under credential_mode: inject, and the slot the gateway consumed to authenticate the caller. Naming authorization under auth_mode: gateway_key therefore puts the caller's own credential back on the upstream request in place of the one this route would inject, never both — which is what lets an internal service that already authorizes on the end user's Authorization keep doing so unchanged.
A credential slot — authorization, proxy-authorization, x-api-key, api-key, x-goog-api-key, cookie, and the AWS SigV4 trio x-amz-security-token / x-amz-date / x-amz-content-sha256 — and traceparent / tracestate are forwarded only when a pattern names them exactly. A glob such as "*" or "x-*" is a statement about the operator's own headers, not consent to hand a third party the caller's credential or to graft the caller's trace onto that party's telemetry, so a broad pattern overrides the rest of the strip set and leaves those alone.
This route's own auth_header_name and identity_header are read the same way. Both are slots this route chose rather than ones the gateway owns — under auth_mode: header_key the first carries the gateway credential the caller authenticated with, and the second carries an end-user identity this route records and strips — so a glob does not sweep either, and a pattern that names one in full forwards it.
Headers whose forwarding would break the exchange rather than change who it comes from are stripped whatever the patterns say: host, content-length, the hop-by-hop headers that describe the caller's own connection, and the gateway's x-aisix-* namespace.
value.hosts(array,null, optional): InboundHostvalues this route serves (the forward-proxy entry: a TLS-terminating device delivers plaintext traffic with the original host, e.g.api.githubcopilot.com). Matched case-insensitively, ignoring any:portsuffix; a leading*.wildcard matches exactly one extra label (*.githubcopilot.commatchesproxy.githubcopilot.com). Host-matched requests keep their full path (no prefix stripping unlesspath_prefixalso matched).value.identity_header(string,null, optional): Optional header carrying the end-user identity injected by the upstream network device (e.g.x-aisix-user). Its value is recorded on the usage event for per-employee audit attribution and stripped before forwarding. Lowercase-only so the forbidden credential-slot list in the coupling is exhaustive; credential-bearing names (authorization,cookie, …) are rejected outright — their value on the usage event would be credential retention, not identity.value.name(string, optional): Operator-facing label, unique within the gateway. Referenced by API keys'allowed_routesglobs and used for usage attribution.value.path_prefix(string,null, optional): Gateway path prefix this route serves, e.g./passthrough/openai. Must start with/.
How the prefix is treated depends on the target shape: a target_url route MOUNTS at the prefix, so it is stripped before the remainder is joined to the target base; a preserve_host route MIRRORS an upstream that owns its own path space, so the prefix only selects which requests the route claims and the complete path is forwarded unchanged.
A route WITHOUT hosts must not claim a reserved gateway namespace (/v1, /mcp, /a2a, health probes) — the typed routes would shadow it. A route WITH hosts may use any prefix: host-matched requests dispatch ahead of the typed routes, which is what lets a forward proxy relay an upstream's own namespace (e.g. Copilot's /mcp/... on its chat host). At least one of path_prefix / hosts is required; when both are set the request must satisfy both.
value.preserve_host(boolean, optional): Derive the target from the request's ownHostheader (https://<host>), for forward-proxy routes that fan one route out over several official hosts. Only legal whenhostsis set — the matched allowlist is what makes the derived target non-attacker- controlled (SSRF guard).value.provider_key_id(string,null, optional): ProviderKey whose secret is injected upstream whencredential_modeisinject(per-provider auth shape:x-api-key+anthropic-versionfor Anthropic,Authorization: Bearerotherwise; itsstrip_headersand TLS settings apply). Required forinject; forbidden forforward_client.value.source_cidrs(array,null, optional): Client source CIDRs allowed to use this route. Required (non-empty) whenauth_modeisanonymous— network reachability is the only gate left in front of the anonymous principal. Optional hardening for the other modes; unset means no route-level restriction.value.target_url(string,null, optional): Explicit upstream base URL, e.g.https://api.openai.com. The matched request's remainder path and query are appended. Exactly one oftarget_url/preserve_hostmust be configured.value.timeout_ms(integer,null, optional): Maximum time, in milliseconds, for the upstream exchange. Bounds the response-header phase and any non-SSE body read, but never a healthy SSE relay (which ends with the upstream stream or the client hanging up). When omitted, the gateway default request timeout applies the same way.- allOf variant 1
- anyOf variant 1: Path-prefix match
- anyOf variant 2: Host match
- allOf variant 2
- allOf variant 3
- allOf variant 4
- allOf variant 5
- oneOf variant 1: Explicit target URL
- oneOf variant 2: Preserve inbound host
value.preserve_host(object, required): Set when the route derives its target from the inbound Host instead of target_url.- allOf variant 6
- allOf variant 7
- allOf variant 8
- allOf variant 9
- allOf variant 10
- allOf variant 11
- allOf variant 12: auth_header_name only in header_key mode
- allOf variant 13: anonymous_key_id only in anonymous mode
- allOf variant 14
- allOf variant 15
- anyOf variant 1: name
- anyOf variant 2: display_name
401: Missing or invalid admin keyerror_msg(string, required): Human-readable error message.404: Resource not found Response fields (application/json): identical toGET /admin/v1/passthrough_routes/{id}, response 401 above.500: Configuration store operation failed Response fields (application/json): identical toGET /admin/v1/passthrough_routes/{id}, response 401 above.
cURL
curl -X GET 'http://127.0.0.1:3001/admin/v1/passthrough_routes/{id}'