Skip to main content
Browse docs
By Audience
Getting Started
Configuration
Use Cases
IDE Integration
Third-Party Integrations
Engineering Cache
Console
API Reference
Gateway
Workflow Guides
Templates
Providers and SDKs
Industry Guides
Advanced Guides
Browse by Role
Deployment Guides
In-Depth Guides
Tutorials
FAQ

Custom Routes

Custom routes let you create URL-path-based routing rules that assign different policy chains or provider upstreams to different API paths within the same gateway instance. Rather than running a separate gateway per product area, you declare a single routes: block and let Keeptrusts dispatch each request to the correct backend with the correct policy enforcement.

Use this page when

  • You need the exact command, config, API, or integration details for Custom Routes.
  • You are wiring automation or AI retrieval and need canonical names, examples, and constraints.
  • If you want a guided rollout instead of a reference page, use the linked workflow pages in Next steps.

Typical use cases:

  • Multi-product gateways/v1/chat/ routes to GPT-4o while /v1/code/ routes to a code-specialist provider.
  • Admin vs. user traffic/v1/admin/ paths apply an elevated audit policy chain; /v1/user/ paths apply standard content safety.
  • Tenant-aware routing — an X-Tenant: healthcare header routes requests to a HIPAA-compliant provider; all other tenants go to the default provider.
  • Method-level controlGET requests to /v1/models are pass-through; POST requests to /v1/chat/completions go through the full policy chain.

Primary audience

  • Primary: AI Agents, Technical Engineers
  • Secondary: Technical Leaders

Route Configuration

Routes are declared under the top-level routes key. Each entry is a RouteRule object.

pack:
name: routes-routes-1
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o-mini
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- admin-audit-logger
- admin-scope-check
- content-safety
- pii-redaction
- basic-safety-filter
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
admin-audit-logger:
action: block
admin-scope-check:
action: block
content-safety:
action: block
pii-redaction:
action: redact
basic-safety-filter:
action: block
routes:
- name: admin-api
path: "/v1/admin"
match: prefix
methods:
- POST
- PUT
- DELETE
priority: 10
chain:
- admin-audit-logger
- admin-scope-check
upstream: openai-gpt4o
- name: chat-completions
path: "/v1/chat/completions"
match: exact
methods:
- POST
priority: 50
chain:
- content-safety
- pii-redaction
upstream: openai-gpt4o
- name: default
path: "/"
match: prefix
priority: 999
chain:
- basic-safety-filter
upstream: openai-gpt4o-mini

RouteRule field reference

FieldTypeRequiredDescription
namestringyesUnique name for this route. Used in logs and the console.
pathstringyesURL path to match. Format depends on the match field.
matchstringnoMatching strategy: prefix (default), exact, or regex.
methodslist of stringsnoHTTP methods this rule applies to. Omit to match all methods.
headersmapnoMap of header-name: value that must all be present for the rule to match.
priorityintegernoLower values are evaluated first. Default 100. Catch-all routes should use 999.
strip_pathboolnoWhen true, removes the matched path prefix before forwarding to the upstream. Default false.
upstreamstringnoProvider target ID to route matching requests to. Overrides the global default_upstream.
chainlist of stringsnoOrdered list of policy IDs to apply to matching requests. Overrides the global default_chain.
add_request_headersmapnoHeaders to inject into the upstream request. Values support ${ENV_VAR} substitution.
add_response_headersmapnoHeaders to inject into the response returned to the client.

Path Matching

Keeptrusts supports three path matching strategies controlled by the match field.

prefix — path prefix matching

The rule matches any request whose path starts with the configured path value.

pack:
name: routes-routes-2
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-embed-small
provider: openai
model: text-embedding-3-small
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
routes:
- name: chat-all
path: "/v1/chat"
match: prefix
upstream: openai-gpt4o
- name: embeddings-all
path: "/v1/embeddings"
match: prefix
upstream: openai-embed-small

exact — exact path matching

The rule matches only when the request path is an identical string match.

pack:
name: routes-routes-3
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
routes:
- name: chat-completions-only
path: "/v1/chat/completions"
match: exact
upstream: openai-gpt4o

regex — regular expression matching

The rule matches when the request path satisfies the regular expression in the path field. Capture groups are not used for path rewriting.

pack:
name: routes-routes-4
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
routes:
- name: versioned-chat
path: "^/v[0-9]+/chat/completions$"
match: regex
upstream: openai-gpt4o
- name: model-info-endpoints
path: "^/v1/(models|model-info|capabilities)(/.*)?$"
match: regex
chain: []
upstream: openai-gpt4o
Prefer prefix or exact for common paths — they are evaluated with simple string operations and have lower overhead than regex. Reserve regex for routes that genuinely need pattern matching.

Header-Based Routing

Routes can require specific request header values to match. Use this to route traffic by tenant, product line, environment, or any other header your clients send.

