Retries and idempotency

If a network error occurs, you might not receive a response. For example, if a create request times out, you can't tell whether the resource was created. To retry safely, send an Idempotency-Key header and retry with the same key. The API returns the original response and doesn't create anything twice.

curl -X POST https://api.pyas.io/v2/events \
  -H "x-api-key: $PYAS_API_KEY" \
  -H "Idempotency-Key: booking-81723" \
  -H "content-type: application/json" \
  -d '{ "accountId": "'$ACCOUNT_ID'", "title": "Intro call", "startsAt": "2026-10-21T15:00:00Z", "endsAt": "2026-10-21T15:30:00Z" }'

The SDK does this for you on every POST, PATCH, PUT and DELETE request. It generates a key and reuses it when it retries the request. To tie retries to your own records, pass your own key with the idempotencyKey option:

pyas.events.create(body, { idempotencyKey: 'booking-81723' })

How it works

  • Any POST, PATCH, PUT or DELETE request accepts an Idempotency-Key header. A key can be up to 255 printable characters and must be unique for each operation you intend to perform. For example, you can use a booking id or a random UUID.
  • The API stores the response for 24 hours. If you send the same key with the same request, the API returns the stored response with an Idempotent-Replayed: true header.
  • If you send the same key with a different request, the API rejects the request with VALIDATION_IDEMPOTENCY_CONFLICT (422 Unprocessable Entity), because each key identifies a single operation.
  • If you send the same key while the first request is still in progress, the API rejects the request with RESOURCE_CONFLICT (409 Conflict). Wait a moment, then retry.
  • The API doesn't store responses for failures that are worth retrying (5xx and 429 Too Many Requests), so a retry runs the request again.
  • Keys are scoped to your app, so a key sent by another app never conflicts with yours.

What to retry

Every error code indicates whether a retry can succeed. The error codes page lists the retryable value for each code. You can also get these values from the API:

GET /v2/errors
ResponseRetry?
429 RATE_LIMIT_EXCEEDED, PROVIDER_RATE_LIMITEDYes, after Retry-After seconds
5xx, PROVIDER_TIMEOUT, PROVIDER_UNAVAILABLE, CONNECTION_TOKEN_EXPIREDYes, with backoff. Include an idempotency key for writes.
PROVIDER_UNKNOWN_ERROR (502)Once. If it fails again, contact support with the trace id.
No responseYes, with the same idempotency key
Any other 4xxNo. Change the request first. The error's hint explains how.

Increase the wait between attempts (1, 2, 4, 8 seconds, with some random jitter), and stop after a few attempts.

Prevent conflicting updates

Idempotency protects you from duplicates caused by your own retries. To avoid overwriting an update that someone else made, send the event's version in the If-Match header. See Prevent conflicting updates.