Routing Rules API - Programmatic AI Routing Control
Overview
Section titled “Overview”The Routing Rules API allows you to programmatically create and manage custom routing rules that control how TokenRouter selects AI providers and models for your requests.
Supported Providers
Section titled “Supported Providers”TokenRouter currently supports the following providers for routing rules:
openai- OpenAI (GPT-4o, GPT-4, GPT-3.5)anthropic- Anthropic (Claude 3.7, Claude 3.5, Claude 3)gemini- Google Geminimistral- Mistral AIdeepseek- DeepSeek
Supported Modes
Section titled “Supported Modes”balance- Balanced routing (default)cost- Cost-optimized routingquality- Quality-optimized routinglatency- Latency-optimized routing
List Routing Rules
Section titled “List Routing Rules”GET https://api.tokenrouter.io/v1/routing-rulesReturns all routing rules for the authenticated user, ordered by priority (highest first).
const response = await fetch('https://api.tokenrouter.io/v1/routing-rules', { headers: { 'Authorization': 'Bearer tr_...', }});
const { data } = await response.json();console.log(`Found ${data.length} routing rules`);import requests
response = requests.get( 'https://api.tokenrouter.io/v1/routing-rules', headers={'Authorization': 'Bearer tr_...'})
data = response.json()['data']print(f"Found {len(data)} routing rules")curl https://api.tokenrouter.io/v1/routing-rules \ -H "Authorization: Bearer tr_..."Response
Section titled “Response”{ "data": [ { "id": 1, "user_id": 123, "name": "Force Anthropic for Code", "is_enabled": true, "priority": 100, "match_json": { "contains": ["code", "function", "programming"] }, "action_json": { "set_provider": "anthropic", "set_model": "claude-3-7-sonnet-latest" }, "created_at": "2025-09-13T19:14:17.000000Z", "updated_at": "2025-09-13T19:14:17.000000Z" } ]}Create Routing Rule
Section titled “Create Routing Rule”POST https://api.tokenrouter.io/v1/routing-rulesCreates a new routing rule.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable name (max 128 chars) |
is_enabled | boolean | Yes | Whether the rule is active |
priority | integer | Yes | Priority (-1000 to 1000, higher = first) |
match_json | object | Yes | Conditions for matching |
action_json | object | Yes | Actions to take when matched |
Match Conditions
Section titled “Match Conditions”All conditions are combined with AND logic - every specified condition must match for the rule to trigger.
| Condition | Type | Description | Example |
|---|---|---|---|
contains | string or array | Search for text in user input (case-insensitive substring match) | "code" or ["code", "function"] |
metadata_equals | object | Match metadata key-value pairs (exact match) | {"user_tier": "premium"} |
mode | string | Match routing mode (case-insensitive) | "balance", "cost", "quality", "latency" |
task | string | Shorthand for metadata_equals.task (case-sensitive) | "summarize" |
Notes:
containssearches anywhere in the input text (if array, matches if ANY value found)- Input is normalized: objects/arrays are JSON-encoded before matching
- Empty strings in
containsarray are ignored
Actions
Section titled “Actions”Once set, actions cannot be overridden by lower-priority rules.
| Action | Type | Description | Notes |
|---|---|---|---|
set_provider | string | Force specific provider | Lowercase: openai, anthropic, gemini, mistral, deepseek |
set_model | string | Force specific model | Full model name: claude-3-7-sonnet-latest, gpt-4o |
set_mode | string | Override routing mode | Lowercase: balance, cost, quality, latency |
add_warning | string or object | Add custom warning | String or {"message": "text"} |
Action Precedence:
- First matching rule that sets
set_providerwins - subsequent rules cannot change it - Same applies for
set_modelandset_mode add_warningcan be set by multiple rules (accumulates)- Skipped actions are logged in rule trace with reason
Examples
Section titled “Examples”Route Code Questions to Anthropic
Section titled “Route Code Questions to Anthropic”const response = await fetch('https://api.tokenrouter.io/v1/routing-rules', { method: 'POST', headers: { 'Authorization': 'Bearer tr_...', 'Content-Type': 'application/json', }, body: JSON.stringify({ name: "Force Anthropic for Code", is_enabled: true, priority: 100, match_json: { contains: ["code", "function", "programming"] }, action_json: { set_provider: "anthropic", set_model: "claude-3-7-sonnet-latest" } })});
const { data } = await response.json();console.log(`Created rule: ${data.name}`);import requests
response = requests.post( 'https://api.tokenrouter.io/v1/routing-rules', headers={'Authorization': 'Bearer tr_...'}, json={ "name": "Force Anthropic for Code", "is_enabled": True, "priority": 100, "match_json": { "contains": ["code", "function", "programming"] }, "action_json": { "set_provider": "anthropic", "set_model": "claude-3-7-sonnet-latest" } })
data = response.json()['data']print(f"Created rule: {data['name']}")curl -X POST https://api.tokenrouter.io/v1/routing-rules \ -H "Authorization: Bearer tr_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Force Anthropic for Code", "is_enabled": true, "priority": 100, "match_json": { "contains": ["code", "function", "programming"] }, "action_json": { "set_provider": "anthropic", "set_model": "claude-3-7-sonnet-latest" } }'Cost Optimization for Summaries
Section titled “Cost Optimization for Summaries”{ "name": "Cost-optimize summaries", "is_enabled": true, "priority": 50, "match_json": { "metadata_equals": { "task": "summarize" } }, "action_json": { "set_mode": "cost" }}Multiple Conditions (AND logic)
Section titled “Multiple Conditions (AND logic)”{ "name": "Research in balanced mode", "is_enabled": true, "priority": 60, "match_json": { "contains": "research", "mode": "balanced" }, "action_json": { "set_mode": "quality", "set_provider": "anthropic" }}Get Routing Rule
Section titled “Get Routing Rule”GET https://api.tokenrouter.io/v1/routing-rules/{id}Returns a single routing rule by ID.
const response = await fetch('https://api.tokenrouter.io/v1/routing-rules/1', { headers: { 'Authorization': 'Bearer tr_...', }});
const { data } = await response.json();response = requests.get( 'https://api.tokenrouter.io/v1/routing-rules/1', headers={'Authorization': 'Bearer tr_...'})
data = response.json()['data']curl https://api.tokenrouter.io/v1/routing-rules/1 \ -H "Authorization: Bearer tr_..."Update Routing Rule
Section titled “Update Routing Rule”PATCH https://api.tokenrouter.io/v1/routing-rules/{id}Updates an existing routing rule. All fields are optional.
Examples
Section titled “Examples”Disable a Rule
Section titled “Disable a Rule”await fetch('https://api.tokenrouter.io/v1/routing-rules/1', { method: 'PATCH', headers: { 'Authorization': 'Bearer tr_...', 'Content-Type': 'application/json', }, body: JSON.stringify({ is_enabled: false })});requests.patch( 'https://api.tokenrouter.io/v1/routing-rules/1', headers={'Authorization': 'Bearer tr_...'}, json={"is_enabled": False})curl -X PATCH https://api.tokenrouter.io/v1/routing-rules/1 \ -H "Authorization: Bearer tr_..." \ -H "Content-Type: application/json" \ -d '{"is_enabled": false}'Update Priority
Section titled “Update Priority”{ "priority": 150}Update Actions
Section titled “Update Actions”{ "action_json": { "set_provider": "openai", "set_model": "gpt-4o" }}Delete Routing Rule
Section titled “Delete Routing Rule”DELETE https://api.tokenrouter.io/v1/routing-rules/{id}Permanently deletes a routing rule.
await fetch('https://api.tokenrouter.io/v1/routing-rules/1', { method: 'DELETE', headers: { 'Authorization': 'Bearer tr_...', }});requests.delete( 'https://api.tokenrouter.io/v1/routing-rules/1', headers={'Authorization': 'Bearer tr_...'})curl -X DELETE https://api.tokenrouter.io/v1/routing-rules/1 \ -H "Authorization: Bearer tr_..."Response
Section titled “Response”{ "success": true}Real-World Examples
Section titled “Real-World Examples”Example 1: Route Legal Questions to GPT-4o
Section titled “Example 1: Route Legal Questions to GPT-4o”{ "name": "Legal content → GPT-4o", "is_enabled": true, "priority": 90, "match_json": { "contains": ["legal", "contract", "compliance", "regulation"] }, "action_json": { "set_provider": "openai", "set_model": "gpt-4o" }}When it matches:
- Input contains “legal”, “contract”, “compliance”, or “regulation”
What it does:
- Routes to OpenAI’s GPT-4o model
Example 2: Use DeepSeek for Cost-Sensitive Tasks
Section titled “Example 2: Use DeepSeek for Cost-Sensitive Tasks”{ "name": "Cost mode → DeepSeek", "is_enabled": true, "priority": 75, "match_json": { "mode": "cost" }, "action_json": { "set_provider": "deepseek" }}When it matches:
- Request uses
auto:costor mode is set tocost
What it does:
- Routes to DeepSeek (most cost-effective)
Example 3: Premium Users Get Quality Mode
Section titled “Example 3: Premium Users Get Quality Mode”{ "name": "Premium users → Quality", "is_enabled": true, "priority": 80, "match_json": { "metadata_equals": { "user_tier": "premium" } }, "action_json": { "set_mode": "quality", "add_warning": { "message": "Premium user - using quality routing" } }}When it matches:
- Request metadata includes
user_tier: "premium"
What it does:
- Switches to quality mode
- Adds a warning message to the response
Rule Evaluation Order
Section titled “Rule Evaluation Order”Rules are evaluated in the following order:
- Priority (descending) - Higher priority rules evaluated first
- ID (ascending) - Older rules evaluated first for same priority
- All rules are checked - Multiple rules can match the same request
- Action precedence - First rule to set an action wins for that action type
Error Responses
Section titled “Error Responses”400 Bad Request
Section titled “400 Bad Request”{ "error": { "message": "The name field is required." }}403 Forbidden
Section titled “403 Forbidden”{ "error": { "message": "Custom routing rules require a paid plan." }}404 Not Found
Section titled “404 Not Found”{ "error": { "message": "Routing rule not found" }}