Skip to main content

Route Configuration Guide

Learn how to configure routes with custom headers, method filtering, and environment-specific settings.

HTTP Methods

Control which HTTP methods are allowed:

Allow All Methods

By default, all methods (GET, POST, PUT, PATCH, DELETE) are allowed.

Restrict Methods

  1. Edit your route
  2. Under Allowed Methods, uncheck methods you want to block
  3. Example: Only allow GET and POST
Use case: Prevent clients from deleting data (block DELETE)

Header Injection

Add custom headers to requests sent to your backend:

Example: Add API Key

Example: Add Authentication

Use {{secret:secret_name}} to inject secrets

Body Injection

Add data to the request body:

Example: Add Tenant ID

Note: Only works with POST, PUT, PATCH requests

Raw card numbers are refused on egress

A request whose body carries a payment card number in the clear is refused with 403 raw_pan_egress_refused and is not forwarded — unless the route’s destination host has been allowed for raw card data, either on this route or for the whole workspace.
The check runs after header injection, body injection and any Relay field actions, on the exact bytes that would go on the wire — so a card number that arrives in the request, one that a {{secret:…}} placeholder injects, and one a field action produces are all seen. It covers every transport a route can use: direct, mTLS, VPN and static-egress. One value is exempt, and only one: a card that a Relay detokenize action just resolved from a pan vault. That vault’s own allowed_destinations was already checked against this route’s host before anything was decrypted, so the card path a route is built for keeps working. If you see this refusal, you have three ways forward, narrowest first.
  1. Tokenize the number into a pan vault and let a Relay detokenize action put it back on the way out. This is the intended path and the only one where the clear number never exists outside the hop that needs it.
  2. Allow it on this route alone. Open the route, go to Security, and turn off Enable security defaults to reveal the individual protections. Then turn off Refuse raw card numbers — the switches in that card all read the same way round, on meaning protected, so allowing a card number is switching a protection off. The grant covers this route in this environment and nothing else — not your other routes, not workflow steps, not webhooks, not /v1/proxy. Switching the protection off allows the route’s current destination, labelled as such; Add another destination beneath it takes further hostnames or *.suffix wildcards for the exceptions (a per-method target, a processor with a host family). An owner or admin, a fresh second factor to add a host (never to remove one), audited as egress.route_pan_allowed_hosts_updated.
  3. Allow it for the whole workspace with PUT /admin/pan-egress/allowed-hosts (see the ephemeral proxy’s section on this refusal for the request shape). This opens the destination on every egress path at once, so prefer option 2 when only one route needs it. Audited as egress.pan_allowed_hosts_updated.
Both allowlists are empty by default, and they are a union — a route grant can only add a destination, never take one away that the workspace already allows.
The route grant records the hostname, not a simple on/off. If you later point the route at a different target, the grant no longer covers it and card numbers are refused again — deliberately, so that consent you gave for one destination cannot follow the route somewhere you never approved. The security defaults card says so when it happens — and says it whether or not the individual protections are showing — and the grant is not settable through the /v1 API: an API key that can proxy must not be able to authorise itself a destination for raw card numbers.
Self-hosted data planes: the route grant does not apply in production yet. A self-hosted node serves production traffic from the bundle the control plane syncs to it, and that bundle does not carry the per-route grant. Non-production environments on the same node read the database directly and DO honour it, so the grant will appear to work in your test environment and then stop at production — which is the opposite of what you would expect, and the reason this warning exists.It always fails closed: a route whose grant is not seen refuses the card number, it never forwards one you did not allow. Until the bundle carries the column, use the workspace-wide allowlist for production on self-hosted. Cloud deployments are unaffected.
Each refusal writes an egress.raw_pan_refused audit entry with the destination host and a masked sample; the number is never logged or stored. Detection is 13–19 digits (spaces and hyphens allowed) that pass the Luhn checksum and carry a recognised issuer prefix, so an ordinary 16-digit order number is not affected.

Moving a route that decrypts or detokenizes

