Skip to the content
Menu: Idempotency and retries

Idempotency and retries

A network can fail after Zentiq has done what you asked but before the answer reaches you. Retrying a GET, PUT, PATCH or DELETE is always safe. Retrying a POST that creates something (a persona, a webhook, a session) could create it twice, unless you send an Idempotency-Key.

How it works#

Send a unique string (up to 255 characters; a UUID is ideal) in the Idempotency-Key header, and send the same key when you retry the same request:

Shell
curl -X POST https://app.zentiqai.com/v1/knowledge/bases \
  -H "Authorization: Bearer $ZENTIQ_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c2b8e-2f4a-4c1e-9d7a-0b6c5e4d3a21" \
  -d '{ "name": "Help centre" }'
  • The first success is kept for 24 hours. A retry with the same key and the same request gets that answer again, with Idempotency-Replayed: true, and nothing is done twice.
  • The same key with a different request is 409 idempotency_conflict: use a new key for a new request.
  • A retry while the first is still running is 409 idempotency_in_progress, with Retry-After: wait, then retry.
  • A failed first attempt isn't kept: a retry after a failure runs again.

Keys are per API key: two integrations can't collide.

Which operations take it#

These are safe to repeat by their own input (the same externalId gives back the same record), and their answer is never stored:

In the SDKs#

The SDKs send an Idempotency-Key with every operation above and reuse it when they retry, so their own retries are always safe. To make your retries safe (a job that restarts, a queue that redelivers), pass a key you keep with the job:

Node
// The SDK sends an Idempotency-Key with every creating call that takes one (the reference marks them) and reuses it
// when it retries. To make your own retries safe across restarts, pass a key you store with the job:
const pack = await zentiq.createKnowledgeBase({ name: "Help centre" }, { idempotencyKey: "import-2026-10-01-help-centre" });

Speaking into a live session#

POST /v1/sessions/{id}/say takes its own eventId in the body instead: in external turn mode, a line sent again with the same eventId is spoken once (see Bring your own brain).