Idempotency
The Bird API supports opt-in request deduplication via the Idempotency-Key header. This page is the wire contract; for the concepts — why, when, and retry strategy — see Idempotency.
Request header
| Header | Constraints |
|---|---|
| Idempotency-Key | Optional. Any non-empty string up to 255 characters; a UUID v4 is recommended. Honored on POST, PATCH, and DELETE; ignored on GET, HEAD, and OPTIONS. |
Omitting the header skips idempotency entirely — the request is processed normally with no deduplication. An empty key or one longer than 255 characters returns 400 with code E01002 InvalidRequest.
Keys are scoped to your workspace (two workspaces can use the same key string without collision) and retained for roughly 3 hours. After the retention window, a reused key is processed as a fresh request.
Przykład kodu
curl -X POST https://us1.platform.bird.com/v1/email/messages \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{ "from": "hello@example.com", "to": ["user@example.com"], "subject": "Welcome!", "html": "<p>Hi.</p>" }'Response semantics
| Scenario | Response |
|---|---|
| First request with a key | Processed normally; the response (2xx or 4xx) is cached against the key. |
| Same key, identical request | Original status and body replayed, with the Idempotency-Replay: true response header. |
| Same key, different request | 409 — E01005 IdempotencyKeyReuse. Generate a new key for the new request. |
| Same key, original request still in flight | 409 — E01004 RequestInProgress. The lock expires within ~30 seconds; wait and retry. |
| Original request returned 5xx | Not cached — the key unlocks and the retry is processed fresh. |
A replayed response is byte-for-byte the original — same status code, same body — distinguished only by the extra header:
Przykład kodu
HTTP/1.1 202 Accepted
Idempotency-Replay: true"Identical request" covers the method, endpoint, path and query parameters, and the raw request body — any difference, including whitespace, makes it a different request and triggers E01005. Both 409 errors come wrapped in the standard error envelope.
5xx responses are deliberately never cached: a server error means Bird does not know whether the request took effect, and replaying it would permanently block the retry from succeeding. Retry 5xx and timeouts with the same key.
SDK behavior
The official SDKs attach an auto-generated UUID Idempotency-Key to every mutating request, generated once per logical call and reused across all retry attempts of that call. You can supply your own key per call (idempotencyKey in TypeScript, option.WithIdempotencyKey in Go, idempotency_key in Python) when one logical operation spans multiple SDK calls. To detect a replay, read the Idempotency-Replay response header through each SDK's transport-metadata accessor: .withResponse() in TypeScript, option.WithResponseInto in Go, and with_raw_response in Python.
Related
- Idempotency concepts — retry strategy, key design, and the durable email-send guarantee
- Errors — the envelope wrapping E01004 and E01005
- Email messages — the send endpoint, the most common place to use a key
- SDK concepts — automatic key generation and retries