Skip to content

Handle errors and retries ​

Decide which failed requests to retry, how, and which to fix instead.

Every status code and the error body are listed in Errors.

Requirements ​

RequirementDescription
Signed requestsWorking signing code — see Authentication
An Idempotency-Key per operationGenerated once per POST, PATCH or DELETE and kept for its retries — see Idempotency

How it works ​

  1. Sort the failure
  2. Retry what is retryable
  3. Fix what isn't

1. Sort the failure ​

You getRetry?Why
No response, a timeout or a connection errorYes, same keyThe request may or may not have run; the key makes a quick retry safe
429, problem-details body Rate limit exceededYes, after a backoffYou sent more than 100 requests in a minute to one resource
429 with retry-after: 2 and an ok: false bodyYes, same key, after 2 secondsThe original request with this key is still being processed
500, 502, 503, 504Yes, same key, with backoffA temporary failure on Zay's side
400NoMalformed JSON, an invalid event batch, or an empty Idempotency-Key
401NoThe signature is wrong or the clock is off — see Sign requests
404NoThe id doesn't exist under your merchant account
413NoThe event batch is too large — split it
422NoThe input failed validation — errors says which field

2. Retry what is retryable ​

  • Keep the Idempotency-Key. A retry must carry the same key as the original, or Zay treats it as a new request.
  • Re-sign every attempt. Build a fresh zay-timestamp and zay-signature each time: a request older than 5 minutes is rejected, and the signature is not part of the idempotency check.
  • Back off. Wait longer between attempts — for example 1, 2, 4, 8 seconds — and add some jitter. Stop after a few attempts and alert someone.
  • Mind the 30-second window. Zay replays the original response only for 30 seconds. A retry later than that runs the request again. For Report a payout that would create a second payout, so check whether the first one exists before retrying late.
  • A 5xx is not replayed. After a server error, the retry runs again even within 30 seconds. For payouts, check whether the payout was created before retrying.

GET requests have no side effects. Retry them freely, with no key.

3. Fix what isn't ​

A 4xx other than 429 won't succeed on retry — the same request gets the same answer. Read detail and errors, fix the request, and send it as a new operation with a new Idempotency-Key:

json
{
  "type": "about:blank",
  "title": "Invalid request parameters",
  "status": 422,
  "detail": "Validation failed: Amount must be greater than 0",
  "instance": null,
  "errors": {
    "amount": ["must be greater than 0"]
  }
}