Idempotency-Key header:
POST /v2/orders— buy a credit pack.POST /v2/surveys/{id}/publish— pay for and publish a draft survey.
GET, PATCH, and DELETE calls are naturally idempotent and safe to retry on network error. POST /v2/surveys/{id}/stop is also safe to retry — stopping an already-stopped survey is a no-op.
Other POST calls (POST /v2/surveys, POST /v2/media, POST /v2/webhook-endpoints) do not accept Idempotency-Key and are not deduplicated server-side. A retry after a lost response can create a duplicate draft survey, upload the same media twice, or register a second webhook endpoint. If you can’t tell whether the original attempt landed, list the resource (GET /v2/surveys?..., GET /v2/webhook-endpoints) or use your own request identifier (externalId on surveys) to reconcile before retrying.
The key
Send a unique string per attempt in the header:- Up to 255 characters. A UUID or a hash of your own request identifiers both work.
- Scoped per team. Two different teams can reuse the same key without collision.
- Retained for 24 hours after the first attempt.
- Generate a fresh key per attempt. Reusing a key is only correct when the request body is byte-identical and you want the same server response.
Replay behaviour
Retrying with the same key and the same body replays the original response:- If the original succeeded (2xx), you get the exact same 2xx body back, with
Idempotent-Replayed: truein the response headers. - If the original returned an error, only the first response is stored — non-2xx responses are not replayed. Retrying is a fresh attempt.
409 idempotency_mismatch. Either use a new key or send the identical body.
Retrying while the original attempt is still running (concurrent duplicates) fails with 409 idempotency_in_flight and a Retry-After header — wait, then retry.
402 on publish never binds the key
A402 from POST /v2/surveys/{id}/publish (insufficient_credits, card_declined, card_authentication_required) does not bind the Idempotency-Key. The survey stays as a draft, nothing was charged, and you can publish again — but you must use a new Idempotency-Key on the retry. The old one is unreserved.
Credit-pack order retry guarantee
Once you start a credit-pack checkout withPOST /v2/orders, its identity and parameters are frozen for 24 hours on the same Idempotency-Key. If a network hiccup drops the response, retry with the same key and body to resume the same order and Stripe Checkout Session — you’ll get back the same checkoutUrl and orderId and won’t double-charge the buyer.
Two things end that guarantee:
- The 24-hour window expires.
- You send a different body under the same key (which fails
409 idempotency_mismatchbefore charging anything).
