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_BUSY responses, where another request held the resource and nothing was changed.

Errors

StatuscodeMeaningWhat to do
400INVALID_IDEMPOTENCY_KEYThe key is empty, longer than 255 characters, or has a character that isn't visible ASCII.Fix the key.
400IDEMPOTENCY_KEY_NOT_SUPPORTEDThis endpoint doesn't accept an idempotency key.Send the request without the Idempotency-Key header.
409IDEMPOTENCY_KEY_IN_USEA request with this key is still being processed.Retry with the same key after the Retry-After header's number of seconds.
422IDEMPOTENCY_KEY_MISMATCHThe 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.
500IDEMPOTENCY_OUTCOME_UNKNOWNThe 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.
503UNEXPECTED_ERRORWe 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-After when 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.

Did this page help you?