pack:
name: routes-routes-5
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: azure-gpt4o-hipaa
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- hipaa-phi-filter
- consent-check
- healthcare-audit-logger
- mnpi-filter
- pii-redaction
- sec-audit-logger
- content-safety
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
hipaa-phi-filter:
action: block
consent-check:
action: block
healthcare-audit-logger:
action: block
mnpi-filter:
action: block
pii-redaction:
action: redact
sec-audit-logger:
action: block
content-safety:
action: block
routes:
- name: healthcare-tenant
path: "/v1/chat/completions"
match: exact
headers:
X-Tenant: healthcare
priority: 10
chain:
- hipaa-phi-filter
- consent-check
- healthcare-audit-logger
upstream: azure-gpt4o-hipaa
- name: finance-tenant
path: "/v1/chat/completions"
match: exact
headers:
X-Tenant: finance
priority: 10
chain:
- mnpi-filter
- pii-redaction
- sec-audit-logger
upstream: openai-gpt4o
- name: default-chat
path: "/v1/chat/completions"
match: exact
priority: 100
chain:
- content-safety
upstream: openai-gpt4o

Multiple required headers

When headers specifies multiple entries, all headers must match for the route to be selected.

pack:
name: routes-routes-6
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: anthropic-claude-sonnet
provider: anthropic
model: claude-sonnet-4-20250514
secret_key_ref:
env: ANTHROPIC_API_KEY
base_url: https://api.anthropic.com
provider_type: anthropic
format: anthropic
policies:
chain:
- audit-logger
- beta-telemetry-logger
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
beta-telemetry-logger:
action: block
routes:
- name: internal-beta-feature
path: "/v1/chat/completions"
match: exact
headers:
X-Environment: staging
X-Feature-Flag: new-model-beta
priority: 5
upstream: anthropic-claude-sonnet
chain:
- beta-telemetry-logger

This route only matches requests that carry both X-Environment: staging and X-Feature-Flag: new-model-beta.


Priority Resolution

Routes are evaluated in ascending priority order (lower number = higher priority). The first matching rule wins. Any route can define a priority; if two routes have the same priority and both match, the first one declared in the config file wins.

priority: 1 → evaluated first
priority: 10 → evaluated second
priority: 50 → evaluated third
priority: 999 → catch-all (evaluated last)

Example priority plan for a multi-product gateway:

PriorityRoute nameRationale
1health-checkPass-through /health before any policy overhead.
5admin-apiPrivileged admin paths with elevated audit chain.
10healthcare-tenantTenant-specific routes before generic ones.
10finance-tenantSame level as healthcare; both are header-scoped.
50chat-completionsMain product path.
75embeddingsSeparate upstream, lower priority than chat.
999defaultCatch-all for anything not matched above.

Per-Route Policy Chains

Each route can reference any set of policies declared in the policies block. The chain is an ordered list of policy IDs; policies execute in the listed order.

policies:
chain:
- admin-scope-check
- audit-logger
- content-safety
- pii-redaction
- rate-limit-headers
routes:
- name: admin-api
path: "/v1/admin"
match: prefix
priority: 5
chain:
- admin-scope-check
- audit-logger
upstream: openai-gpt4o
- name: user-chat
path: "/v1/chat/completions"
match: exact
priority: 50
chain:
- content-safety
- pii-redaction
- rate-limit-headers
upstream: openai-gpt4o
- name: default
path: "/"
match: prefix
priority: 999
chain:
- content-safety
upstream: openai-gpt4o-mini
policy:
admin-scope-check:
action: block
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
content-safety:
action: block
pii-redaction:
action: redact
rate-limit-headers:
action: block
providers:
targets:
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o-mini
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY

Stripping Path Prefixes

When strip_path: true is set, the matched path prefix is removed before the request is forwarded to the upstream. This is useful when your downstream clients use a custom path namespace that your upstream provider doesn't expect.

pack:
name: routes-routes-8
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- content-safety
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
content-safety:
action: block
routes:
- name: openai-gateway-namespace
path: "/kt/openai"
match: prefix
strip_path: true
upstream: openai-gpt4o
chain:
- content-safety

A client that sends POST /kt/openai/v1/chat/completions will have the /kt/openai prefix stripped, so the upstream receives POST /v1/chat/completions.


Injecting Headers

Use add_request_headers and add_response_headers to inject or override headers at the route level.

pack:
name: routes-routes-9
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-primary
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- content-safety
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
content-safety:
action: block
routes:
- name: internal-service-a
path: "/v1/chat/completions"
match: exact
headers:
X-Service: service-a
priority: 20
add_request_headers:
X-KT-Route-Source: service-a
X-Upstream-Tenant: "${TENANT_ID}"
add_response_headers:
X-KT-Policy-Chain: service-a-chain
Vary: X-Service
chain:
- content-safety
upstream: openai-gpt4o

Header values that include ${VAR_NAME} syntax are resolved from the process environment at gateway startup. They cannot be resolved dynamically per-request.


