Skip to content

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.

Confirm before hold_expiry_at (typically ~15 minutes).

Idempotency (hold is special)

Retrying the same key returns the original hold (201), even if the new body describes a different slot. It will not create a second ACTIVE hold. It also will not 409. Do not reuse a hold key across slots. 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" }.

HTTPerror
400IDEMPOTENCY_KEY_REQUIRED
403UNAUTHORIZED — not your hold
404HOLD_NOT_FOUND
409INVALID_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.

Start in the sandbox. Production access is granted after certification.