Idempotency and retries
The network fails halfway through a POST. Did the job get created? Without a way to ask — and this API has no way to read a job back — a retry is a coin toss between a missing job and two of them.
The Idempotency-Key header removes the guess.
Sending a key
Section titled “Sending a key”Every create request carries one:
Idempotency-Key: crm-order-2026-000123- Required on POST only.
GETrequests need none. - Up to 255 characters, from
A-Z a-z 0-9 . _ : -. - A UUID v4 is the recommended shape.
- Generate it once per intended action, and reuse that same value for every retry of it.
The last point is the whole mechanism. A key generated fresh on each attempt protects nothing.
What happens on a repeat
Section titled “What happens on a repeat”| You send | You get |
|---|---|
| The same key, the same body | The original response, replayed. No second record is created. |
| The same key, a different body | 422, IDEMPOTENCY_CONFLICT. The key is already spoken for by a different request. |
| The same key while the first is still running | 409, IDEMPOTENCY_CONFLICT. Wait, then retry. |
A new key, but an external_id already used | 409, DUPLICATE_EXTERNAL_ID. |
The last row is a second line of defence. Your own external_id — CRM-JOB-10001 — is checked for duplicates independently of the idempotency key, so even a genuinely new request cannot create a second EyeOnTask job for one CRM record.
What to retry, and what not to
Section titled “What to retry, and what not to”Retry on 429, and only after the Retry-After period. Use the same idempotency key. See rate limits.
Do not retry automatically on 422 or 409. Both mean the server understood you and is refusing on purpose — a field is wrong, or the record already exists. Retrying changes nothing and hides the problem; these belong in front of a person, or in a queue that a person reads.
Use a new key for a different request. Two jobs for the same customer on the same day are two actions and want two keys, however similar their bodies look.