Full Example — Multi-Route Gateway Config

The following demonstrates a complete policy-config.yaml for a SaaS platform that serves multiple product areas from a single gateway.

gateway:
port: 41002
host: 0.0.0.0
providers:
default_upstream: openai-gpt4o
targets:
- id: openai-gpt4o
provider: openai:chat:gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-gpt4o-mini
provider: openai:chat:gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: anthropic-sonnet
provider: anthropic:chat:claude-3-5-sonnet-20241022
secret_key_ref:
env: ANTHROPIC_API_KEY
- id: azure-gpt4o-hipaa
provider: azure:chat:gpt-4o
base_url: https://hipaa-region.openai.azure.com/openai/deployments/gpt-4o
secret_key_ref:
env: AZURE_OPENAI_API_KEY
- id: openai-embed
provider: openai:embedding:text-embedding-3-small
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- admin-role-check
- audit-logger
- hipaa-phi-filter
- content-safety
routes:
- name: admin-ops
path: "/v1/admin"
match: prefix
methods:
- POST
- PUT
- PATCH
- DELETE
priority: 5
chain:
- admin-role-check
- audit-logger
upstream: openai-gpt4o
- name: healthcare-chat
path: "/v1/chat/completions"
match: exact
headers:
X-Tenant: healthcare
priority: 10
chain:
- hipaa-phi-filter
- audit-logger
upstream: azure-gpt4o-hipaa
- name: standard-chat
path: "/v1/chat/completions"
match: exact
methods:
- POST
priority: 50
chain:
- content-safety
upstream: openai-gpt4o
- name: embeddings
path: "/v1/embeddings"
match: exact
methods:
- POST
priority: 50
chain: []
upstream: openai-embed
- name: default
path: "/"
match: prefix
priority: 999
chain:
- content-safety
upstream: openai-gpt4o-mini
policy:
admin-role-check:
action: block
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
hipaa-phi-filter:
action: block
content-safety:
action: block

Best Practices

  1. Always define a catch-all default route at priority 999. Without a default, requests that don't match any specific route fall through to the global default_chain and default_upstream. An explicit default route makes the fallback behaviour visible in the config file.

  2. Use prefix matching for path namespaces; use exact for specific endpoints. Prefix routes are efficient and composable. Reserve regex for genuinely variable path patterns.

  3. Put header-based tenant routes at a lower priority number than generic path routes. Header-based routes are more specific, so they should win over generic path matches.

  4. Separate admin paths from user paths. Give admin paths a dedicated policy chain that includes role validation and unconditional audit logging. Never rely on the client to self-identify as an admin; check the X-Roles header against an allow-list policy.

  5. Use strip_path to decouple client path conventions from upstream expectations. This lets you namespace all Keeptrusts traffic under a custom prefix (e.g., /kt/) without requiring changes to upstream provider SDKs.

  6. Validate your route config with kt config lint before deploying. The linter catches overlapping exact routes at the same priority, invalid policy references, and upstream IDs that don't resolve to a declared target.

For AI systems

  • Canonical terms: Keeptrusts Custom Routes, RouteRule, path matching, header-based routing, route priority, strip_path.
  • Config keys: routes[].name, routes[].path, routes[].match (prefix | exact | regex), routes[].methods, routes[].headers, routes[].priority, routes[].strip_path, routes[].upstream, routes[].chain, routes[].add_request_headers, routes[].add_response_headers.
  • CLI validation: kt config lint catches overlapping exact routes at the same priority, invalid policy references, and unresolved upstream IDs.
  • Priority convention: 1 = health checks, 5 = admin, 10 = tenant-specific, 50 = main product, 999 = catch-all default.
  • Header injection: ${ENV_VAR} syntax resolved from process environment at gateway startup.
  • Best next pages: Consumer Groups, Rate Limiting, Provider Routing.

For engineers

  • Prerequisites: at least one provider target and policy declared for routes to reference.
  • Always define a catch-all default route at priority 999 to make fallback behaviour explicit.
  • Use prefix or exact matching for common paths; reserve regex for genuinely variable patterns (lower overhead).
  • Header-based routes must be at a lower priority number than generic path routes to win first.
  • Use strip_path: true to decouple client path namespaces from upstream OpenAI-compatible paths.
  • Validate: run kt config lint --file policy-config.yaml before deploying to catch unresolved references.
  • Test: send requests with specific X-Tenant headers and confirm the correct chain and upstream appear in Events.

For leaders

  • Multi-product on one gateway: custom routes eliminate the need to run separate gateway instances per product area, reducing infrastructure cost and operational complexity.
  • Tenant isolation: header-based routing enforces tenant-specific compliance policies (HIPAA, finance audit) without application code changes.
  • Security: admin paths get dedicated role-check policies and audit chains, separated from user-facing paths by priority.
  • Operational simplicity: all routing logic is declarative in one config file, auditable, and version-controllable.

Next steps