Skip to content

Idempotency

Networks fail. If a request times out, you can’t tell whether it ran. Send an Idempotency-Key header and you can retry it safely: the first request runs, and every retry with the same key gets the same response without running it again.

Use a new key for each thing you mean to do, such as schedule-october or a UUID. Keys are up to 255 letters, digits, _, ., : and -.

Terminal window
curl -X POST "$BASE/segments" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: segment-october-readers' \
-H 'Content-Type: application/json' -d '{"name":"October readers","definition":{"all":[{"type":"opened","withinDays":30}]}}'

Retry it with the same key and body, and you get the same segment back, with the header idempotent-replayed: true. No second segment is created.

Terminal window
curl -X POST "$BASE/segments" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: segment-october-readers' \
-H 'Content-Type: application/json' -d '{"name":"October readers","definition":{"all":[{"type":"opened","withinDays":30}]}}'

Check it worked: both responses have the same id, and GET $BASE/segments lists it once.

  • A key is kept for 24 hours, then it can be used again.
  • The same key with a different method, path or body gives 409 idempotency_conflict.
  • While the first request is still running, a retry gets 409 idempotency_conflict saying so. Wait a moment and retry again: it never runs twice.
  • A missing key where one is required, or a key with other characters, gives 422 validation_failed.
  • A 5xx or 429 response isn’t kept, so retrying with the same key runs the request again.
  • Idempotency records are stored in your own app table, never in our account: even a hash of a body with an email address in it could be reversed.
Terminal window
# Expect 409 idempotency_conflict
curl -X POST "$BASE/segments" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: segment-october-readers' \
-H 'Content-Type: application/json' -d '{"name":"September readers","definition":{}}'

These change what’s sent, so they need a key:

  • POST /campaigns/{id}/test
  • POST /campaigns/{id}/schedule
  • POST /campaigns/{id}/resume

These accept one, and we recommend it:

  • POST /contacts
  • POST /contacts/batch
  • POST /segments
  • POST /templates
  • POST /templates/{id}/versions
  • POST /campaigns
  • POST /imports/csv
  • POST /imports/mailchimp
  • POST /imports/{id}/commit
  • POST /exports

When you retry after 503 dependency_unavailable or a timeout, use the same key.