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 key | Response |
|---|---|
SUCCEEDED | 200 with the stored result and "idempotentReplay": true. Nothing runs again. |
QUEUED or RUNNING | 202 with invocationId, status and "idempotentReplay": true. Wait, then retry or read the invocation. |
FAILED or any other status | A 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 returns200 {"deduplicated": true}. - Async callbacks can be delivered more than once. De-duplicate them on
invocationId; see Async runs and callbacks.