Firewall Rules API - AI Security and Content Filtering
Overview
Section titled “Overview”The Firewall Rules API allows you to programmatically create and manage firewall rules that filter, block, or transform content in requests and responses based on pattern matching.
Key Concepts
Section titled “Key Concepts”prompt- Apply rule to user input before sending to AI provider (currently implemented)response- Apply rule to AI output before returning to user (planned feature - currently not evaluated)
Pattern Types
Section titled “Pattern Types”substring- Case-insensitive substring search usingstripos()(simple and fast)regex- Regular expression matching with PCRE (more powerful, flexible)- Patterns without delimiters are auto-wrapped:
\d{3}becomes/\d{3}/i - Patterns with delimiters are used as-is:
/\d{3}/or/\d{3}/i - All patterns are case-insensitive by default
- Patterns without delimiters are auto-wrapped:
Actions
Section titled “Actions”block- Immediately reject the request with a 403 Forbidden error (stops all processing)mask- Replace matched content with replacement text and continue processingwarn- Add warning to response metadata without modifying content
List Firewall Rules
Section titled “List Firewall Rules”GET https://api.tokenrouter.io/v1/firewall-rulesReturns all firewall rules for the authenticated user, ordered by priority (highest first).
const response = await fetch('https://api.tokenrouter.io/v1/firewall-rules', { headers: { 'Authorization': 'Bearer tr_...', }});
const { data } = await response.json();console.log(`Found ${data.length} firewall rules`);import requests
response = requests.get( 'https://api.tokenrouter.io/v1/firewall-rules', headers={'Authorization': 'Bearer tr_...'})
data = response.json()['data']print(f"Found {len(data)} firewall rules")curl https://api.tokenrouter.io/v1/firewall-rules \ -H "Authorization: Bearer tr_..."Response
Section titled “Response”{ "data": [ { "id": 1, "user_id": 123, "name": "Block Credit Cards", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/\\d{4}-\\d{4}-\\d{4}-\\d{4}/", "action": "block", "replacement": null, "priority": 100, "created_at": "2025-09-13T19:14:23.000000Z", "updated_at": "2025-09-13T19:14:23.000000Z" }, { "id": 2, "user_id": 123, "name": "Mask Email Addresses", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/", "action": "mask", "replacement": "[EMAIL]", "priority": 90, "created_at": "2025-09-13T19:14:23.000000Z", "updated_at": "2025-09-13T19:14:23.000000Z" } ]}Create Firewall Rule
Section titled “Create Firewall Rule”POST https://api.tokenrouter.io/v1/firewall-rulesCreates a new firewall 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 |
scope | string | Yes | prompt or response |
type | string | Yes | substring or regex |
pattern | string | Yes | Pattern to match |
action | string | Yes | block, mask, or warn |
replacement | string | No | For mask action (default: [redacted]) |
priority | integer | Yes | Priority (-1000 to 1000, higher = first) |
Examples
Section titled “Examples”Block Credit Card Numbers
Section titled “Block Credit Card Numbers”const response = await fetch('https://api.tokenrouter.io/v1/firewall-rules', { method: 'POST', headers: { 'Authorization': 'Bearer tr_...', 'Content-Type': 'application/json', }, body: JSON.stringify({ name: "Block Credit Cards", is_enabled: true, scope: "prompt", type: "regex", pattern: "/\\d{4}-\\d{4}-\\d{4}-\\d{4}/", action: "block", priority: 100 })});
const { data } = await response.json();console.log(`Created rule: ${data.name}`);import requests
response = requests.post( 'https://api.tokenrouter.io/v1/firewall-rules', headers={'Authorization': 'Bearer tr_...'}, json={ "name": "Block Credit Cards", "is_enabled": True, "scope": "prompt", "type": "regex", "pattern": r"/\d{4}-\d{4}-\d{4}-\d{4}/", "action": "block", "priority": 100 })
data = response.json()['data']print(f"Created rule: {data['name']}")curl -X POST https://api.tokenrouter.io/v1/firewall-rules \ -H "Authorization: Bearer tr_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Block Credit Cards", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/\\d{4}-\\d{4}-\\d{4}-\\d{4}/", "action": "block", "priority": 100 }'Mask Email Addresses
Section titled “Mask Email Addresses”{ "name": "Mask Email Addresses", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/", "action": "mask", "replacement": "[EMAIL]", "priority": 90}Warn on API Keys (Substring)
Section titled “Warn on API Keys (Substring)”{ "name": "Warn on API Keys", "is_enabled": true, "scope": "prompt", "type": "substring", "pattern": "api_key", "action": "warn", "priority": 50}Get Firewall Rule
Section titled “Get Firewall Rule”GET https://api.tokenrouter.io/v1/firewall-rules/{id}Returns a single firewall rule by ID.
const response = await fetch('https://api.tokenrouter.io/v1/firewall-rules/1', { headers: { 'Authorization': 'Bearer tr_...', }});
const { data } = await response.json();response = requests.get( 'https://api.tokenrouter.io/v1/firewall-rules/1', headers={'Authorization': 'Bearer tr_...'})
data = response.json()['data']curl https://api.tokenrouter.io/v1/firewall-rules/1 \ -H "Authorization: Bearer tr_..."Update Firewall Rule
Section titled “Update Firewall Rule”PATCH https://api.tokenrouter.io/v1/firewall-rules/{id}Updates an existing firewall rule. All fields are optional.
Examples
Section titled “Examples”Disable a Rule
Section titled “Disable a Rule”await fetch('https://api.tokenrouter.io/v1/firewall-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/firewall-rules/1', headers={'Authorization': 'Bearer tr_...'}, json={"is_enabled": False})curl -X PATCH https://api.tokenrouter.io/v1/firewall-rules/1 \ -H "Authorization: Bearer tr_..." \ -H "Content-Type: application/json" \ -d '{"is_enabled": false}'Update Pattern
Section titled “Update Pattern”{ "pattern": "/\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}/"}Change Action
Section titled “Change Action”{ "action": "warn"}Update Replacement Text
Section titled “Update Replacement Text”{ "replacement": "[REDACTED-PII]"}Delete Firewall Rule
Section titled “Delete Firewall Rule”DELETE https://api.tokenrouter.io/v1/firewall-rules/{id}Permanently deletes a firewall rule.
await fetch('https://api.tokenrouter.io/v1/firewall-rules/1', { method: 'DELETE', headers: { 'Authorization': 'Bearer tr_...', }});requests.delete( 'https://api.tokenrouter.io/v1/firewall-rules/1', headers={'Authorization': 'Bearer tr_...'})curl -X DELETE https://api.tokenrouter.io/v1/firewall-rules/1 \ -H "Authorization: Bearer tr_..."Response
Section titled “Response”{ "success": true}Real-World Examples
Section titled “Real-World Examples”Example 1: Block Social Security Numbers
Section titled “Example 1: Block Social Security Numbers”{ "name": "Block SSN", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/\\d{3}-\\d{2}-\\d{4}/", "action": "block", "priority": 100}When it matches:
- Input contains pattern like “123-45-6789”
What it does:
- Blocks the request immediately
- Returns 403 error with firewall message
Example 2: Mask Phone Numbers
Section titled “Example 2: Mask Phone Numbers”{ "name": "Mask Phone Numbers", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}/", "action": "mask", "replacement": "[PHONE]", "priority": 85}When it matches:
- Phone numbers like “(555) 123-4567”, “555-123-4567”, or “555.123.4567”
What it does:
- Replaces the phone number with
[PHONE] - Continues processing with masked input
Example 3: Warn on Sensitive Keywords
Section titled “Example 3: Warn on Sensitive Keywords”{ "name": "Warn on Sensitive Topics", "is_enabled": true, "scope": "prompt", "type": "substring", "pattern": "confidential", "action": "warn", "priority": 60}When it matches:
- Input contains “confidential” (case-insensitive)
What it does:
- Adds a warning to the response metadata
- Continues processing normally
Example 4: Mask API Keys in Responses
Section titled “Example 4: Mask API Keys in Responses”{ "name": "Mask API Keys in Output", "is_enabled": true, "scope": "response", "type": "regex", "pattern": "/sk-[a-zA-Z0-9]{32,}/", "action": "mask", "replacement": "[API_KEY]", "priority": 95}When it matches:
- AI response contains patterns like “sk-…”
What it does:
- Replaces API key patterns in the response
- Protects against accidental key leakage
Example 5: Block Multiple Credit Card Formats
Section titled “Example 5: Block Multiple Credit Card Formats”{ "name": "Block All Credit Card Formats", "is_enabled": true, "scope": "prompt", "type": "regex", "pattern": "/\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}/", "action": "block", "priority": 100}When it matches:
- “1234-5678-9012-3456”
- “1234 5678 9012 3456”
- “1234567890123456”
What it does:
- Blocks any of these credit card formats
Pattern Matching Details
Section titled “Pattern Matching Details”Substring Matching
Section titled “Substring Matching”- Case-insensitive - “API_KEY” matches “api_key”, “Api_Key”, etc.
- Simple search - Matches anywhere in the text
- Fast - More efficient than regex (no compilation overhead)
- Input normalization - Objects/arrays are JSON-encoded before matching
- Example: Pattern “secret” matches “my-secret-key”
Regex Matching
Section titled “Regex Matching”- Full PCRE support - Use standard regex syntax
- Auto-wrapping - Patterns without delimiters are wrapped automatically
\d{3}-\d{2}-\d{4}becomes/\d{3}-\d{2}-\d{4}/i/\d{3}-\d{2}-\d{4}/stays as-is
- Case-insensitive by default - ‘i’ flag added automatically to wrapped patterns
- Safe execution - Invalid regex patterns fail gracefully (no match)
- Input normalization - Objects/arrays are JSON-encoded before matching
Examples:
/\d{3}-\d{2}-\d{4}/- SSN pattern (stays as-is)/[a-z]+@[a-z]+\.[a-z]+/- Simple email (stays as-is)\d{16}- Wrapped as/\d{16}/i(case-insensitive)/sk-[a-zA-Z0-9]{32,}/- API key pattern
Rule Evaluation
Section titled “Rule Evaluation”Rules are evaluated in this order:
- Priority (descending) - Higher priority rules evaluated first
- ID (ascending) - Older rules evaluated first for same priority
- All matching rules apply - Multiple firewall rules can trigger for the same request
- Scope filtering - Only rules with
scope: "prompt"are currently evaluated
Action Behavior
Section titled “Action Behavior”Block Action
Section titled “Block Action”Request: "My SSN is 123-45-6789"Rule: Block on pattern /\d{3}-\d{2}-\d{4}/
Result: 403 ForbiddenResponse: { "error": { "message": "Request blocked by firewall rule \"Block SSN\".", "meta": { "rule_id": 1 } }}Notes:
- Request is immediately rejected (throws
RoutingException) - No further processing occurs
- Error message includes rule name
- HTTP status: 403 Forbidden
Mask Action
Section titled “Mask Action”Request: "Email me at john@example.com"Rule: - Type: regex - Pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/ - Action: mask - Replacement: [EMAIL]
Transformed Input: "Email me at [EMAIL]"(Request continues to AI provider with masked input)Notes:
- Pattern is replaced with
replacementtext (default:[redacted]) - Substring type: Uses
str_ireplace()(case-insensitive) - Regex type: Uses
preg_replace()with the pattern - Input can be string or array - masking applies to all string values
- Processing continues after masking
Warn Action
Section titled “Warn Action”Request: "This is confidential information"Rule: - Type: substring - Pattern: confidential - Action: warn
Response metadata includes:{ "warnings": [ { "code": "firewall", "message": "Firewall rule \"Warn on Sensitive Topics\" triggered." } ]}Notes:
- Warning message is added to context with code
"firewall" - Message format:
Firewall rule "{rule_name}" triggered. - Request processing continues normally
- Warnings are included in response metadata
- Multiple warn rules accumulate multiple warnings
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 firewall rules require a paid plan." }}404 Not Found
Section titled “404 Not Found”{ "error": { "message": "Firewall rule not found" }}Best Practices
Section titled “Best Practices”- Start with warnings - Test patterns with
warnaction first - Use specific patterns - Avoid overly broad patterns that may block legitimate requests
- Test thoroughly - Validate regex patterns before deploying
- Monitor performance - Check analytics to see how often rules trigger
- Use appropriate scope -
promptfor input filtering,responsefor output sanitization - Set priorities carefully - Higher priority for more critical rules
- Combine with routing rules - Use together for complete request control