Idempotency
Preventing duplicate public API writes when an integration retries.
Idempotency
Current V2 status (2026-09-24): This contract is live in V2 on the writes V2 exposes today:
POST /api/v1/leads,POST /api/v1/clients, andPATCH /api/v1/clients/:id, plus test-key sandbox writes to leads, clients, and estimates, andPOST /api/v1/webhookswith a live key. LivePOST /api/v1/estimatesdraft creation is pending production and will also require this header. Until released, it returns405 write_not_supported. Estimate updates, job and invoice writes, and lead updates still answer405 write_not_supportedwith a live key. In V2 the key must be 1 to 255 printable characters (422 invalid_idempotency_key), a missing header returns422 missing_idempotency_key, and two bodies count as the same request when they are the same JSON document, whatever the key order or number spelling. Live-key automation draft-save, publish, and pause operations also require this header. Test keys cannot use automation routes.
All live and sandbox external API POST and PATCH writes require an Idempotency-Key header. Workflow gateway POST queries are read-only and do not require the header. When live draft creation ships, the key will include POST /api/v1/estimates. DELETE /api/v1/webhooks/:id accepts the header as an option: send one and a retry after a lost response replays the original success instead of answering 404.
That includes every public write endpoint. In V2 today, live keys can use /api/v1/leads, /api/v1/clients, /api/v1/clients/:id, and /api/v1/webhooks; test keys can additionally write sandbox records through /api/v1/estimates and /api/v1/estimates/:id:
/api/v1/leads/api/v1/leads/:id/api/v1/clients/api/v1/clients/:id/api/v1/estimates/api/v1/estimates/:id/api/v1/jobs/api/v1/jobs/:id/api/v1/invoices/api/v1/invoices/:id/api/v1/webhooks
Live-key PATCH /api/v1/automations/:id, POST /api/v1/automations/:id/publish, and POST /api/v1/automations/:id/pause also require this header. These routes do not accept test keys. The matching MCP write tools require an idempotencyKey argument and forward it to the same idempotency ledger.
Application workflow mutations at POST /api/v1/workflows/{operation} use a durable request receipt. The first response includes meta.request_id; read its state at GET /api/v1/workflows/requests/{requestId} with either exact workflows:read or workflows:write. A mutation requires a live key with exact workflows:write scope and the current application permission for that operation. Legacy * and workflows:* do not grant these scopes.
This protects you from duplicate writes when a request times out, your worker retries, or a no-code platform like Zapier replays the same step.
How It Works
- Your integration sends a unique
Idempotency-Key. - CE Pro stores the request fingerprint and response.
- If you retry the same request with the same key and the same payload, CE Pro returns the original result instead of creating a duplicate record.
- If you reuse the same key with a different payload, CE Pro returns
409. - If another request with the same key is still running, CE Pro returns
409 idempotency_in_progress.
For a workflow operation, the key claims one durable receipt and is never reclaimed. CE Pro never automatically starts a pending or indeterminate mutation again. A recognized post-claim 4xx preserves its HTTP status and includes a sanitized receipt_id with receipt_status: "indeterminate"; an unknown server failure returns 202 with the indeterminate receipt. Reusing the key with different input returns 409. Once completed, an exact retry replays the saved response and includes X-Idempotent-Replayed: true.
Header Example
Idempotency-Key: cepro-lead-20260314-001When To Reuse A Key
Reuse the same key only when you are retrying the exact same operation.
Examples:
- A lead-create call timed out and you want to retry it safely
- A network hop failed after the server already processed the request
- A workflow runner retries the same step automatically
Create a new key for every new write operation.
Recommended Strategy
Use a key derived from your upstream system's stable id:
- Form submission id
- CRM record id
- Queue message id
- Workflow run id plus step id
That keeps retries safe even across worker restarts.
Error Behavior
- Same key + same body: CE Pro replays the original response
- Same key + different body:
409 - Same key while the original request is still running:
409 idempotency_in_progress - An automation draft save with a stale
expectedRevisionalso returns409;
reload the workflow details and review the current version before retrying.
- Missing key on a mutating
POSTorPATCH: request rejected - Key on
DELETE /api/v1/webhooks/:id: optional; when present, a retry replays the original success
The resource-specific REST endpoints keep completed and failed idempotency records for 72 hours. Application workflow mutations use the durable receipt described below.
Workflow receipts are durable operation records. Do not retry an unresolved mutation with a new idempotency key: look up its receipt and wait for the original operation's state. Receipt lookup and replay recheck the same key, member, current permission, and location scope that claimed the receipt. Changed access hides a receipt with 404 or rejects a replay with 409. For catalog entries marked as returning secrets, only the first response can contain the sensitive value; the stored receipt and replay contain the redacted projection.
Practical Tip For No-Code Tools
If your tool supports a stable step identifier, map that into Idempotency-Key. If it does not, create a deterministic key from the external object id you are syncing.
Related articles
Was this article helpful?
Still need help? Contact support