Idempotency and batch
A timeout doesn't tell you whether BrokerPlus made the record. Send the same request again without
protection and you can end up with two contacts, two leads, or two tasks. This page covers the two
tools that prevent that: the Idempotency-Key header for single requests, and external_id for
batch writes.
The Idempotency-Key header
Make up a unique key for each new operation, such as a UUID, and send it on every POST. If you
retry with the same key and the same request, the API returns the response it stored the first
time, with an Idempotent-Replay: true header, and does not do the work again.
A retry must send exactly the same bytes. Serialize the body once and send that string on every attempt. Different whitespace or a different key order counts as a different request.
A good key comes from your own data, so a crashed job finds the same key when it restarts. For
example, webform-<submission id> or zoho-contact-<old id>.
What the header covers
| Rule | Detail |
|---|---|
| Methods | POST only. PATCH and DELETE are not protected. |
| Lifetime | 24 hours. After that the key is forgotten, which does not mean the first request failed. |
| Ownership | A key belongs to the API key and broker that first used it. Key strings are unique across the brokerage. |
| Match | The method, path, and body bytes must all match. |
| Access | If you can no longer see the record the first request made, the replay returns 404 and changes nothing. |
| Optional | Without the header, nothing is stored and a retry is a new request. |
The header makes a retry safe, but it is not an exactly-once guarantee. The record write and the
stored response are separate steps, so a server error can land between them. After a 5xx or a
timeout, check the record before you send a request with a new key.
Conflicts
| Response | What happened, and what to do |
|---|---|
409 IDEMPOTENCY_KEY_IN_FLIGHT | The first request is still running. Wait, then retry with the same key and body. If it persists, check whether the record exists. |
409 IDEMPOTENCY_KEY_CLAIMED | Another API key or broker owns this key. Nothing ran. Don't switch to a new key until you know whether the first request worked, or you can make a duplicate. |
422 IDEMPOTENCY_KEY_REUSED | The key is yours, but the request differs from the first one. Send the original method, path, and body, or use a new key for a genuinely new operation. |
A request that fails validation before it changes anything releases its key. Fix the body and try again with the same key.
Batch writes
Four endpoints create or update up to 100 records in one request:
POST /v1/contacts/batchPOST /v1/leads/batchPOST /v1/deals/batchPOST /v1/tasks/batch
Each item is the body you would send to the single create (POST /v1/contacts) or, for a record
that exists, the single update (PATCH /v1/contacts/{id}). The single endpoint checks each item, so
the rules and errors are the same.
Code
Code
How a batch behaves:
- Send
external_idwith anamespace, and BrokerPlus remembers the pair. The next batch with the sameexternal_idupdates that record instead of making a new one. Thenamespaceis the name of the system your ids come from, such aszoho, so two systems can use the same id. - To update a record you already know, send its BrokerPlus
id. Sendidandexternal_idtogether to link your id to a record that is already in BrokerPlus, so later batches find it. - If the record an
external_idnames was deleted or merged in BrokerPlus, that item fails with404 NOT_FOUNDand nothing is written. BrokerPlus does not quietly re-create what the broker removed. - Items are not one transaction. A failed item doesn't stop the others. Read
results, one per item in the order you sent them, and retry only the items that failed. - An
external_idthat already names a different record fails that item with409 EXTERNAL_ID_TAKEN. Two requests racing on the same newexternal_idfail one item with409 EXTERNAL_ID_IN_FLIGHT; send it again shortly. - A batch that is invalid as a whole (no items, more than 100, the same
external_idtwice, or anexternal_idwithoutnamespace) returns400and writes nothing. - Each item counts as one request against the rate limit.
- A batch is a
POST, so theIdempotency-Keyheader works on it too. A retry with the same key replays the whole batch response.
The Migrate from another CRM guide uses batch writes for a full import.
To complete, cancel, or reopen many tasks at once, use POST /v1/tasks/bulk (up to 200 tasks). It
applies one action and lists the tasks it changed and skipped.