Idempotent Requests
Safely retry failed requests.
Network errors and timeouts can leave you unsure whether a request reached Neon. An idempotency key lets you retry that request safely: we'll process it at most once, and once it finishes, every retry with the same key gets the original response back.
Send a key
Idempotency keys work on POST and PATCH requests. The header is optional, and requests without it work as before. We ignore the header on other methods, such as GET, which you can already retry safely. A few endpoints don't accept a key, and return 400 IDEMPOTENCY_KEY_NOT_SUPPORTED if you send one.
Generate a unique key for each operation, such as a UUID v4, and send it in the Idempotency-Key header. Keys are 1 to 255 visible ASCII characters: letters, digits and punctuation, with no spaces. Use a new idempotency key for each new operation.
curl --request POST \
--fail-with-body --show-error --include \
--url https://api.neonpay.com/checkout \
--header 'X-Api-Key: <YOUR_API_KEY>' \
--header 'Idempotency-Key: 5f2b6c1e-8d4a-4b7e-9c3f-2a1d0e6b7c84' \
--header 'Content-Type: application/json' \
--data '{ ... }'If the response doesn't arrive, send the exact same request again with the same key. If we already processed the first request, you get its response, with the same status code, body and checkout id. No second checkout is created.
If a retry can happen after your service restarts, or from a different worker, store the key with the operation before you send the first request. Otherwise a retry gets a new key, and we can't tell that it's a duplicate.
How Neon matches a retry
A retry must be the same request as the original:
- the same method and path, including path parameters such as
checkoutId - the same query parameters
- the same JSON body. Key order and whitespace don't matter.
Headers other than Idempotency-Key aren't compared. If you reuse a key with a different request, including on a different endpoint, we'll return a 422 IDEMPOTENCY_KEY_MISMATCH and not process it.
Where keys must be unique
A key only needs to be unique among requests made with the same credentials:
- API key (
X-Api-Key): all API keys of one environment share the same keys. Sandbox and production are separate environments. - Client token (
X-Client-Token): keys are separate for each token. Retry with the same token you used for the original request. See Create a client token.
For example, the same key sent with a sandbox API key and with a production API key is two separate requests.
Retention
We keep a key for 24 hours after its first use. After that, a request with the same key is processed as a new request. Retry within 24 hours.
What Neon stores
Once we start processing a request, we store the response and return it on every retry, including error responses such as 400, 404 and 500. To send a corrected request, use a new key.
We don't store the following responses, so you can retry these requests with the same key:
- requests rejected before processing starts, such as invalid request bodies (
400), authentication failures (401) and rate limits (429) 409 RESOURCE_BUSYresponses, where another request held the resource and nothing was changed.
Errors
| Status | code | Meaning | What to do |
|---|---|---|---|
400 | INVALID_IDEMPOTENCY_KEY | The key is empty, longer than 255 characters, or has a character that isn't visible ASCII. | Fix the key. |
400 | IDEMPOTENCY_KEY_NOT_SUPPORTED | This endpoint doesn't accept an idempotency key. | Send the request without the Idempotency-Key header. |
409 | IDEMPOTENCY_KEY_IN_USE | A request with this key is still being processed. | Retry with the same key after the Retry-After header's number of seconds. |
422 | IDEMPOTENCY_KEY_MISMATCH | The key was already used with a different request. | Use a new key for a new request. A mismatch on a retry usually means the retry isn't identical to the original. |
500 | IDEMPOTENCY_OUTCOME_UNKNOWN | The original request was interrupted. It may or may not have taken effect. | Check the resource's state, for example with Get a checkout, before you send the request again with a new key. |
503 | UNEXPECTED_ERROR | We can't process requests with an idempotency key right now. Nothing was processed. | Retry with the same key after the Retry-After header's number of seconds. |
Retry checklist
- Retry network errors and timeouts with the same key and the same request.
- Back off between retries, and honor
Retry-Afterwhen it's present. - Create a new key for each new operation. Don't reuse a key after you change the request.
- Stop retrying after 24 hours. After that, the key no longer protects against duplicates.
Updated about 5 hours ago