If a route carries a standing decrypt or detokenize field action (POST /v1/routes/{routeId}/actions), changing where it sends is treated like revealing the values it opens.
A decrypt action opens kc: ciphertext and a detokenize action turns a vault token back into the card number or SSN behind it, on every call through the route. On the request side the opened value is sent to the route’s upstream; on the response side the upstream’s own values are opened and returned to the caller. Either way, whoever chooses the upstream chooses who reads opened values, so giving such a route a new destination needs the same authority as attaching the action:
  • In the dashboard: an Owner or Admin, a fresh second factor (a security key, passkey or authenticator code — never an emailed code), and an optional reason, recorded in the audit log as a plaintext.reveal entry (surface: route.destination_change) before the change is saved. An Editor sees why on the route page and is refused, whether or not they have Reveal secrets. You are asked when you Save, never while you edit, and once per Save however much it changes: the page sends the Target URL, the configuration, the allowed methods and the Serve traffic switch together. Cancelling the verification saves nothing. Pushing a Target URL to every environment asks once for all of them, and a double-click on any of the page’s commands sends the change once and asks once.
  • On the API (/v1): a token issued to a person (knoxcall login, a device or authorization-code grant) is refused; a machine credential must hold the action’s own permission — transit:decrypt on its key, or vaults:detokenize on its vault. The change is recorded as route.destination_change before it is written.
  • The onboarding assistant cannot do it; it points you at the route page.
“A new destination” means a URL the route does not already store: a new base URL, a new per-method target URL (active or not), or a new environment carrying a URL the route has never had — including one a collection’s defaults would provision. It also means starting to send to a URL the route only stores: turning on a disabled environment, turning on method-specific configs (so their target URLs go live), allowing a method that reaches a base URL every allowed method used to bypass, copying a URL that sits idle into a base URL, or duplicating an environment whose URL sits idle into one that serves traffic. A URL counts as one the route already sends to only when a GET, POST, PUT, PATCH or DELETE request reaches it today; a URL that only another method reaches (a route restricted to HEAD, or to a method name no client sends) is treated as idle. Because two saves made at the same moment could each look harmless, a change is judged as if the environment’s switches (enabled, the method restriction, method-specific configs) were all open: on an environment that holds an idle URL, a save that would send to it once those switches open — or placing an idle URL into a paused environment — asks for the verification too. Re-saving a URL the route already uses, removing one, turning an environment off, duplicating an environment the route already sends to, and renaming an environment need nothing extra. Routes with no such action — and routes whose actions only encrypt or tokenize — are unaffected.

Path Handling

The request path is appended verbatim to the route’s target base URL. KnoxCall does not rewrite, strip, or remove any path prefix. For example, if your target base URL is https://api.example.com and a client requests /api/v1/users/123, the request is forwarded to:
If the target base URL already includes a path (for example https://api.example.com/backend), the client path is appended to it (https://api.example.com/backend/api/v1/users/123). Query parameters from the incoming request are preserved.
A target URL must point at a third-party upstream. Private, loopback and cloud-metadata addresses are refused, and so is any KnoxCall host (api.knoxcall.com, hooks.knoxcall.com, another workspace’s *.knoxcall.com address, or your own) — KnoxCall never sends your route’s traffic back to itself. To call one of your routes from a workflow, use the HTTP Request node’s Route mode instead of typing the route’s URL.

Environment Configuration

Set different target URLs per environment:
  1. Edit route
  2. Scroll to Environment Configuration
  3. For each environment:
    • Development: http://localhost:3000
    • Staging: https://staging-api.example.com
    • Production: https://api.example.com
Clients specify environment via header:

Rate Limiting

Limit requests per client:
  1. Enable Rate Limiting
  2. Set limits:
    • Requests: 100
    • Window: 60 (seconds)
    • Burst: 120
This allows 100 requests per minute, with bursts up to 120.

Timeout Settings

Default timeout is 30 seconds. Contact support to adjust.

Testing Configuration

After making changes:
  1. Click Test Route
  2. Select environment
  3. Enter sample request
  4. View response

Need More Help?

  • See the Quick Start Guide for basics
  • Learn about secrets for secure credential injection
  • Check troubleshooting guides for common issues

📊 Statistics

  • Level: intermediate
  • Time: 10 minutes

🏷️ Tags

routes, configuration, intermediate