Idempotent API requests
Send clientRequestId so a timed-out Routerra Teams API call can be retried without applying it twice — and what the deduplicated replay will not tell you.
A request that times out leaves you with a real question: did it land? Dispatching a plan twice is not a harmless mistake — it spends two optimizations and can pull routes back from drivers a second time. clientRequestId is how you retry without having to guess.
It is an optional string of up to 128 characters, and five operations accept it:
POST /optimizePOST /plans/{planId}/stopsPUT /plans/{planId}/stops/{stopId}POST /plans/{planId}/stops/removePOST /plans/{planId}/dispatch
Generate one per logical operation — a UUID is the obvious choice — and send it with the call. If the call fails in a way that leaves you unsure (a timeout, a dropped connection), repeat the request with the same id. The operation is applied at most once, and the repeat gives you back the original result with deduplicated: true attached.
Request · POST …/dispatch
{
"driverIds": [91, 93],
"clientRequestId": "d3f1c0aa-2b7e-4a51-9c8d-6e2f0b41a7c5"
}Response · the retry
{
"planId": 315,
"status": "DISPATCHING_IN_PROGRESS",
"driverIds": [91, 93],
"deduplicated": true
}When a repeat is refused
409 client_request_id_conflict— that id has already been used for a different operation, or on a different plan. Ids are not scoped per endpoint; take a new one.409 client_request_in_progress— a request with this id is still running and there is no stored result yet. This is the one worth retrying: wait a few seconds and ask again.
Two windows to know about
- The in-progress window is 10 minutes. After that the server treats the first call as abandoned, and a repeat carrying the same id runs the operation again rather than replaying it. Retry inside the window, or accept that a very late retry is a fresh call.
- Change-log entries shed their heavy fields after 30 days. A repeat older than that gets
409 client_request_id_conflictinstead of a replay. In practice nothing retries a request a month later, so this matters only if you generate ids from a stable key — an order number, say — and could reuse one much later.
Everything else
The remaining endpoints do not take a clientRequestId, so treat their retries on their own terms. GET calls are safe to repeat by definition. POST /plans/{planId}/approve is protected by the state machine instead: it only accepts a plan in DISPATCHED, so a second approve finds the plan already APPROVED and answers 409 plan_state_transition rather than doing the work twice — see Plan lifecycle & statuses.
A 429 is always safe to retry, because nothing was applied before the refusal — see API limits & quotas. For the rest of the codes, see API error reference.