Skip to navigation

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’s priceDelta.
  • Multi-admission ticket component — basePrice is carried once, on the default admission’s datePrices row. A non-default admission’s priceDelta is 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’s priceDelta across the admissions the customer is buying.
  • Non-admission component (coupon, fee, etc.) — the per-unit price before discounts is the basePrice from its datePrices row for the date. No priceDelta applies; the component doesn’t appear in timeSlots[].

Then apply the row’s discounts to that sum:

perUnit = (basePrice + priceDelta - packageDiscountAmount)
× (1 - packageDiscountPct / 100)
× (1 - priceListDiscountPct / 100)

Multiply by items[].quantity to get each component’s contribution to the package total, then sum across components.

What the price fields carry:

  • basePrice is 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.
  • priceDelta is the per-slot dynamic adjustment (fixed, relative, or percentage), computed against that base.
  • priceListDiscountPct is the line discount from the price list, in percent. It is the same number getCapacity returns as discountPct.
  • packageDiscountPct and packageDiscountAmount are 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 priceListDiscountPct is 0 whenever a package discount is set.
  • A package configured with both a percentage and an amount gets neither. Both package* fields are 0, and priceListDiscountPct applies as usual.
  • When the package sets its own unit price for the component, the price list is not consulted, so priceListDiscountPct is 0.

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. maxCapacity and remainingCapacity are omitted. Render as “Available” / “Unlimited” — there is no number to display.
  • Any other value — maxCapacity and remainingCapacity are both present. remainingCapacity of 0 means sold out. The numbers’ semantics differ by mode (e.g. sales counts initial sales, admitted counts admitted entries) — interpret with capacityControl for 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:

maxCapacityremainingCapacity
This endpoint405
Capacity webhook10065

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 in admissions[], in datePrices[] with the default admission’s code, and in timeSlots[].
    • 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 empty admissions array, and in datePrices[] with admissionCode: "" (blank). They never appear in timeSlots[] — there’s no schedule to attach to.
  • 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 — use getCapacity for personalized pricing.
  • No quantity — defaults to 1; the caller multiplies by items[].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 getCapacity concern at point-of-purchase. Cancelled slots and slots not marked visible-on-web are excluded.
  • Elapsed slots are not filtered — a fromDate in the past returns past slots. Compare each slot’s startDate/startTime against the matching admission’s admissionLocalTime to 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

x-np-api-keystring
API Key authentication via header

Path parameters

tenantstringRequired

Your Entra Tenant ID. More details.

environmentstringRequired

Your Business Central Environment. More details.

companystringRequired

Your Business Central Company. More details.

Headers

x-api-versiondateOptional

Used for API versioning. More details.

Query parameters

itemNumberstringRequired
An item or product number defined in the ticketing system
fromDatedateOptional

Start of the date range (inclusive), YYYY-MM-DD. Defaults to today.

toDatedateOptional

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.

withPricebooleanOptional

When true, the response includes the datePrices array (per-date basePrice and discount fields) and a priceDelta on each time slot. Defaults to false.

withCapacitybooleanOptional

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.

itemNumberstring
An item or product number defined in the ticketing system
itemslist of objects
timeSlotslist of objects
datePriceslist of objectsOptional