ANY /v1/proxy — that accepts any HTTP method and forwards the request to the URL you supply in the X-Knox-Proxy-URL header. References of the form {{ token: ... }} in the body or query string are resolved against your tenant’s vaults before the request reaches the upstream.
For a conceptual overview see the Ephemeral Proxy guide.
Unlike the Routes endpoints — which manage proxy configuration — this endpoint executes a one-shot proxy call. There is no
id to look up, no row to list, and no environment overrides.Invoke
X-Knox-Proxy-URL. Body and query-string {{ token: ... }} references are resolved against your tenant’s vaults before the upstream call is made. The upstream response is streamed back unchanged.
Request Headers
All other headers you send are forwarded to the upstream except for hop-by-hop headers (
Connection, Keep-Alive, TE, Trailers, Transfer-Encoding, Upgrade, Proxy-Authorization, Proxy-Authenticate), the Authorization and Host headers, and any header beginning with X-Knox-.
Request Body
Optional. Sent to the upstream after token substitution. The body is scanned recursively for two template forms:
Anything else shaped like
{{ ... }} is rejected with 400 template_error rather than forwarded to the upstream. See Templates.
Maximum 20 distinct token references per request.
Response
The upstream’s response is streamed back unchanged: same status code, same headers (minus hop-by-hop andContent-Length), same body bytes. KnoxCall adds two correlation headers:
Errors
Templates
{{ token: <token-id> }}
Substituted with the raw value of the matching vault token. Tokens are tenant-globally unique — you do not need to specify the vault.
400 token_not_found. If the token exists but you lack vault:detokenize permission for the vault that owns it, the request fails with 403 (PolicyDenied).
{{ encrypted | json: $.path }}
Reads a value from the decoded X-Knox-Encrypted payload using JSONPath. Useful when you want to keep ad-hoc sensitive values out of your application’s heap.
\{{ ... }} — sending literal braces
Any {{ ... }} that is not one of the two forms above is rejected with 400 template_error. It is never forwarded. That is deliberate: silently passing an unrendered {{ token: ... }} through would disclose the token identifier to the third-party upstream and deliver a request with a hole where a credential should be.
When the braces are meant for the upstream’s own templating, escape the opening delimiter with a backslash. The escape renders a literal {{, and the text after it is never treated as a template — so a single body can carry both:
card_number substituted with the real value, and email_subject as the literal Hi {{ first_name }}, your receipt. Note the doubled backslash: JSON has no \{ escape, so a literal backslash is written \\ in the source.
Only the opening {{ is escapable — a bare }} was never a delimiter and always passes through untouched, so nested JSON such as {"a":{"b":{"c":1}}}} is never rewritten. To bypass templating entirely and forward your bytes verbatim, send X-Knox-Proxy-Mode: transparent instead.
Permissions
Each invocation evaluates two permissions:
The
vault:detokenize check is enforced per token reference, scoped to the vault that owns the token. A denial throws PolicyDenied and the request fails with 403.
Audit
Every invocation writes:- An
api_requestsrow withproxy_mode = 'ephemeral', status code, latency, upstream host, source IP, and token count. The body, headers, and resolved token values are never stored. - An
audit_logsentry taggedephemeral_proxy.invoke(Audit Logs). - A Fleet Graph signal carrying method, upstream host, status code, and latency. The customer’s path is recorded as
/proxy— never the raw upstream path.