> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ephemeral Proxy

> One-shot proxy for sensitive requests. Resolve vault tokens on the wire so raw card data, PII, and secrets never touch your application.

# Ephemeral Proxy

The **Ephemeral Proxy** is a one-shot HTTPS proxy. Unlike [Routes](/essentials/routes/what-are-routes), there is no pre-configured row — every call is its own invocation. You pass the upstream URL in a header, KnoxCall validates it, swaps any `{{ token: ... }}` references for the underlying vault values, and forwards the request.

The composition with [Vaults](/essentials/secrets/secrets-overview) is the killer feature: **store the token in your database, send the token to KnoxCall, KnoxCall sends the raw value to the upstream.** Your systems never hold the raw card number, SSN, or API secret.

## When to use it

Use Ephemeral Proxy when:

* The destination URL is dynamic — chosen per-request, not per-route.
* You want to detokenize vault tokens last-mile (PCI-scope reduction, PII handling).
* You need a quick passthrough without configuring a Route, ApiKey scope, environment overrides, etc.

Use [Routes](/essentials/routes/what-are-routes) when:

* You call the same upstream repeatedly and want signing, rate limits, env overrides, and full per-request observability.
* You need IP allowlisting, mTLS, or method-specific configuration.
* You want logs grouped by route in the dashboard.

## How a request flows

```text theme={"dark"}
Your client → POST https://api.knoxcall.com/v1/proxy
              X-Knox-Proxy-URL: https://api.stripe.com/v1/charges
              Authorization: Bearer tk_live_...
              Content-Type: application/json

              { "amount": 5000,
                "currency": "usd",
                "source": "{{ token: tok_01H... }}" }

KnoxCall:
  1. Authenticates your API key
  2. Checks `proxy:invoke` permission + your plan limit
  3. Validates the upstream URL (https only, DNS hostname, SSRF-safe)
  4. Scans body + query for {{ token: ... }} references
  5. Looks up each token in your vaults, gates per-vault detokenize
  6. Renders the body with raw values substituted in
  7. Sends the rewritten request to the upstream
  8. Streams the response back to you, audit-logged

Stripe sees:    { "amount": 5000, "currency": "usd",
                  "source": "tok_visa_real_card_token" }

You see:        Stripe's response, passed through unchanged.
```

The token strings, raw values, and bodies are **never** logged. Only metadata (upstream host, status code, latency, token count) lands in the audit chain and the Fleet Graph.

## Quick example

```bash theme={"dark"}
curl -X POST https://api.knoxcall.com/v1/proxy \
  -H "Authorization: Bearer tk_live_abc123..." \
  -H "X-Knox-Proxy-URL: https://api.stripe.com/v1/charges" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "currency": "usd",
    "source": "{{ token: tok_01HZX... }}"
  }'
```

The `tok_01HZX...` came from a prior `POST /v1/vaults/.../tokenize` call — see the [Vaults overview](/essentials/secrets/secrets-overview).

## Template syntax

Two reference forms are supported in the JSON body and query string:

| Form                              | What it does                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `{{ token: tok_xxx }}`            | Looks up the token in your tenant's vaults and substitutes the raw value.                                     |
| `{{ encrypted \| json: $.path }}` | Reads a value from the optional `X-Knox-Encrypted` header payload (base64-encoded JSON in v1) using JSONPath. |

Templates are scanned in body and query only. Headers pass through unchanged in v1 — header-injection is a separate hardening pass.

If a token isn't found, KnoxCall returns `400 token_not_found` rather than silently sending an empty value to the upstream.

## Required and optional headers

| Header                            | Required    | Purpose                                                                                                                                   |
| --------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `Authorization: Bearer <api-key>` | Yes         | Standard KnoxCall API auth.                                                                                                               |
| `X-Knox-Proxy-URL`                | Yes         | The upstream URL. Must be `https://`, must be a DNS hostname (no IP literals), must pass SSRF checks.                                     |
| `Content-Type`                    | Recommended | Defaults to `application/json` if omitted.                                                                                                |
| `X-Knox-Encrypted`                | No          | Base64-encoded JSON payload addressable via `{{ encrypted \| json: ... }}`. v1 is opaque base64-JSON; full JWE support is on the roadmap. |
| `X-Knox-Timeout-Ms`               | No          | Per-request upstream timeout (positive integer ≤ 30000).                                                                                  |

Reserved headers (`Authorization`, `Host`, `Content-Length`, anything starting with `X-Knox-`) are stripped before the request reaches the upstream. Every other header you send is forwarded unchanged.

## What you get back

KnoxCall passes the upstream response through verbatim — same status code, same headers (minus hop-by-hop), same body bytes. KnoxCall adds two headers so you can correlate:

| Response header             | Meaning                                                                                   |
| --------------------------- | ----------------------------------------------------------------------------------------- |
| `X-Knox-Request-Id`         | The KnoxCall request ID for audit-log lookup.                                             |
| `X-Knox-Destination-Status` | The upstream's status code (echoed; useful when proxies/CDNs mangle the surfaced status). |

If the upstream is unreachable, KnoxCall returns `502 upstream_error`.

## Limits and gates

| Gate                   | Behaviour                                                                                                                    |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Plan**               | Requires the **Starter** plan or above. `402 plan_limit` if disabled.                                                        |
| **Permission**         | `proxy:invoke` on resource type `ephemeral_proxy`. Per-vault `vault:detokenize` is also evaluated for each referenced token. |
| **Tokens per request** | Maximum **20** `{{ token: ... }}` references per request. `400 validation_error` past the cap.                               |
| **Upstream URL**       | HTTPS only, DNS hostname only (no IP literals), private/loopback ranges blocked, dangerous metadata endpoints blocked.       |
| **Timeout**            | Default 25s, max 30s.                                                                                                        |

## Audit and observability

Every invocation writes:

* An `api_requests` row with `proxy_mode = 'ephemeral'`, status code, latency, upstream host, token count, and source IP. **The body, headers, and token values are not stored.**
* An `audit_log` entry tagged `ephemeral_proxy.invoke`.
* A Fleet Graph signal carrying `(method, upstream_host, status_code, latency_ms)` — never the body, never the token strings, never the customer's path.

You can query the audit chain via `GET /v1/audit-logs?action=ephemeral_proxy.invoke` ([Audit Logs](/api-reference/audit-logs/list)).

## Comparison: Routes vs Ephemeral Proxy

|                                      | Routes                                              | Ephemeral Proxy                                                        |
| ------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------- |
| Lifecycle                            | Persistent row, configured once, called many times. | One-shot — no row, no config.                                          |
| Upstream URL                         | Set per route, can be overridden per environment.   | Set per request via `X-Knox-Proxy-URL`.                                |
| Discovery in dashboard               | Listed under **Routes**, full per-route metrics.    | Not listed — discoverable via audit logs and Fleet Graph.              |
| Best for                             | Repeat traffic to a known partner API.              | Tokenization passthrough, dynamic destinations, lightweight use cases. |
| Headers, signing, IP allowlist, mTLS | All configurable.                                   | Headers passthrough only; SSRF + plan gating only.                     |
| Token resolution                     | Configured per-route via injection rules.           | Inline `{{ token: ... }}` syntax in request body / query.              |

## Next steps

* See the [Ephemeral Proxy API reference](/api-reference/ephemeral-proxy/invoke) for the complete request/response schema.
* See [Vaults](/essentials/secrets/secrets-overview) to create the tokens you'll reference.
* See [Routes](/essentials/routes/what-are-routes) when you need a persistent, observable proxy instead.
