Appointments from Booking Orbit
How Service, Services and People fields and the Booking Orbit blocks are delivered, and how to take bookings on your own pages with the Booking Orbit SDK.
Reference3 min read
A space connected to a Booking Orbit location under Configuration › Orbit connections has three more field types and four blocks. The entry stores only what was picked, { "id", "name" }. Every answer from the delivery API, the SDK and GraphQL fills in the rest from Booking Orbit's public booking API, kept for at most a minute, and fresh in preview.
Connecting also adds the space's verified domains and preview addresses to the location's allowed websites, so your pages can book in the visitor's browser without the booking widget. The widget is for websites not built with CMS Orbit.
A service
"service": { "id": "6c0000000000000000000001", "slug": "boot-fitting", "name": "Boot fitting", "summary": "Foot scan, try-on and heat moulding, so new boots fit from the first walk.", "category": "Fitting", "image": { "url": "https://images.unsplash.com/photo-1575987116913-e96e7d490b8a?…", "alt": "Boot fitting" }, "durationMinutes": 45, "mode": "in-person", "priceKind": "fixed", "price": 45000, "currency": "NOK", "payment": "none", "deposit": null, "staffIds": ["6c00…a1", "6c00…a2"], "nextAvailable": "2026-11-02T09:00:00.000Z", "bookingUrl": "https://app.bifrostorbit.com/booking/b/northwilds-oslo/boot-fitting", "available": true}- Prices are in minor units, such as øre:
45000is 450 kr.priceKindisfixed,from,freeorhidden.bookingPrice(service, locale)from the SDK formats it. paymentisnone,deposit(withdepositin minor units) orfull. A booking that needs payment comes back with a payment address to send the customer to.nextAvailableis the first free time in the coming two weeks, in UTC, ornull.bookingUrlis the service on Booking Orbit's own booking page, for visitors without JavaScript.available: falsemeans the service is hidden or removed, or Booking Orbit could not be reached and had never answered. The picked name is kept; leave it out or show it without a button.
A person arrives as { id, name, title, bio, photo, available }.
The blocks
Every block also arrives with booking: { baseUrl, location, name, kind, timeZone, currency, locales, address, phone, email, openingHours, policies }. baseUrl and location are what the Booking Orbit SDK needs.
bookingServiceListeyebrow, heading, intro, services, bookLink, limit, and items: the picked services, or every service when none are pickedbookingAppointmentheading, intro, service, confirmation, and items (every service) and team (every person)bookingNextTimesheading, service, bookLink, limit, and times: { startsAt, staffIds }[] for the servicebookingTeameyebrow, heading, intro, staff, and items: the picked people, or everyone who takes bookings| Block | Key | Fields it arrives with |
|---|---|---|
| Services | bookingServiceList | eyebrow, heading, intro, services, bookLink, limit, and items: the picked services, or every service when none are picked |
| Book an appointment | bookingAppointment | heading, intro, service, confirmation, and items (every service) and team (every person) |
| Next available times | bookingNextTimes | heading, service, bookLink, limit, and times: { startsAt, staffIds }[] for the service |
| Meet the team | bookingTeam | eyebrow, heading, intro, staff, and items: the picked people, or everyone who takes bookings |
bookLink is the page the editor chose to book on. Open it with the service, and the time, in the address, such as /services?service=boot-fitting&start=2026-11-02T09:00:00.000Z, so the booking block starts there.
Book on the page
The Book an appointment block gives you what to start with. Take the booking itself with the Booking Orbit SDK, in the browser:
'use client'import { createBookingClient } from '@bifrost-orbit-booking/sdk'import type { CmsBookingLocation } from '@bifrost-orbit-cms/sdk'export async function bookFirstTime(booking: CmsBookingLocation, service: string, customer: { name: string; email: string }) { const client = createBookingClient({ baseUrl: booking.baseUrl, location: booking.location, locale: 'en' }) const slots = await client.slots({ service, timeZone: booking.timeZone, days: 7 }) const time = slots.days.flatMap((day) => day.slots)[0] if (!time) return null const hold = await client.hold({ service, startsAt: time.startsAt }) return client.book({ service, startsAt: time.startsAt, holdToken: hold.token, ...customer })}The answer has the appointment, whose manageUrl ends in its manage token for moving or cancelling, and payment, with a url to send the customer to when the service needs paying online. See Booking Orbit SDK for every call.
Refreshing pages
Booking Orbit does not send content.published when a service or a free time changes. Free times change all the time, so cache pages with Booking Orbit blocks for a minute or two at most, or read times in the browser with the SDK.
Was this page helpful?