Skip to main content

Auto-Router Management API

Manage auto-router configurations programmatically. Create routers, add routing rules, test configurations, and work the review queue -- all through the API.

For an overview of how auto-routing works, see Auto-Router. If your integration was built against the old keyword-based rules, see Upgrading from v1 for the breaking changes.

Use a service account key

These endpoints are designed for programmatic access. We recommend using a service account key rather than a personal key -- service account keys belong to the team (not a user), so you can separate API management from keys that are tied to budgets.

You can only access routers you created (admins can access all routers).

Create a router

curl -X POST https://api.haimaker.ai/auto-router/new \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"router_name": "my-router",
"default_model": "openai/gpt-4o",
"rules": [
{
"rule_order": 1,
"example_prompts": [
"Write a Python function to deduplicate a list",
"Debug this TypeScript error: Cannot read properties of undefined",
"Refactor this SQL query to use a CTE"
],
"target_model": "anthropic/claude-sonnet-4-20250514"
},
{
"rule_order": 2,
"example_prompts": [],
"required_capabilities": ["vision"],
"target_model": "openai/gpt-4o"
}
]
}'

Rules are optional at creation time -- you can add them later. The default_model handles requests when no rule matches. The server embeds each rule's example prompts and stores the resulting centroid; you never send or manage embeddings yourself.

Rule fields

FieldTypeDescription
rule_orderintPriority (lower = higher priority; breaks similarity ties)
example_promptsstring[]Example prompts that define what this rule matches (max 50). Embedded server-side.
match_thresholdfloatMinimum similarity (0-1) for the rule to fire. Omit for the default, 0.8.
required_capabilitiesstring[]Only fire when the request needs these capabilities
initial_turn_onlyboolOnly match on the first message in a conversation
enabledboolDisabled rules are kept but never match (default true)
target_modelstringModel to route to when this rule matches

Rule responses also include a read-only source field: manual for rules you created, mined for rules the tuner learned from traffic, migrated for rules converted from v1 keywords.

warning

keywords and keyword_categories are no longer accepted -- sending either returns a 400. The GET /auto-router/keyword-categories endpoint has been removed. See Upgrading from v1.

Available capabilities

vision, function_calling, response_schema, audio_input, pdf_input, web_search, reasoning

Get router info

curl https://api.haimaker.ai/auto-router/{router_id}/info \
-H "Authorization: Bearer YOUR_API_KEY"

Returns the full configuration including rules, derived model pool, associated keys, and the capture_enabled / auto_apply_enabled settings.

Update a router

Update the router name, default model, or learning settings.

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/update \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"default_model": "anthropic/claude-sonnet-4-20250514",
"capture_enabled": true,
"auto_apply_enabled": false
}'
FieldDescription
capture_enabledStore normalized prompts for tuning and the Traffic tab (30-day retention). Set false to opt out -- the router stops learning.
auto_apply_enabledLet high-confidence tuner proposals apply automatically. Set false and every proposal goes to the review queue instead.

Delete a router

curl -X DELETE https://api.haimaker.ai/auto-router/{router_id}/delete \
-H "Authorization: Bearer YOUR_API_KEY"

Deleting a router unlinks all associated API keys (they will return an error if model: "haimaker/auto" is used).

List routers

curl https://api.haimaker.ai/auto-router/list \
-H "Authorization: Bearer YOUR_API_KEY"

Returns all routers you created. Admins see all routers.


Rule management

Add a rule

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/rules \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rule_order": 1,
"example_prompts": [
"Write a terraform module for a GKE cluster",
"Why is my helm upgrade stuck in pending-install?"
],
"target_model": "anthropic/claude-sonnet-4-20250514"
}'

Existing rules at or above the specified rule_order are shifted down automatically.

Update a rule

curl -X PUT https://api.haimaker.ai/auto-router/{router_id}/rules/{rule_id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rule_order": 1,
"example_prompts": [
"Write a terraform module for a GKE cluster",
"Why is my helm upgrade stuck in pending-install?",
"Fix this Dockerfile so the build cache works"
],
"match_threshold": 0.75,
"target_model": "anthropic/claude-sonnet-4-20250514"
}'

Editing example_prompts recomputes the rule's centroid server-side.

Delete a rule

curl -X DELETE https://api.haimaker.ai/auto-router/{router_id}/rules/{rule_id} \
-H "Authorization: Bearer YOUR_API_KEY"

Reorder rules

Bulk reorder rules without changing their content:

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/rules/reorder \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{"rule_id": "rule-abc", "rule_order": 1},
{"rule_id": "rule-def", "rule_order": 2},
{"rule_id": "rule-ghi", "rule_order": 3}
]
}'

Revert a mined rule

One-click revert for rules the tuner created. The rule is disabled (not deleted) and the changelog records who reverted it.

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/rules/{rule_id}/revert \
-H "Authorization: Bearer YOUR_API_KEY"

Only works on mined or migrated rules -- for rules you created manually, use delete instead.


Simulate routing

Test which model would be selected for a given prompt without making an actual LLM request. Free and fast. The response is a full similarity breakdown, so this doubles as a debugger for thresholds and rule overlap.

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/simulate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Write a Python script to parse CSV files"
}'

You can also pass full messages and tools arrays for more accurate simulation:

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/simulate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}
]}
]
}'

Response:

