Routerra LogoTeams
Browse articles· Idempotent API requests
For ownersUpdated 2026-09-08 · 3 min read

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 /optimize
  • POST /plans/{planId}/stops
  • PUT /plans/{planId}/stops/{stopId}
  • POST /plans/{planId}/stops/remove
  • POST /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_conflict instead 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.

Was this article helpful?

Still stuck?

Write to us — a human reads every message.

Contact support