POST /v1/sms could send the same message twice.
Robase fixes this with an Idempotency-Key header: the first successful request wins, and subsequent retries with the same key return the original response without doing the work again.
How it works
Pass a unique key per logical send attempt:Idempotent-Replay: true header so you can tell them apart from fresh requests.
Rules
Keys are scoped to the project and the endpoint
Keys are scoped to the project and the endpoint
order-92413-dispatch-sms on /v1/sms is distinct from the same key on /v1/emails. And keys from project A never collide with project B.Keys live for 24 hours
Keys live for 24 hours
After 24 hours the cached response is evicted. If you retry later than that, you get a fresh attempt — so keep retries inside a reasonable window.
Failures are retryable, not cached
Failures are retryable, not cached
We only cache
2xx and 4xx responses. 5xx errors are not cached — the retry with the same key triggers a fresh attempt.Batch rows each need their own key
Batch rows each need their own key
For Per-row keys are namespaced separately from the top-level
POST /v1/sms/batch, put the per-row key on each element:Idempotency-Key header.What to use as a key
A good idempotency key is derived from your data, not random:order-92413-dispatch-sms✅user-42-password-reset-2026-04-17✅uuid.v4()❌ (a fresh UUID per retry is not idempotent — you’ll send twice)
user-42-reset-${Date.now()} bucketed to the minute.