{
"resolved_model": "anthropic/claude-sonnet-4-20250514",
"rule_id": "rule:rule-abc-123",
"reason": "example-match",
"similarity": 0.91,
"detected_capabilities": null,
"rule_similarities": [
{
"rule_id": "rule-abc-123",
"target_model": "anthropic/claude-sonnet-4-20250514",
"similarity": 0.91,
"match_threshold": 0.8,
"matched": true,
"skipped_reason": null
},
{
"rule_id": "rule-def-456",
"target_model": "openai/gpt-4o",
"similarity": 0.42,
"match_threshold": 0.8,
"matched": false,
"skipped_reason": null
}
]
}
FieldDescription
resolved_modelThe model that would handle the request
rule_id"rule:<id>" of the matched rule, or "default" / "capability-fallback"
reason"example-match", "capability-fallback", or "default"
similaritySimilarity score of the matched rule
detected_capabilitiesCapabilities detected in the request
rule_similaritiesPer-rule breakdown: score vs. threshold, and skipped_reason (disabled, capability-mismatch, not-initial-turn, target-not-capable, no-examples) when a rule wasn't eligible

Proposals (review queue and changelog)

The tuner analyzes your captured traffic daily and proposes cheaper routes as rules. See Rules the router learns on its own for how proposals are generated and when they auto-apply.

List proposals

# Review queue
curl "https://api.haimaker.ai/auto-router/{router_id}/proposals?status=pending" \
-H "Authorization: Bearer YOUR_API_KEY"

# Changelog
curl "https://api.haimaker.ai/auto-router/{router_id}/proposals?status=auto_applied,accepted,rejected,reverted" \
-H "Authorization: Bearer YOUR_API_KEY"

status accepts a comma-separated list of pending, auto_applied, accepted, rejected, reverted, expired. Omit it to get everything (newest first, up to 200).

Response (one entry):

{
"id": "prop-123",
"router_id": "router-abc",
"rule_id": null,
"status": "pending",
"cluster_examples": [
"Classify the sentiment of this review as positive, negative, or neutral: ...",
"Classify the sentiment of this review as positive, negative, or neutral: ..."
],
"cluster_stats": {
"weight": 1240,
"distinct_days": 6,
"tightness": 0.94,
"key_attribution": {"a1b2c3...": 0.98}
},
"judge_tier": "trivial",
"judge_task_type": "sentiment classification",
"judge_reasoning": "Single-label classification with a fixed output format; no reasoning depth required.",
"current_route": "default",
"proposed_model": "z-ai/glm-4.7-flash",
"projected_savings": 38.4,
"created_at": "2026-06-10T04:00:00Z",
"resolved_at": null,
"resolved_by": null,
"resolved_by_email": null
}
FieldDescription
cluster_examplesRepresentative prompts from the traffic cluster
cluster_statsVolume (weight), distinct_days, cluster tightness, and which API keys sent the traffic
judge_tiertrivial, standard, or complex
judge_reasoningWhy the judge rated it that way -- read this before accepting
current_routeWhere the traffic goes today (default, capability-fallback, or a rule)
projected_savingsEstimated monthly savings in USD, from the cluster's observed spend
resolved_byUser ID, or "auto" / "auto-revert" for tuner actions
resolved_by_emailEmail of the resolving user, when applicable

Pending proposals expire after 30 days if nobody acts on them.

Accept a proposal

Creates the mined rule and records the decision in the changelog.

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/proposals/{proposal_id}/accept \
-H "Authorization: Bearer YOUR_API_KEY"

Reject a proposal

curl -X POST https://api.haimaker.ai/auto-router/{router_id}/proposals/{proposal_id}/reject \
-H "Authorization: Bearer YOUR_API_KEY"

Both return the updated proposal. Only pending proposals can be accepted or rejected.


Traffic summary

Top captured prompt templates, for understanding what your router actually serves. Same data as the dashboard's Traffic tab.

curl "https://api.haimaker.ai/auto-router/{router_id}/traffic-summary?days=30" \
-H "Authorization: Bearer YOUR_API_KEY"

days is clamped to 1-30. Returns the top 50 templates by request count:

{
"days": 30,
"templates": [
{
"prompt_hash": "9f8e7d...",
"prompt_text": "HEARTBEAT: confirm agent liveness and report queue depth",
"weight": 4210,
"trigger": "rule:rule-abc-123",
"resolved_model": "z-ai/glm-4.7-flash"
}
]
}

prompt_text is the normalized template (volatile parts like timestamps stripped), truncated to 300 characters. trigger is default, capability-fallback, or rule:<id>. Returns empty templates if capture is disabled for the router.


Assign a router to a key

To use auto-routing, assign a router to an API key via the auto_router_id field. Then requests with model: "haimaker/auto" will use that router.

curl -X POST https://api.haimaker.ai/key/update \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "sk-key-to-update",
"auto_router_id": "router-id-here"
}'

Or assign during key creation:

curl -X POST https://api.haimaker.ai/key/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"team_id": "your-team-id",
"key_alias": "auto-routed-key",
"auto_router_id": "router-id-here"
}'

Query routing history

Fetch spend logs to see how your auto-routed requests were resolved. See Auto-Router > Query routing history for full details.

curl "https://api.haimaker.ai/spend/logs/v2?start_date=2026-06-01&end_date=2026-06-08&page=1&page_size=50" \
-H "Authorization: Bearer YOUR_API_KEY"

Each entry includes auto-routing metadata in the metadata field: auto_routed_from, auto_routed_model, auto_routing_trigger, auto_routing_similarity, and auto_routing_rule_source.