Skip to content

Python SDK

Terminal window
pip install tokenrouter
from tokenrouter import Tokenrouter
client = Tokenrouter(
api_key="tr_..."
)
response = client.responses.create(
model="auto:balance",
input="Hello, world!"
)
client = Tokenrouter(
api_key="tr_...",
environment="production", # or "local"
timeout=60.0, # seconds
)
response = client.responses.create(
model="auto:balance",
input="What is Python?"
)
response = client.responses.create(
model="gpt-4o:quality",
input="Explain decorators",
temperature=0.7,
max_output_tokens=1000
)
stream = client.responses.create(
model="auto:balance",
input="Write a story",
stream=True
)
for chunk in stream:
if chunk.event == 'content.delta':
print(chunk.delta.text, end='', flush=True)
from tokenrouter import AsyncTokenrouter
async_client = AsyncTokenrouter(api_key="tr_...")
response = await async_client.responses.create(
model="auto:balance",
input="Hello!"
)

Manage custom routing logic to control how requests are routed.

rule = client.routing_rules.create(
name="Coding Tasks → OpenAI",
priority=100,
is_enabled=True,
match_json={"task": "coding"},
action_json={
"set_provider": "openai",
"set_model": "gpt-4o"
}
)
print(f"Created rule: {rule.data.id}")
rules = client.routing_rules.list()
for rule in rules.data:
print(f"{rule.name} (Priority: {rule.priority})")
rule = client.routing_rules.retrieve(123)
print(rule.data)
client.routing_rules.update(
123,
priority=150,
is_enabled=False
)
client.routing_rules.delete(123)
# Input contains text (case-insensitive)
match_json={"contains": "code review"}
# Match metadata
match_json={"metadata_equals": {"task": "documentation"}}
# Match routing mode
match_json={"mode": "balanced"}
# Multiple conditions (all must match)
match_json={
"task": "coding",
"mode": "quality"
}
# Force specific provider
action_json={"set_provider": "anthropic"}
# Force specific model
action_json={"set_model": "gpt-4o"}
# Override routing mode
action_json={"set_mode": "cost"}
# Add warning
action_json={
"add_warning": {"message": "Using beta routing"}
}
# Combine actions
action_json={
"set_provider": "openai",
"set_model": "gpt-4o",
"set_mode": "quality"
}

Protect your application by filtering sensitive content in requests and responses.

# Block credit card numbers
rule = client.firewall_rules.create(
name="Block Credit Cards",
priority=100,
is_enabled=True,
scope="prompt",
type="regex",
pattern=r"\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}",
action="block"
)
# Mask email addresses in responses
rule = client.firewall_rules.create(
name="Mask Email Addresses",
priority=80,
is_enabled=True,
scope="response",
type="regex",
pattern=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
action="mask",
replacement="[EMAIL_REDACTED]"
)
# Warn when profanity detected
rule = client.firewall_rules.create(
name="Warn on Profanity",
priority=50,
is_enabled=True,
scope="response",
type="substring",
pattern="inappropriate",
action="warn"
)
rules = client.firewall_rules.list()
for rule in rules.data:
print(f"{rule.name} ({rule.action})")
print(f" Scope: {rule.scope}")
print(f" Pattern: {rule.pattern}")
rule = client.firewall_rules.retrieve(123)
print(rule.data)
# Disable temporarily
client.firewall_rules.update(123, is_enabled=False)
# Change action
client.firewall_rules.update(123, action="warn")
client.firewall_rules.delete(123)
  • prompt - Apply to user input before sending to LLM
  • response - Apply to LLM output before returning to user
  • substring - Case-insensitive text matching
  • regex - Regular expression matching (PCRE-compatible)
  • block - Reject request/response with 422 error
  • mask - Replace matched content with replacement text
  • warn - Allow but add warning to metadata
# Social Security Numbers
pattern = r"\d{3}-\d{2}-\d{4}"
# Phone Numbers
pattern = r"\+?1?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}"
# Email Addresses
pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
# API Keys (OpenAI format)
pattern = r"sk-[a-zA-Z0-9]{32,}"
# Credit Cards (any format)
pattern = r"\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}"
from tokenrouter import APIError
try:
response = client.responses.create(...)
except APIError as error:
print(f"API Error: {error}")
print(f"Status: {error.status}")
print(f"Type: {error.type}")
try:
response = client.responses.create(
model="auto:balance",
input="My credit card is 4532-1234-5678-9010"
)
except APIError as error:
if error.status == 422:
print("Request blocked by firewall")
print(f"Reason: {error.message}")
# Create multiple rules for different scenarios
client.routing_rules.create(
name="Complex Analysis → GPT-4",
priority=100,
is_enabled=True,
match_json={
"contains": ["analyze", "complex"],
"mode": "quality"
},
action_json={
"set_provider": "openai",
"set_model": "gpt-4o"
}
)
client.routing_rules.create(
name="Simple Tasks → Cost Mode",
priority=50,
is_enabled=True,
match_json={"contains": ["summarize", "list"]},
action_json={"set_mode": "cost"}
)
# Layer 1: Block PII in prompts
client.firewall_rules.create(
name="Block PII in Input",
priority=100,
is_enabled=True,
scope="prompt",
type="regex",
pattern=r"\d{3}-\d{2}-\d{4}|\d{16}",
action="block"
)
# Layer 2: Mask emails in responses
client.firewall_rules.create(
name="Mask Emails in Output",
priority=90,
is_enabled=True,
scope="response",
type="regex",
pattern=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
action="mask",
replacement="[REDACTED]"
)
# Layer 3: Warn on sensitive keywords
client.firewall_rules.create(
name="Warn on Sensitive Terms",
priority=80,
is_enabled=True,
scope="response",
type="substring",
pattern="confidential",
action="warn"
)

All SDK classes are fully typed with type hints:

from tokenrouter import (
Tokenrouter,
AsyncTokenrouter,
RoutingRule,
FirewallRule
)
from tokenrouter.types import (
ResponseCreateParams,
RoutingRuleCreateParams,
FirewallRuleCreateParams
)