Routes and Consumer Groups
Path-based routing and API key-based consumer groups give you fine-grained control over which upstream targets and policy chains apply to each request.
Use this page when
- You are setting up path-based routing to direct requests to different upstream providers.
- You need per-route policy chains to apply different enforcement rules per endpoint.
- You are configuring consumer groups to give different API key holders separate rate limits, chains, or upstreams.
Primary audience
- Primary: AI Agents, Technical Engineers
- Secondary: Technical Leaders
Routes
The routes: section maps incoming request paths to specific upstream providers and per-route policy chains. Without routes, all requests use the global chain and provider routing.
Basic path routing
pack:
name: config-routes-and-consumers-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-prod
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-embed
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
path: "/v1/chat/completions"
upstream: openai-prod
- name: embeddings
path: "/v1/embeddings"
upstream: openai-embed
Full route reference
pack:
name: config-routes-and-consumers-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-prod
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- prompt-injection
- pii-detector
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
prompt-injection: {}
pii-detector:
action: redact
routes:
- name: chat-route
path: "/v1/chat"
match: prefix
methods:
- POST
headers:
X-Team: engineering
priority: 10
strip_path: false
upstream: openai-prod
chain:
- prompt-injection
- pii-detector
Route fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | — | Unique route identifier for logging and diagnostics |
path | string | yes | — | URL path pattern to match |
match | string | no | prefix | prefix or exact match |
methods | string[] | no | all | HTTP methods this route applies to |
headers | map | no | — | Header conditions (all must match) |
priority | integer | no | 0 | Higher priority wins when multiple routes match |
strip_path | boolean | no | false | Remove the matched prefix from the forwarded path |
upstream | string | no | — | Provider target ID to route to |
chain | ChainEntry[] | no | — | Per-route policy chain (overrides global) |
Route resolution
When a request arrives:
- All matching routes are collected (path + method + headers)
- Sorted by
prioritydescending - First match wins
- If no routes match, the global chain and routing apply
Separate chains per endpoint
pack:
name: multi-endpoint
version: 1.0.0
enabled: true
providers:
targets:
- id: openai-chat
provider: openai
model: gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-embed
provider: openai
model: text-embedding-3-small
secret_key_ref:
env: OPENAI_API_KEY
routes:
- name: chat-secured
path: "/v1/chat/completions"
upstream: openai-chat
chain:
- prompt-injection
- pii-detector
- quality-scorer
- name: embeddings-fast
path: "/v1/embeddings"
upstream: openai-embed
chain:
- audit-logger
policies:
chain:
- audit-logger
- prompt-injection
- pii-detector
- quality-scorer
policy:
prompt-injection: {}
pii-detector:
action: redact
quality-scorer:
thresholds:
min_aggregate: 0.8
Method-based routing
pack:
name: config-routes-and-consumers-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-prod
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- prompt-injection
- pii-detector
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
prompt-injection: {}
pii-detector:
action: redact
routes:
- name: completions-post
path: "/v1/chat/completions"
methods:
- POST
upstream: openai-prod
chain:
- prompt-injection
- pii-detector
- name: models-get
path: "/v1/models"
methods:
- GET
chain: []
Header-based routing
pack:
name: config-routes-and-consumers-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: openai-fast
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-safe
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
- id: openai-prod
provider: openai
model: gpt-4o-mini
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
- prompt-injection
- pii-detector
- dlp-filter
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true
prompt-injection: {}
pii-detector:
action: redact
dlp-filter:
action: block
routes:
- name: engineering-route
path: "/v1/chat/completions"
headers:
X-Team: engineering
upstream: openai-fast
priority: 10
- name: compliance-route
path: "/v1/chat/completions"
headers:
X-Team: compliance
upstream: openai-safe
chain:
- prompt-injection
- pii-detector
- dlp-filter
priority: 10
- name: default-route
path: "/v1/chat/completions"
upstream: openai-prod
priority: 0
Strip path for backend proxying
pack:
name: config-routes-and-consumers-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: custom-backend
provider: openai
model: gpt-4o-mini
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: custom-api
path: "/api/v2"
match: prefix
strip_path: true
upstream: custom-backend
Consumer groups
The consumer_groups: section identifies API consumers by their key and applies per-group rate limits, policy chains, and upstream overrides.
Basic consumer group
consumer_groups:
key_header: "Authorization"
groups:
- name: "enterprise"
api_keys:
- "sha256:a1b2c3d4e5f6..." # SHA-256 hash of the API key
rate_limit:
max_requests: 1000
window_seconds: 60
Full consumer group reference
consumer_groups:
key_header: "Authorization" # header to extract the API key from (default)
groups:
- name: "enterprise"
api_keys: # SHA-256 hashes of permitted keys
- "sha256:a1b2c3..."
- "sha256:d4e5f6..."
rate_limit:
max_requests: 1000
max_tokens: 500000
window_seconds: 60
chain: # per-group chain override (replaces global)
- "audit-logger"
upstream: "openai-enterprise" # per-group upstream override
- name: "free-tier"
api_keys:
- "sha256:789abc..."
rate_limit:
max_requests: 10
window_seconds: 60
Consumer group fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
key_header | string | no | "Authorization" | Request header containing the API key |
groups[].name | string | yes | — | Group name for logging and diagnostics |
groups[].api_keys | string[] | yes | — | SHA-256 hex hashes of valid API keys |
groups[].rate_limit.max_requests | integer | no | — | Max requests per window |
groups[].rate_limit.max_tokens | integer | no | — | Max tokens per window |
groups[].rate_limit.window_seconds | integer | yes (if rate_limit) | — | Rate limit window |
groups[].chain | ChainEntry[] | no | — | Override the policy chain for this group |
groups[].upstream | string | no | — | Override the upstream provider for this group |
How key matching works
- The gateway extracts the value from
key_header - Strips the
Bearerprefix if present - Computes the SHA-256 hash
- Looks up the hash in the consumer group index
- If matched, applies the group's rate limit, chain, and upstream
- If no match, falls back to global settings
Generating key hashes
echo -n "my-secret-api-key" | shasum -a 256 | cut -d' ' -f1
# → a1b2c3d4e5f67890...
Tiered access example
pack:
name: "tiered-access"
version: "1.0.0"
enabled: true
providers:
targets:
- id: "openai-4o"
provider: "openai"
model: "gpt-4o"
secret_key_ref:
env: "OPENAI_API_KEY"
- id: "openai-mini"
provider: "openai"
model: "gpt-4o-mini"
secret_key_ref:
env: "OPENAI_API_KEY"
consumer_groups:
key_header: "Authorization"
groups:
- name: "enterprise"
api_keys:
- "sha256:enterprise_key_hash_here"
rate_limit:
max_requests: 5000
max_tokens: 2000000
window_seconds: 3600
upstream: "openai-4o"
chain:
- "audit-logger"
- name: "professional"
api_keys:
- "sha256:pro_key_hash_1"
- "sha256:pro_key_hash_2"
rate_limit:
max_requests: 500
max_tokens: 200000
window_seconds: 3600
upstream: "openai-4o"
- name: "free-tier"
api_keys:
- "sha256:free_key_hash"
rate_limit:
max_requests: 20
max_tokens: 10000
window_seconds: 3600
upstream: "openai-mini"
chain:
- "prompt-injection"
- "pii-detector"
- "quality-scorer"
policies:
chain:
- "prompt-injection"
- "pii-detector"
- "audit-logger"
Combining routes and consumer groups
Routes and consumer groups compose naturally. Consumer group resolution happens first, then route matching. The per-group chain override takes precedence when set.
pack:
name: "combined-routing"
version: "1.0.0"
enabled: true
providers:
targets:
- id: "openai-standard"
provider: "openai"
model: "gpt-4o"
secret_key_ref:
env: "OPENAI_API_KEY"
- id: "openai-embed"
provider: "openai"
model: "text-embedding-3-small"
secret_key_ref:
env: "OPENAI_API_KEY"
routes:
- name: "embeddings"
path: "/v1/embeddings"
upstream: "openai-embed"
chain:
- "audit-logger"
consumer_groups:
groups:
- name: "internal"
api_keys: ["sha256:internal_hash"]
rate_limit:
max_requests: 10000
window_seconds: 3600
policies:
chain:
- "prompt-injection"
- "pii-detector"
- "quality-scorer"
- "audit-logger"
For AI systems
- Canonical terms: Keeptrusts, routes, consumer_groups, path, upstream, chain, priority, match, strip_path, api_keys, key_header
- Config/command names:
routes[],routes[].path,routes[].upstream,routes[].chain,routes[].priority,consumer_groups,consumer_groups.groups[],consumer_groups.key_header - Best next pages: Providers Configuration, Config Rate Limits, Declarative Config Reference
For engineers
- Prerequisites: Multiple provider targets defined in
providers.targets[]. For consumer groups, SHA-256 hashes of your API keys (echo -n 'key' | shasum -a 256). - Validation: Run
kt policy lintto validate route and consumer group configuration. Test routing withcurl -H 'X-Team: engineering' http://localhost:8080/v1/chat/completionsand verify the correct upstream is selected in gateway logs. - Key commands:
kt policy lint,kt gateway run,echo -n 'key' | shasum -a 256
For leaders
- Governance: Routes and consumer groups segment your AI traffic by team, product, or tier. This enables per-team audit trails, differentiated compliance enforcement, and team-specific cost attribution.
- Cost: Consumer group rate limits prevent any single API key holder from over-consuming shared capacity. Per-group upstream overrides can route cost-sensitive traffic to cheaper models.
- Rollout: Start with a single default route. Add per-endpoint routes as you onboard teams with different compliance requirements. Introduce consumer groups when you issue separate API keys per team.
Next steps
- Providers Configuration — Define upstream targets
- Config Rate Limits — Global and per-scope rate limiting
- Policy Controls Catalog — Available chain policies
- Security and Network Configuration — IP allowlisting per consumer