Packages sell several things as one product at one price: a stay with a room plus meals, a sauna hour or tickets, or a bundle without a room. Use these endpoints to list packages and show one with everything it contains.
All endpoints are scoped to the organization that owns the API key:
/store/v0
List packages
GET /store/v0/packagesReturns the packages that are public, on sale now and bookable (no closed_reason).
Response
{
"packages": [
{
"public_id": "9630b448-147c-424a-8ed5-f9d41cdc7421",
"name": "Autumn calm at Jølstraholmen",
"short_description": "3–10 nights with a private sauna hour included.",
"description": "…",
"kind": "stay",
"asks_for_day": false,
"dates_label": "3–10 nights",
"nights_min": 3,
"smallest_party": 1,
"largest_party": 6,
"room_choices": "Lodgen or Deluxe elvasus",
"price_label": "Depends on your dates",
"price_unit_label": null,
"price_range": null,
"thumbnail_url": "https://assets.servos.dk/derivations/media/thumbnail/400/400/…",
"medias": [],
"components": [
{
"public_id": "f7fc65b6-f266-408f-b5c5-5bbf8f344022",
"kind": "room",
"name": "Lodgen or Deluxe elvasus",
"inclusion": "included",
"booking_role": "room",
"quantity_rule": "per_stay",
"quantity_label": "once per booking",
"guest_picks": true,
"price": null,
"prices_vary": false,
"thumbnail_url": "https://assets.servos.dk/derivations/media/thumbnail/400/400/…",
"options": [
{
"public_id": "d031cf87-a78d-4b6e-997b-bc8a6ff37f41",
"name": "Lodgen",
"capacity": 6,
"capacity_label": "Up to 6 guests",
"accommodation_id": "e212ccd5-aa5d-4603-936f-0a0151cc0ebd",
"service_id": null,
"service_variant_id": null,
"price": null,
"thumbnail_url": "https://assets.servos.dk/derivations/media/thumbnail/400/400/…"
}
]
},
{
"public_id": "1054ad56-72da-4149-bc41-4216887d98be",
"kind": "service",
"name": "Private sauna",
"inclusion": "included",
"booking_role": "included",
"quantity_rule": "per_stay",
"quantity_label": "once per booking",
"guest_picks": false,
"price": null,
"prices_vary": false,
"thumbnail_url": null,
"options": [
{
"public_id": "5a74bfac-5a61-46bf-b830-fd2c71087ce7",
"name": "Private sauna",
"capacity": 6,
"capacity_label": "Up to 6 guests",
"accommodation_id": null,
"service_id": "c12037f4-12da-4f9d-8462-30ccb754661f",
"service_variant_id": "5b603b73-47e6-41fb-a298-5abfbaf2a67c",
"price": null,
"thumbnail_url": null
}
]
},
{
"public_id": "99f1cb76-4180-456b-b880-b8e09c600d84",
"kind": "addon",
"name": "Breakfast",
"inclusion": "extra",
"booking_role": "extra",
"quantity_rule": "per_guest_night",
"quantity_label": "per guest per night",
"guest_picks": false,
"prices_vary": false,
"price": {
"cents": 25000,
"currency": "NOK",
"amount": 250.0,
"formatted": "250 NOK",
"abbreviated": "250 NOK"
},
"thumbnail_url": null,
"options": [
{
"public_id": "96fa5303-146e-4a06-9ce6-8cb4467c7373",
"name": "Breakfast",
"capacity": null,
"capacity_label": null,
"accommodation_id": null,
"service_id": null,
"service_variant_id": null,
"price": {
"cents": 25000,
"currency": "NOK",
"amount": 250.0,
"formatted": "250 NOK",
"abbreviated": "250 NOK"
},
"thumbnail_url": null
}
]
}
],
"component_groups": [
["f7fc65b6-f266-408f-b5c5-5bbf8f344022"],
["1054ad56-72da-4149-bc41-4216887d98be"],
["99f1cb76-4180-456b-b880-b8e09c600d84"]
]
}
]
}Get a package
GET /store/v0/packages/{public_id}Returns { "package": { … } } with the fields of the list plus a stay's check_ins. A private package opens here and in the search and cart endpoints, but is not in the list, so you can sell it by direct link. A draft returns 404.
Package object reference
| Field | Type | Description |
|---|---|---|
public_id | string | Package public identifier |
name | string | Package name |
short_description | string | null | One-line summary |
description | string | null | Full description, plain text with line breaks |
kind | "stay" | "bundle" | A stay books a room for a range of nights. A bundle has no room and no dates. |
asks_for_day | boolean | Bundles only. The guest picks one day, and its services are booked on that day. Send it as check_in_date; closed days lists the days to disable. |
dates_label | string | How long the stay is, for example "2 nights" or "3–10 nights" |
nights_min | integer | Stays only. Shortest stay in nights. |
check_ins | check-in[] | Stays, from GET /store/v0/packages/{public_id} only. Every date a stay can start on, from today for a year, with the nights it can last. Dates not listed can't be booked. |
smallest_party / largest_party | integer | The fewest and most guests the package takes. Offer party sizes between them. |
room_choices | string | null | Stays where the guest picks the room: the rooms to choose from, like "Lodgen or Deluxe elvasus" |
price_label | string | null | The price as a sentence, for example "Depends on your dates" or "2,345 NOK per guest per night" |
price_unit_label | string | null | The unit of a fixed price, for example "per guest per night" |
price_range | object | null | { "min": money, "max": money, "from": boolean } for fixed-price packages; null at item prices. Show min as "From …" when from. |
closed_reason | string | null | Why nobody can book the package now, like "Not on sale" or "Jazz has ended". Show it instead of the booking form. |
today | date (YYYY-MM-DD) | The venue's date today. Dates before it can't be booked. |
event_starts_on / event_ends_on | date | null | Bundles with an event only. The event's first and last day; the bundle books its services on them. |
thumbnail_url | string | null | Cover image |
medias | media[] | Package images, see Types |
components | component[] | What the package contains, in display order |
component_groups | string[][] | Every component's public ID in display order, grouped. See Component groups. |
A check-in is { "date": "YYYY-MM-DD", "min_nights": 3, "max_nights": 10, "nights": [3, 4, …, 10] }. nights lists every stay length that can start on date; the check-out is date plus one of them. The rules behind it (season, closed dates, start days, shortest and longest stay, and which rooms are free) are applied on the server, so the calendar only needs these dates.
Component
| Field | Type | Description |
|---|---|---|
public_id | string | Component public identifier. Use it in choices, extra_component_ids and slots. |
kind | string | room, addon, product, service, service_addon or ticket. A service_addon is booked onto the booking of a service component in the same package |
name | string | Display name; lists the options when there are several |
inclusion | "included" | "extra" | Included components are in the package price. Extras are optional and cost their own price on top. |
booking_role | string | Where the booking form shows it: room (the quotes), pick (the guest chooses an option), included or extra (a tick box) |
quantity_rule | string | How many are booked: per_stay, per_guest, per_night or per_guest_night |
quantity_label | string | The quantity rule in English, like "per guest per night" |
guest_picks | boolean | true when the guest chooses one of several options |
asks_for_time | boolean | true for services: the guest picks a time, sent in slots |
thumbnail_url | string | null | The first option's image |
price | money | null | Extras only. The cheapest option's price per unit. |
prices_vary | boolean | true when the options cost different amounts, so show price as "From …" |
options | option[] | The items the component can book |
Option
| Field | Type | Description |
|---|---|---|
public_id | string | Option public identifier. Use it as the value in choices. |
name | string | Item name |
capacity | integer | null | Rooms and services: how many guests it has space for |
capacity_label | string | null | capacity in English, like "Up to 6 guests" |
accommodation_id | string | null | Rooms only. The accommodation's public ID. |
service_id / service_variant_id | string | null | Services only. Use them with Service availability to list times. |
price | money | null | Extras only. This option's price per unit. |
party_seats | boolean | Services only. true when each guest takes a seat, so a time needs as many free seats as the party. |
starts_at / starts_label | string | null | Tickets only. The event's start, as a timestamp and as a label in the venue's time zone, like "Thu 8 Oct, 20:00". |
Component groups
component_groups lists every component's public ID in display order, in
groups. Components with booking_role included that a guest can't tell apart
share a group: show it once with its count, like "3 × Packed lunch". Every other
component, each extra and pick list among them, has a group of its own. In a
group of services, each component still takes its own time in slots.
Booking a package
- Show the package with
GET /store/v0/packages/{public_id}. - Price it for the guest's dates and party with the package search.
- For every service component the guest books, list times with Service availability using the option's
service_idandservice_variant_id, the search'sservice_starts_onandservice_ends_on, and the option'sseatsfrom the search. - Add it to a cart with Cart packages.