Resource add-ons API
A resource add-on is an add-on backed by a bookable resource, such as a party room or a sauna. It has its own time window before, during or after the main activity, and its own duration and pricing rules.
The link between an add-on and a resource is a resource add-on configuration. You manage configurations with the admin API, and you can read them and check their availability with the public API.
You cannot currently add a resource add-on to a booking through the public API. The booking widget hides the step, and resource add-ons are not included in the booking price. Use the endpoints on this page to set up configurations and to check availability only.
Admin: manage configurations
All admin endpoints need a staff JWT with the admin:write permission.
| Method | Path | Description |
|---|---|---|
GET | /api/v1/admin/addons/{addonId}/resources | List the configurations for an add-on. |
POST | /api/v1/admin/addons/{addonId}/resources | Link a resource to an add-on. |
GET | /api/v1/admin/addons/{addonId}/resources/{configId} | Get one configuration. |
PATCH | /api/v1/admin/addons/{addonId}/resources/{configId} | Update a configuration. |
DELETE | /api/v1/admin/addons/{addonId}/resources/{configId} | Remove a configuration. |
GET | /api/v1/admin/resources/{resourceId}/addon-configs | List the configurations that use a resource. |
The list endpoint accepts the query parameters resourceId, isActive and includeResource.
Configuration fields
| Field | Type | Description |
|---|---|---|
resourceId | string | Required on create. The resource that is booked. |
durationMode | string | FIXED (default), SELECTABLE or CUSTOM. See below. |
fixedDurationMins | integer | Duration for FIXED. |
selectableDurations | integer[] | Allowed durations for SELECTABLE, for example [30, 60, 90]. |
minDurationMins | integer | Shortest duration for CUSTOM. |
maxDurationMins | integer | Longest duration for CUSTOM. |
durationStepMins | integer | Step for CUSTOM, for example 15. |
pricingMode | string | FLAT, PER_HOUR, PER_PERSON or COMPOSITE. See below. |
flatPrice | decimal | Price for FLAT. |
perHourPrice | decimal | Hourly price for PER_HOUR. |
perPersonPrice | decimal | Per-person price for PER_PERSON and COMPOSITE. |
basePrice | decimal | Base fee for COMPOSITE. |
allowBefore | boolean | The resource can be booked before the activity. |
allowDuring | boolean | The resource can be booked during, or overlapping, the activity. |
allowAfter | boolean | The resource can be booked after the activity. |
bufferMinsBefore | integer | Set-up time blocked before the resource window. |
bufferMinsAfter | integer | Clean-up time blocked after the resource window. |
maxCapacity | integer | Capacity override. Leave empty to use the resource's own capacity. |
isActive | boolean | Inactive configurations are not offered. |
sortOrder | integer | Display order. |
Duration modes
| Mode | The customer... | Fields used |
|---|---|---|
FIXED | gets one fixed duration. | fixedDurationMins |
SELECTABLE | picks one duration from a list. | selectableDurations |
CUSTOM | picks any duration in a range and step. | minDurationMins, maxDurationMins, durationStepMins |
Pricing modes
| Mode | Price |
|---|---|
FLAT | flatPrice, whatever the duration. |
PER_HOUR | perHourPrice × duration in hours. |
PER_PERSON | perPersonPrice × party size. |
COMPOSITE | basePrice + perPersonPrice × party size. |
Public: read configurations and availability
These endpoints need no login. Send your tenant ID in the x-tenant-id header.
| Method | Path | Description |
|---|---|---|
GET | /api/v1/availability/resource-addons/configs | Configurations linked to a product, without availability. |
GET | /api/v1/availability/resource-addons | Configurations that have capacity and a free window for a slot. |
GET | /api/v1/availability/resource-addons/{configId}/time-windows | The time windows you can choose for one configuration. |
List configurations for a product
GET /api/v1/availability/resource-addons/configs?productId=p_demo
x-tenant-id: t_demo
The only query parameter is productId. The response is { "resourceAddons": [...] }; the item shape is described below.
List available resource add-ons for a slot
GET /api/v1/availability/resource-addons?productId=p_demo&slotId=sl_123&partySize=8&activityStartsAt=2026-10-15T14:00:00Z&activityEndsAt=2026-10-15T15:00:00Z
x-tenant-id: t_demo
| Parameter | Required | Description |
|---|---|---|
productId | Yes | The main activity's product. |
slotId | Yes | The selected slot. |
partySize | Yes | Number of people. |
activityStartsAt | Yes | Activity start, ISO 8601. |
activityEndsAt | Yes | Activity end, ISO 8601. |
Response:
{
"resourceAddons": [
{
"configId": "rac_party_room",
"addonId": "addon_party_room",
"addonName": "Party Room",
"resourceId": "res_party_room_1",
"resourceName": "Party Room A",
"resourceType": "ROOM",
"durationMode": "SELECTABLE",
"selectableDurations": [60, 90],
"pricingMode": "FLAT",
"displayPrice": "€120",
"flatPrice": 120,
"allowBefore": true,
"allowDuring": false,
"allowAfter": true,
"bufferBeforeMins": 15,
"bufferAfterMins": 15,
"maxCapacity": 20,
"partySize": 8,
"capacityAvailable": true,
"availableWindows": 4
}
]
}
Get time windows for one configuration
GET /api/v1/availability/resource-addons/{configId}/time-windows?activityStartsAt=2026-10-15T14:00:00Z&activityEndsAt=2026-10-15T15:00:00Z&partySize=8
x-tenant-id: t_demo
| Parameter | Required | Description |
|---|---|---|
activityStartsAt | Yes | Activity start, ISO 8601. |
activityEndsAt | Yes | Activity end, ISO 8601. |
partySize | Yes | Number of people. |
excludeBookingId | No | A booking to ignore when checking for conflicts. |
Response:
{
"configId": "rac_party_room",
"resourceName": "Party Room A",
"addonName": "Party Room",
"timeWindows": [
{
"startsAt": "2026-10-15T15:00:00Z",
"endsAt": "2026-10-15T16:00:00Z",
"durationMins": 60,
"position": "AFTER",
"price": 120,
"available": true
}
]
}
position is BEFORE, DURING, AFTER or OVERLAP. When available is false, conflictReason says why.