Appearance
Holds
A hold is a short reservation while you collect payment. Required before confirm.
Auth: database-backed x-api-key.
Create
http
POST /api/v1/bookings/hold
Content-Type: application/json
x-api-key: <your-api-key>
{
"venue_id": "a0000000-0000-4000-8000-000000000001",
"resource_id": "badminton-court-1",
"slot_start": "2026-09-20T18:00:00.000Z",
"slot_duration_minutes": 60,
"idempotency_key": "hold-9f2a-4c1e-8b7d-1a2b3c4d5e6f"
}idempotency_key is required. customer_phone is optional (membership price at hold time). Omit partner_id.
201: hold_id, slot_id, status: "ACTIVE", hold_expiry_at, price_rupees.
Hold duration is set per venue and can change at any time — the current default for a newly configured venue is 15 minutes. Sandbox: a partner hold lasts at least 15 minutes even where a venue sets a shorter duration, because you take payment on your own checkout before confirm. Production: that minimum arrives with the next production release; until then a partner hold lasts exactly the venue's duration, which can be shorter. Either way, hold_expiry_at is the authoritative deadline for this hold; do not hardcode a duration in your integration. Confirm before hold_expiry_at, or the hold is dead and the slot is released automatically.
Idempotency (hold is special)
Retrying the same key with the same request returns the original hold (201). The same key with a different slot, duration, option, court type or customer returns 409 IDEMPOTENCY_KEY_MISMATCH; a key whose hold expired or was cancelled returns 409 HOLD_EXPIRED / INVALID_HOLD_STATE. See Idempotency.
Release
When the customer abandons checkout:
http
POST /api/v1/partner/holds/{holdId}/cancel
Content-Type: application/json
x-api-key: <your-api-key>
{ "idempotency_key": "cancel-hold-9f2a-…", "reason": "abandoned checkout" }idempotency_key is required. 200: { "message": "Hold released successfully", "hold_id": "…", "status": "CANCELLED" }.
| HTTP | error |
|---|---|
| 400 | IDEMPOTENCY_KEY_REQUIRED |
| 403 | UNAUTHORIZED — not your hold |
| 404 | HOLD_NOT_FOUND |
| 409 | INVALID_HOLD_STATE — not ACTIVE. A retry with the same cancel key after success still returns 200. |
Errors on create
Documented on Booking flow: SLOT_NOT_AVAILABLE (400 or 409), TRANSFORMATION_CONFLICT, VENUE_NOT_AUTHORIZED.
