Buni.aiDocs

Idempotency

Retry API calls safely with the x-idempotency-key header, so a network timeout never sends a message or runs a workflow twice.

Networks fail after the server has done the work. If you retry a timed-out request without protection, the customer gets the same message twice or the order workflow runs twice. Send an x-idempotency-key header and Buni.ai returns the first run instead of starting a new one.

Send a key

Use a value that identifies the business event, not the HTTP attempt, such as order-10442-paid. Keys are up to 128 characters.

curl -X POST "https://www.buni.ai/api/v1/orgs/$ORG_ID/automations/$PROJECT_ID/trigger-async" \
  -H "Authorization: Bearer $BUNI_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "x-idempotency-key: order-10442-paid" \
  -d '{"event": "order.paid", "payload": {"orderId": "ORD-10442"}}'

How a repeated key is answered

A key is matched within one project, for the same kind of call: target (bot, flow or automation) and mode (sync or async). The request body is not compared, so do not reuse a key for a different event.

Sync endpoints

/bots/.../message, /flows/.../trigger and /automations/.../trigger:

Earlier run with this keyResponse
SUCCEEDED200 with the stored result and "idempotentReplay": true. Nothing runs again.
QUEUED or RUNNING202 with invocationId, status and "idempotentReplay": true. Wait, then retry or read the invocation.
FAILED or any other statusA new run starts. Retrying with the same key after a failure is safe.

Async endpoints

/bots/.../invoke, /flows/.../trigger-async and /automations/.../trigger-async return 202 with the earlier invocationId, its current status and "idempotentReplay": true, whatever that status is. A run that failed is not retried; use a new key to run again.

{
  "invocationId": "clx9km1a40030ab12cd34ef40",
  "status": "FAILED",
  "idempotentReplay": true
}

Things to know

  • Keys longer than 128 characters are ignored, as if you sent none.
  • Keys do not expire.
  • A replayed response still counts toward the rate limit, but does not create an invocation, so it does not use your monthly quota.
  • Polling, dead-letter and invocation endpoints ignore the header.
  • The Webhook trigger URL also honours x-idempotency-key: a repeat returns 200 {"deduplicated": true}.
  • Async callbacks can be delivered more than once. De-duplicate them on invocationId; see Async runs and callbacks.
Last reviewed 24 September 2026

On this page