PUBLIC
Returns available entry timeslots for the given products on the requested date.
Used during checkout to let the customer pick an entry window.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Part of the catalog — The product catalog explains how merchants, products, calendars and timeslots fit together.
Why this endpoint exists
Some venues admit visitors in timed entry windows — a zoo managing crowd flow, a museum with slot capacity. For those products a date alone is not a bookable request; the provider needs to know which window.
This endpoint asks the provider what is open on a given date and returns the windows with their remaining capacity. It exists as its own call because availability is live: it cannot be baked into the catalog cache, and it is the only capacity signal that reflects the provider's current state.
It is a POST because it takes a list of product ids in the body, not because it changes anything. Nothing is reserved or held.
When to call it
Whenever a product in the basket reports requires_timeslot: true, after the customer picks a date and before you create a checkout. The slot they choose becomes the time component of date in Create.
Skip it entirely when every product reports requires_timeslot: false.
Request
curl -X POST https://api.acc.funtrips.io/v2/fulfillment/timeslots \
-H "x-campaign-id: $CAMPAIGN_ID" \
-H "Content-Type: application/json" \
-d '{
"product_ids": ["d4b8f2a1-6c3e-4957-b18d-2f5a9c7e3b04"],
"date": "2026-09-12"
}'| Field | Type | Required | Notes |
|---|---|---|---|
product_ids | UUID[] | Yes | The products the customer intends to buy |
date | date YYYY-MM-DD | Yes | Calendar day — no time component |
Send all timeslotted products from the basket in one call. The returned slots are the ones workable for the set, which is what you need when the customer is buying an adult and a child ticket that must be admitted together.
Response
{
"data": {
"date": "2026-09-12",
"slots": [
{
"entry_from": "2026-09-12T09:00:00Z",
"entry_until": "2026-09-12T10:00:00Z",
"available_capacity": 48
},
{
"entry_from": "2026-09-12T10:00:00Z",
"entry_until": "2026-09-12T11:00:00Z",
"available_capacity": 12
}
]
},
"meta": { "correlation_id": "…" }
}| Field | Meaning |
|---|---|
entry_from | Start of the window. This is the value you send as date at checkout |
entry_until | End of the window — for display: "09:00 – 10:00" |
available_capacity | Units left in the window |
Pass entry_from through verbatim as the checkout date. Do not reformat, re-zone or truncate it — it is the provider's slot key, and a rewritten timestamp may not match a slot.
Filter out slots where available_capacity is below the customer's requested quantity: showing a window with 2 places left to someone buying 4 tickets produces a failure at checkout that you could have prevented here.
An empty slots array is a real answer
slots array is a real answer
Empty slots on arequires_timeslot: trueproduct means that date is not bookable.Block the date and prompt the customer to choose another. Do not fall back to midnight or to "no timeslot": timeslotted providers reject a midnight visit time, and because midnight UTC is 02:00 Amsterdam in summer, the request that does get through books the wrong day.
The same empty response means the opposite for a product with requires_timeslot: false — that product is all-day and the date alone is sufficient. The product flag, not the slot list, tells you which case you are in, so branch on the flag explicitly rather than inferring intent from an empty array.
if (product.requires_timeslot) {
const { data } = await fetchTimeslots([product.id], date);
const usable = data.slots.filter(s => s.available_capacity >= quantity);
if (usable.length === 0) return blockDate(date); // not bookable
return usable; // let the customer pick
}
return null; // all-day: date is enoughTimezones
Slot timestamps are absolute instants with a zone. Convert to the venue's local time for display; send entry_from back unmodified. A slot rendered in the customer's browser timezone will confuse anyone booking from abroad — the venue opens at 09:00 local, not 09:00 wherever the customer is sitting.
Errors
| Status | type | Cause |
|---|---|---|
400 | — | product_ids empty, a malformed UUID, or date not YYYY-MM-DD |
500 | — | Unexpected fault, or the provider could not be reached. Retryable |
Fulfillment errors carry no type field — branch on status. See Error handling.
A date with no availability is 200 with slots: [], not an error.
