Using API v1? See what changes in v2, or the v1 docs
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,PUTorDELETErequest accepts anIdempotency-Keyheader. 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: trueheader. - 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
| Response | Retry? |
|---|---|
429 RATE_LIMIT_EXCEEDED, PROVIDER_RATE_LIMITED | Yes, after Retry-After seconds |
5xx, PROVIDER_TIMEOUT, PROVIDER_UNAVAILABLE, CONNECTION_TOKEN_EXPIRED | Yes, with backoff. Include an idempotency key for writes. |
PROVIDER_UNKNOWN_ERROR (502) | Once. If it fails again, contact support with the trace id. |
| No response | Yes, with the same idempotency key |
| Any other 4xx | No. 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.