Idempotency-Key header on any POST request that takes a JSON body to
make it safe to retry. If the first attempt already succeeded, the retry returns
that original response instead of creating a second record or sending a second
message. File uploads are the exception — they take form data, and the header
has no effect there.
Retrying
Send the identical request — same endpoint, same body — with the same key. The replayed response carries anIdempotency-Replay: true header so you can tell
it apart from a fresh one.
Use a new key whenever you mean to perform a new operation, even a similar one.
Reusing a key with a changed body is rejected rather than treated as a retry, so
a key is bound to exactly one request.
Keys are scoped to your organization and last 24 hours. After that the same
value can be used again for a new operation.
Manual invoice payments
ForPOST /v1/invoices/{id}/payments, the header is required and also
identifies the manual payment in chat, MCP, and automations. Reuse the same key
only for the same invoice, amount, payment time, and note. The key stays bound
to that payment after the 24-hour API replay window ends.
This holds once that window closes, and when the payment was recorded from chat,
MCP, or an automation: an identical retry returns the original payment, and a
different payment sent under the same key is refused with
IDEMPOTENCY_KEY_REUSED. Record each new payment with a new key.
While a request is still running
If you retry before the original request has finished, the retry returns409
and the original keeps running. Wait, then retry again to collect the result.
A request that fails releases its key immediately, so you can retry it with the
same key. When an error tells you to use a new key, use one — retrying with the
original returns the failed attempt instead of starting a new one.
Errors
See Errors for the full catalog.
Domain registration and renewal
Registering a domain (POST /v1/domain-registrations) and renewing one
(POST /v1/domains/{id}/registration/renew) move money, so the header is
required there. Omitting it returns 400. See
Register a Domain via the API.