Skip to content
Sursa Developers

Idempotent requests

A request can fail after Sursa has already done the work: the connection drops, or your process restarts before the response arrives. If you send the same POST again, you could create a second card or a second webhook. An idempotency key prevents that.

Send an Idempotency-Key header with every POST and PATCH. If Sursa has already seen a request with this key, it does not run the operation again: it returns the response it saved the first time.

curl -X POST https://api.example.com/v1/cards/text \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -H "Idempotency-Key: 6f1d2c9e-7b0a-4c43-9a51-0d6c1c1f8e21" \
  -H "Content-Type: application/json" \
  -d '{"title": "Refund policy", "body_markdown": "Refunds are processed within 14 days."}'

A repeated request gets the same status and body as the first one, with an extra header:

HTTP/1.1 200 OK
Idempotency-Replayed: true
X-Request-Id: 01JB7R…

The repeated request has its own X-Request-Id.

Choosing a key

  • Use a new random value, such as a UUID v4, for each logical operation: "create this card", "register this webhook". Use the same value for every retry of that operation, and never for a different one.
  • A good key is derived from your own data when you have one, for example sync-2026-10-24-record-1042. Then even a restarted job that lost its memory sends the same key again.
  • The key is 1 to 255 printable ASCII characters. Anything else returns 400 with the code api.idempotency_key_invalid.

What Sursa does with the key

SituationResponse
First request with this keyThe operation runs as usual.
Same key, same request, the first one finished with 2xx or 4xxThe saved response, with Idempotency-Replayed: true. The operation does not run again.
Same key, the first request is still running409 api.idempotency_in_progress with Retry-After: 1. Wait and retry.
Same key, a different method, path, Content-Type or body409 api.idempotency_mismatch. The key is already taken by another request.
The first request finished with 5xx or 429The key is released: the next request with it runs the operation again.
  • A key is valid for 24 hours. After that, the same key starts a new operation.
  • Keys are separate per organization and per caller: two different API keys can use the same value without affecting each other.
  • An error response with 4xx is saved too. A request that failed validation fails the same way when it is repeated with the same key; fix it and send it with a new key.

Which requests need it

MethodIdempotency-Key
POST, PATCHSend it. Every endpoint that saves its response for a repeat lists the header in the API reference.
GET, PUT, DELETENot needed: these methods are safe to repeat by their meaning. The header is accepted and has no effect.
POST that only reads, such as search, the financial reports and POST /v1/catalog/resolveAccepted, but nothing is saved: the request simply runs again.

Some operations are safe to repeat even without the header:

  • PUT /v1/cards-by-external-id/{external_id} creates or replaces the card with your ID; a repeat with the same content changes nothing.
  • Documents of a custom source are keyed by your external_id; sending the same document again returns unchanged.
  • A streamed answer of POST /v1/chat uses the request_id field of the body instead of the header. See Build a Q&A bot.

Retrying safely

Combine the key with the retry rules from Errors: create the key once, before the first attempt, and send it with every attempt of the same operation.