Safely retrying API requests with an Idempotency-Key
When your code calls the Mobile Message API, things can go wrong between sending the request and getting the response back — a network blip, a client timeout, a server you couldn't reach. In those moments your application doesn't know whether the request actually went through. The safe assumption is "I don't know, so I should retry" — but if the original request did succeed, retrying will send the same SMS twice and charge you twice.
The Idempotency-Key header solves this. You attach a unique key to each request you make. If the server has already processed a request with that key, it skips the work and returns the original response. You can retry as many times as you want and only one batch will ever be sent.
This is especially important for the POST /v1/messages endpoint when sending large batches (up to 10,000 messages in one call). A duplicate send at that size is a real incident — not just a credit refund conversation but unwanted SMS landing on every recipient twice.
How to use it
Generate a unique string (a UUID is ideal) and send it as a header on your request:
POST /v1/messages
Idempotency-Key: 7f3e9b1a-4c8d-4e2f-9a1b-2c3d4e5f6a7b
Content-Type: application/json
Authorization: Basic ...
{ "messages": [ ... ] }
The key can be any string up to 255 characters. UUIDs are recommended because they're unique by construction and easy to generate in any language.
Generate one key per logical request, not per retry. If you decide to retry the same request, reuse the same key — that's the whole point.
What happens on the first request
Nothing special — your messages are processed and you get back the usual response. Behind the scenes the API stores a copy of the response under your key.
What happens on a retry
If you send the same Idempotency-Key again, the API returns the original response, byte for byte, without re-processing anything. No second batch is sent, no credits are deducted again, no new message IDs are generated. The response also includes a header you can check to confirm it's a replay:
HTTP/1.1 200 OK
Idempotency-Replay: true
Content-Type: application/json
The Idempotency-Replay: true header only appears on replayed responses, not on the original.
What if I reuse a key with a different request body?
If you accidentally reuse a key for a different request (for example, a different set of messages), the API will reject it with HTTP 422:
{ "error": "Idempotency-Key was reused with a different request payload." }
This is a safety check — it tells you that something in your code is wrong, because the same key should never be paired with two different requests. To recover, generate a fresh key for the new request.
How long are keys remembered?
24 hours. After 24 hours from the first successful request, the cached response is deleted. If you retry with the same key after that, it will be treated as a new request and processed again. For practical purposes this means: retry quickly. Most retry policies finish within seconds or minutes, so 24 hours is far longer than you'll ever need.
Scope
Keys are scoped to your API key. If two different customers happen to choose the same idempotency key, they will not collide — each customer's keys are tracked separately.
When to use it
We recommend always sending an Idempotency-Key from automated systems, especially when:
- You're sending large batches (hundreds or thousands of messages per request)
- Your code includes any kind of retry logic
- Network reliability between you and our API is anything less than perfect (it never is)
- The cost of an accidental duplicate send would be significant
It's also useful during development — if you're iterating on integration code and your test runner retries a request, you won't accidentally send the same SMS to a real number twice.
A complete example
curl https://api.mobilemessage.com.au/v1/messages \
-u "YOUR_API_USERNAME:YOUR_API_PASSWORD" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"messages": [
{
"to": "0400000000",
"message": "Hello from Mobile Message",
"sender": "MyBrand"
}
]
}'
In production code, generate the UUID once before your retry loop starts, then reuse it for every retry of that same logical request.
Summary
- Add an
Idempotency-Keyheader (any unique string, ≤255 characters) to your requests. - Reuse the same key when retrying — get the cached response back.
- Different payload with the same key → HTTP 422.
- Keys expire after 24 hours.
- Replayed responses include the
Idempotency-Replay: trueheader.