Search Time Slots
Browse-oriented endpoint for calendar UIs: returns every time slot for an item across a date range, with optional indicative pricing and current capacity. Designed for use cases like a 30-day calendar UI or a realtime capacity check across a date window.
This endpoint is not a replacement for getCapacity — that endpoint
stays as the single-date, at-checkout call carrying customerNumber for personalized
pricing and authoritative capacity validation. Prices here are indicative —
customerNumber and quantity aren’t accepted, so customer-specific pricing, price
ladders, and quantity discounts are not applied. Slot-level dynamic pricing is
applied and surfaces as priceDelta on each time slot. Price-list and package discounts
are returned as separate fields on each datePrices row (see “Per-unit math” below).
Capacity is accurate at the moment of the response but drifts as bookings come in.
Re-validate at the slot the customer actually picks.
Date-range cap
The range cap is 62 days (toDate - fromDate + 1). Larger ranges return 400.
Times are admission-local
All *Date / *Time fields on timeSlots[] are in the admission’s local wall clock —
no timezone offset is attached to the slot fields. Do not parse them as UTC, and do not
compare them to the consumer’s own clock. Each admission’s
admissions[].admissionLocalTime carries the admission’s wall clock at response time
(with offset) — compare slot times against that as the reference. Different admissions
in one response may sit in different time zones. endDate can differ from startDate
for slots that cross midnight.
Per-unit math
basePrice (in datePrices) and priceDelta (on each time slot) are per unit and
carry no discounts. Combine them first, then apply the discount fields from the same
datePrices row. What to combine depends on the component shape:
- Single-admission ticket component — pick a slot, then the per-unit price before
discounts is
basePrice(for that component and date)+the chosen slot’spriceDelta. - Multi-admission ticket component —
basePriceis carried once, on the default admission’sdatePricesrow. A non-default admission’spriceDeltais its incremental contribution, not a standalone price — do not add the base per admission. Per-unit price before discounts =basePrice(default admission’s row, for the date)+ Σchosen slot’spriceDeltaacross the admissions the customer is buying. - Non-admission component (coupon, fee, etc.) — the per-unit price before discounts
is the
basePricefrom itsdatePricesrow for the date. NopriceDeltaapplies; the component doesn’t appear intimeSlots[].
Then apply the row’s discounts to that sum:
Multiply by items[].quantity to get each component’s contribution to the package
total, then sum across components.
What the price fields carry:
basePriceis the price-list price for the date (so it tracks scheduled price-list changes, e.g. seasonal pricing), or the price configured for the component on the package when the package overrides the price list.priceDeltais the per-slot dynamic adjustment (fixed, relative, or percentage), computed against that base.priceListDiscountPctis the line discount from the price list, in percent. It is the same numbergetCapacityreturns asdiscountPct.packageDiscountPctandpackageDiscountAmountare the discount configured on the package for this component — a percentage, or a per-unit amount.
Only one discount applies at a time. At most one of the three discount fields is non-zero on a row:
- A package discount takes the component out of price-list discounting, so
priceListDiscountPctis0whenever a package discount is set. - A package configured with both a percentage and an amount gets neither. Both
package*fields are0, andpriceListDiscountPctapplies as usual. - When the package sets its own unit price for the component, the price list is not
consulted, so
priceListDiscountPctis0.
Capacity semantics
When withCapacity=true, each time slot carries a capacityControl field — one of none,
sales, admitted, or full. Branch on it:
none— capacity is not tracked for this slot.maxCapacityandremainingCapacityare omitted. Render as “Available” / “Unlimited” — there is no number to display.- Any other value —
maxCapacityandremainingCapacityare both present.remainingCapacityof0means sold out. The numbers’ semantics differ by mode (e.g.salescounts initial sales,admittedcounts admitted entries) — interpret withcapacityControlfor accuracy across modes.
capacityControl is per slot, not per admission — the same admission may have
different effective modes on different slots.
Both numbers are the requested ticket product’s share of the slot, so you can render one against the other — a progress bar, “3 of 40 left” — without knowing how the share is configured.
The share is set by Percentage of Adm. Capacity on the ticket’s admission line and defaults to 100, giving the product the admission’s whole capacity. Configured lower, it caps how far that product may sell into the slot. Every ceiling is measured against the slot’s total count, so a ticket sold through one product reduces the remaining figure for all of them.
The Time Slot Capacity Changed webhook reports the admission’s own figures under the same two field names, since it has no ticket product in context. A slot with an admission capacity of 100, a product capped at 40%, and 35 tickets sold on the slot:
Do not combine figures from the two surfaces in one calculation.
Closed slots
A slot carries closed: true when a configured calendar closes the slot’s date. Any
calendar layer — admission calendars, schedule calendars, or the ticket base calendars
on the BOM item and admission — can trigger this. The response merges them into the
single flag; the specific closing calendar is not identified in the payload.
closed is a calendar signal, not a bookability signal. An absent closed means the
date is open per the calendars — it does not mean the slot can be reserved. For
bookability (sold-out, sales window, elapsed), use getCapacity at
point-of-purchase.
v1 inclusion scope
Only mandatory admissions are emitted in v1. Opt-in and opt-out admissions
(optionalAndSelected, optionalNotSelected) and their addon-experience pricing are
out of scope for v1.
Decomposition
The input item is resolved into one or more components, and each ticket component carries one or more admissions:
- Input item → components. For a single ticket item,
items[]has exactly one entry. For a package,items[]has one entry per underlying item in the package. Components are one of two kinds:- Ticket components — items configured as tickets. They appear in
items[]with at least one entry inadmissions[], indatePrices[]with the default admission’s code, and intimeSlots[]. - Non-admission components — items like coupons or fees that are part of the
package but don’t have admissions. They appear in
items[]with an emptyadmissionsarray, and indatePrices[]withadmissionCode: ""(blank). They never appear intimeSlots[]— there’s no schedule to attach to.
- Ticket components — items configured as tickets. They appear in
- Ticket component → admissions. Each ticket component’s
admissions[]lists every admission the ticket grants access to. A simple ticket grants one; a combo ticket grants several. See “v1 inclusion scope” for which admissions are emitted today.
What this endpoint does not do
- No
customerNumber— usegetCapacityfor personalized pricing. - No
quantity— defaults to 1; the caller multiplies byitems[].quantity. - No rolled-up
packagePrice/packageAvailable— the caller composes from per-row data. - No timezone offsets on time fields (see above).
- Slots whose sales window has ended are not filtered here — that’s a
getCapacityconcern at point-of-purchase. Cancelled slots and slots not marked visible-on-web are excluded. - Elapsed slots are not filtered — a
fromDatein the past returns past slots. Compare each slot’sstartDate/startTimeagainst the matching admission’sadmissionLocalTimeto detect elapsed slots.
Consumers can pass scheduleNumber from a timeSlots[] row directly to
createReservation and to getCapacity — same
field name, same value, no translation.
Authentication
Path parameters
Your Entra Tenant ID. More details.
Your Business Central Environment. More details.
Your Business Central Company. More details.
Headers
Used for API versioning. More details.
Query parameters
Start of the date range (inclusive), YYYY-MM-DD. Defaults to today.
End of the date range (inclusive), YYYY-MM-DD. Defaults to fromDate + 30 days. The total span toDate - fromDate + 1 may not exceed 62 days.
When true, the response includes the datePrices array (per-date basePrice and discount fields) and a priceDelta on each time slot. Defaults to false.
When true, each time slot carries capacityControl; if that mode tracks capacity, maxCapacity and remainingCapacity are also present. Defaults to false.
Response
The decomposed item structure, indicative pricing per date (when requested), and the list of slots in the date range.
