Skip to main content

Booking Groups API

The Booking Groups API provides endpoints for creating and managing multi-activity booking groups. A booking group coordinates multiple bookings into a single unit with shared payment, notifications, and lifecycle management.

Overview

Booking groups allow combining multiple activities (potentially across different sites) into a single event. For example, a corporate team day might include Hohtogolf at 14:00 and Laserareena at 15:30, managed as one booking with a single invoice.

Key concepts:

  • BookingGroup — coordinates multiple child bookings
  • Child Booking — a standard booking linked to a group via groupId
  • Group Status — derived from child booking states (DRAFT → HOLD → CONFIRMED → COMPLETED)
  • Group Payment — single payment transaction covers all activities

Public Endpoints

Create Group Hold

Creates a booking group from a package with atomic holds for all activities. All holds share the same expiry time — if any activity can't be held, the entire operation rolls back.

POST /api/v1/booking-groups/hold

Request Body:

{
"packageId": "pkg_abc123",
"groupType": "PACKAGE",
"partySize": 20,
"customerName": "Acme Corp",
"customerEmail": "events@acme.com",
"customerPhone": "+358501234567",
"slotSelections": [
{
"productId": "p_hohtogolf",
"siteId": "s_redi",
"slotId": "slot_1400"
},
{
"productId": "p_laser",
"siteId": "s_redi",
"slotId": "slot_1530"
}
]
}

Request Fields:

FieldTypeRequiredDescription
packageIdstringNoPackage to create group from (null for custom)
groupTypestringYesPACKAGE or CUSTOM
partySizenumberYesTotal group size (1-500)
customerNamestringNoCustomer or company name
customerEmailstringNoCustomer email for confirmations
customerPhonestringNoCustomer phone number
slotSelectionsarrayNoSlot picks for each activity

Response:

{
"id": "grp_xyz789",
"reference": "GRP-20260415-001",
"status": "HOLD",
"holdExpiresAt": "2026-04-15T14:15:00.000Z",
"bookings": [
{
"bookingId": "bk_001",
"status": "hold",
"slotId": "slot_1400",
"startsAt": "2026-04-15T14:00:00.000Z",
"endsAt": "2026-04-15T15:00:00.000Z"
},
{
"bookingId": "bk_002",
"status": "hold",
"slotId": "slot_1530",
"startsAt": "2026-04-15T15:30:00.000Z",
"endsAt": "2026-04-15T16:30:00.000Z"
}
]
}

Get Group Detail

GET /api/v1/booking-groups/:id

Returns group info with all child bookings and pricing.

Confirm Group

POST /api/v1/booking-groups/:id/confirm

Request Body:

{
"paymentMethod": "STRIPE"
}
FieldTypeRequiredDescription
paymentMethodstringYesSTRIPE, PAYTRAIL, INVOICE, or COMP

For STRIPE, the response includes a stripeClientSecret for completing payment via Stripe Elements on the frontend. The bookings remain in HOLD until the Stripe webhook confirms payment.

For INVOICE and COMP, bookings are confirmed immediately.

Admin Endpoints

All admin endpoints require Bearer token authentication and manage_bookings permission.

List Booking Groups

GET /api/v1/admin/booking-groups

Query Parameters:

ParameterTypeDescription
statusstringFilter by group status
customerEmailstringSearch by customer email

Create Booking Group

POST /api/v1/admin/booking-groups

Creates a group in DRAFT status. For custom groups, add bookings individually afterwards.

Get Booking Group

GET /api/v1/admin/booking-groups/:id

Update Booking Group

PATCH /api/v1/admin/booking-groups/:id

Update customer info, internal notes.

Delete Booking Group

DELETE /api/v1/admin/booking-groups/:id

Only DRAFT groups can be deleted.

Add Booking to Group

POST /api/v1/admin/booking-groups/:id/bookings

Request Body:

{
"productId": "p_hohtogolf",
"siteId": "s_redi",
"slotId": "slot_1400",
"partySize": 20
}

Only works for DRAFT groups. The product must belong to the specified site, and the slot must exist for the product.

Remove Booking from Group

DELETE /api/v1/admin/booking-groups/:id/bookings/:bookingId

Only works for DRAFT groups.

Create Group Hold

POST /api/v1/admin/booking-groups/:id/hold

Creates atomic holds for all bookings in the group with synchronized expiry. Fails entirely if any booking's slot has insufficient capacity.

Calculate Pricing

POST /api/v1/admin/booking-groups/:id/calculate-pricing

Calculates and applies pricing to the group. Returns:

{
"grandTotal": 1100.0,
"subtotal": 1100.0,
"taxTotal": 280.5,
"pricingMethod": "BUNDLE_PER_PERSON",
"allocations": [
{
"bookingId": "bk_001",
"allocatedSubtotal": 567.74,
"taxAmount": 144.77,
"allocatedTotal": 712.51
}
]
}

Confirm Group

POST /api/v1/admin/booking-groups/:id/confirm

Request Body:

{
"paymentMethod": "INVOICE",
"customTotal": 900.0,
"customPricingReason": "Returning customer discount"
}
FieldTypeRequiredDescription
paymentMethodstringYesINVOICE, COMP, STRIPE, or PAYTRAIL
customTotalnumberNoOverride total (requires reason)
customPricingReasonstringNoRequired when customTotal is set

Cancel All Bookings

POST /api/v1/admin/booking-groups/:id/cancel

Request Body:

{
"reason": "Client budget cut"
}

Cancels all non-terminal bookings in the group and releases capacity.

Group Status Lifecycle

DRAFT → HOLD → CONFIRMED → COMPLETED
↓ ↓ ↓
EXPIRED EXPIRED PARTIALLY_CANCELED → CANCELED
StatusMeaning
DRAFTGroup created, activities being added
HOLDAll bookings have active holds
CONFIRMEDPayment processed, all bookings confirmed
PARTIALLY_CANCELEDSome bookings cancelled, others still active
CANCELEDAll bookings cancelled
COMPLETEDAll bookings completed or in terminal state
EXPIREDHold expired before confirmation

Group status is derived from child booking states and updates automatically when any child booking's status changes.

Payment Flow

Invoice Payment

  1. Admin creates group and adds activities
  2. Admin calculates pricing
  3. Admin creates holds (atomic)
  4. Admin confirms with paymentMethod: "INVOICE"
  5. All bookings confirmed immediately, payment transaction created as PENDING
  6. Confirmation email sent to customer

Stripe Payment (Customer Flow)

  1. Customer selects package, picks slots, enters contact info
  2. System creates atomic holds
  3. Customer pays via Stripe checkout
  4. Stripe webhook fires → all bookings confirmed automatically
  5. Confirmation email sent

Complimentary (Comp)

Confirms all bookings with zero payment. Useful for partner events.