Appearance
Idempotency
Network calls fail. Partner mutations are safe to retry if you persist the key.
Where a key is required
| Call | idempotency_key |
|---|---|
POST /bookings/hold | required |
POST /bookings/confirm | required |
POST /partner/holds/{id}/cancel | required |
POST /bookings/{id}/cancel | required |
POST /bookings/{id}/refund | required |
POST /packages/{id}/purchase | required |
POST /waitlist | not used — naturally unique on venue + resource + date + phone |
Missing key on a required call → 400 IDEMPOTENCY_KEY_REQUIRED.
Generate a UUID v4 per logical action in your system. Persist it with that action. Send the same string on every retry until you abandon the action. Then never reuse it.
Scope
Keys are scoped to your partner identity (from the API key), not globally. Two partners may use the same string without colliding. Generate unique keys anyway.
Redis caches the response for one hour. Confirm, cancel, and refund also write a durable row in the same database transaction as the state change. Hold and package purchase have a durable unique index. A retry after a cache flush still replays.
Replay does not re-check venue grants. If a grant is revoked after a mutation succeeded, replaying that mutation still returns the original success.
Confirm, cancel, refund, package purchase
| Situation | Result |
|---|---|
| First request | Executes |
| Same partner + same key + same logical operation | Original success replayed (same ids, no second side effect) |
| Same key used for a different booking, package, customer, or operation (cancel vs refund) | 409 (IDEMPOTENCY_KEY_MISMATCH or package-purchase conflict) |
| Second cancel/refund after the booking is already terminal, without a matching stored key | 409 INVALID_HOLD_STATE |
Hold creation is narrower
Hold does not 409 when you reuse a key with a different slot.
| Situation | Result |
|---|---|
| First hold | 201, new hold_id |
| Same key, same or different slot in the body | 201, the original hold_id — never a second ACTIVE hold |
That is current behaviour, not a bug we will silently change in v1. Do not reuse a hold key across slots. If you need a second hold, generate a new key.
Timeout recipe
text
1. Create UUID, save it on your local booking/hold row.
2. POST with that idempotency_key.
3. If you see 5xx or a timeout, wait briefly and POST the same body again.
4. If you see 4xx (except 409/429), stop. Inspect error.Keep the key outside your HTTP helper. If the helper generates a new UUID per attempt, you have lost idempotency.