Routerra LogoTeams
Browse articles· API limits & quotas
For ownersUpdated 2026-09-08 · 6 min read

API limits & quotas

Rate limits, concurrent optimizations, the daily optimization quota and its dashboard reserve — every way a Routerra Teams API call gets refused with a 429.

Six limits stand between your integration and the solver, and they are independent of each other: clearing one says nothing about the next. Five of the six refuse with 429, which is the trap — tell them apart by the code field, not by the status, because the right thing to do afterwards is different in every case.

LimitDefaultApplies toRefusal
General rate limitcapacity 60, refilled continuouslyEvery endpoint and every MCP tool429 rate_limit_exceeded + Retry-After
Optimize tiercapacity 5, refilled continuouslyEvery optimization, on both transports: the REST paths POST /optimizeincluding dispatch=false — and POST …/dispatch, plus the MCP tools optimize_plan and dispatch_plan, plus POST /changes/{changeId}/apply for a DISPATCH proposal429 rate_limit_exceeded over REST; 429 too_many_requests wherever the token is taken by hand
Concurrent optimizations3 per teamAny dispatch, including the ones started from the dashboard429 concurrent_optimization_limit
Daily optimization quotaFrom the team's plan (optimizationQuota.capacity)POST /optimize with dispatch=true, and POST …/dispatch429 too_many_requests; the token is handed back if the optimization fails
Stops per planThe team's stop limit — 200 unless changed/optimize, …/stops, …/dispatch409 stop_limit_exceeded. …/stops and …/stops/remove also cap the body itself at 200 entries, which is a 400 validation_error and applies whatever the team setting says; /optimize has no such body cap
Open proposals25 per plan, 100 per teamPOST …/changes, and the MCP hand-off429 too_many_proposals

The dashboard's reserve in the daily quota

FieldMeaning
capacityThe team's full daily quota
availableHow much is left in total — dashboard and API together
availableForApiHow much of that API keys may spend. Always ≤ available
"optimizationQuota": { "capacity": 34, "available": 26, "availableForApi": 14 }

You never need a separate call to find out where you stand: the current quota comes back from GET /team and from every POST …/dispatch response.

What to do with each refusal

  • rate_limit_exceeded — wait out the Retry-After header and retry the same call. It is safe: nothing was applied.
  • concurrent_optimization_limit — three optimizations are already running for the team. There is nothing to do but wait for one of them to finish and retry. You cannot free a slot by cancelling: a plan in DISPATCHING_IN_PROGRESS refuses DELETE with 409 plan_state_transition until it reaches DISPATCHED.
  • too_many_requests — the day's optimizations are gone, or the API's share of them is: retrying sooner will not help, so retry tomorrow or ask a dispatcher to run it from the dashboard. The same code also comes back when the optimize-tier bucket is empty on a call that takes its token by hand (optimize_plan, dispatch_plan, apply_change) — that one is worth retrying in a few seconds. The message tells the two apart.
  • too_many_proposals — the queue is full. A dispatcher has to apply or reject some of the open ones first; see Proposed changes.
  • stop_limit_exceeded — a 409, not a 429. Split the work across plans.

When you retry a call that mutates something, send the original clientRequestId so it can only be applied once — see Idempotent API requests. The full list of codes is in API error reference.

Was this article helpful?

Still stuck?

Write to us — a human reads every message.

Contact support