Idempotent Requests
Safely retry EasyRoutes API mutations without performing the same operation twice.
Idempotency lets you safely retry a mutating request when a network error, timeout, or lost response leaves its result uncertain. Add an Idempotency-Key header, then reuse the same key and request for every retry.
EasyRoutes stores the response once the mutation succeeds. A matching retry returns that stored response instead of running the operation again, preventing duplicate resources, updates, and side effects such as webhooks.
Send an idempotency key
Idempotency keys are optional on supported authenticated POST, PUT, PATCH, and DELETE requests; each supported endpoint lists the Idempotency-Key header on its API reference page. Keys are ignored on GET and HEAD and by POST /authenticate.
Generate a new key for each operation — a UUID v4 or another random value with enough entropy to avoid collisions.
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000An idempotency key:
- Must be between 1 and 255 characters.
- Must not contain sensitive information, such as customer details, email addresses, or API credentials.
- Must only be reused with the same API operation and request parameters.
Keys are scoped to your organization and API client, but treat each key as unique within your integration.
How EasyRoutes matches your key
EasyRoutes matches the key against the API operation and its parsed request — path, query, and body. Because the parsed request is compared, differences in JSON whitespace or object key order don't matter.
| Your request | What you get back |
|---|---|
| First request | Reserves the key and runs the operation. The response and mutation are saved together only on success. |
| Retry after success | Doesn't run again. Returns HTTP 200 with the stored response and Idempotency-Replayed: true. |
| Retry while the first is still running | Returns HTTP 409 idempotent request already in progress. Wait, then retry the same request and key. |
| Same key, different request | Returns HTTP 400 cannot reuse key for different request. Send the original request, or use a new key. |
Only successful responses are stored. Validation failures, server errors, and rolled-back mutations aren't replayed, and the key is freed so you can retry.
Example: safely retrying a route creation
The following request creates a route with an idempotency key. Replace YOUR_ACCESS_TOKEN with the token returned by POST /authenticate. Generate the key once, persist it alongside your operation, and reuse that exact value on every retry.
# Generate once (e.g. `uuidgen`), persist it, and reuse it on every retry.
curl -X POST \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"start": {
"address": {
"address1": "123 Queen St W",
"city": "Toronto",
"provinceCode": "ON",
"countryCode": "CA",
"zip": "M5H 2M9"
}
}
}' \
https://easyroutes.roundtrip.ai/api/2024-07/routesIf the response is lost, repeat the request with the same key — don't generate a new one, since the original might already have committed. If it did, EasyRoutes returns the stored response without creating another route:
HTTP/1.1 200 OK
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Idempotency-Replayed: true
Content-Type: application/jsonSuccessful responses echo the Idempotency-Key. Idempotency-Replayed: true appears only on a stored response, never the first.
Failure cases
How you respond depends on whether the operation might have committed:
| Failure | What happened | What to do |
|---|---|---|
| Connection failure, timeout, or lost response | Outcome unknown — the operation might have committed without returning a response. | Retry unchanged with the same key. It replays if committed, otherwise runs safely. |
HTTP 409 with idempotent request already in progress | An earlier request with the same key is still being processed. | Wait, then retry unchanged with the same key. |
Transient HTTP 5xx | No successful response, so nothing was stored and the key is freed. | Retry unchanged with the same key using exponential backoff and jitter. |
Validation or other correctable 4xx error | The operation didn't run and nothing is stored for replay. | Correct the request and retry. Reuse the key, or use a new one. |
HTTP 400 with cannot reuse key for different request | The key is already tied to different parameters or another operation. | Send the original request with that key, or use a new key for the different request. |
HTTP 400 for an invalid key | The key is empty, over 255 characters, or otherwise invalid. Nothing is stored. | Fix the key and retry. |
Never change a request while its outcome is unknown. If the first attempt committed, changing parameters but keeping the key returns a key-reuse error; changing both can run a second mutation.
Retry safely
A retry strategy for mutating requests:
- Generate and persist a key before the first attempt.
- Send the request with that key.
- On a connection failure, timeout,
409, or transient5xx, retry with the same key and unchanged request using exponential backoff with jitter. - On
cannot reuse key for different request, resend the original request or use a new key for the new operation. - Stop after a reasonable limit, keeping the key with your operation record for troubleshooting.
Never replace the key just because a response was lost or a transient error occurred — it breaks the link to the first attempt and can run the operation twice.
Retention
EasyRoutes retains completed idempotency records for at least 24 hours. After that, reusing a key is treated as a new request and can run the operation again, so always generate new keys for new operations.