Skip to main content
Appointment listings need a time slot before payment can complete. You can choose who owns the calendar UI: Both sit on Tier 1 with the same Tier 2 receipt confirmation path.

Prerequisites

The listing must be ready to book: Configure availability and meeting settings in the Onflay dashboard under Scheduling. Without availability, the public slots endpoints return empty days.

Flow B — Onflay calendar (simplest)

Create a checkout session without appointmentSlot. Onflay shows the availability calendar, then payment — either full-page or overlay.

Full-page hosted

Redirect to checkoutUrl.

Overlay (onflay.js)

Same create call with uiMode: "embedded", then open embedUrl in the overlay (see Overlay checkout):
Notes:
  • Works for single-session and session packs. Packs collect all N times inside hosted/overlay checkout before payment.
  • No Stripe PaymentIntent is created until the buyer confirms their time(s).
  • Hybrid listings show a Virtual / In person choice before times.
  • Sessions still expire after 30 minutes if unpaid.

Flow A — Your app owns the calendar

Step 1 — Fetch availability

Public (no API key) endpoints:
Optional query params:
  • variantId — defaults to the listing’s default variant when omitted
  • durationMinutes — override session length (defaults to the variant duration)
Use available-dates to highlight days on a month calendar, then slots for the chosen day’s open start times. Each slot includes an ISO startsAt you can pass straight into checkout. There is also a range helper when you want several days at once:

Step 2 — Buyer selects a slot

Collect in your UI: For pack variants (sessionCount > 1), the buyer must pick exactly N distinct, non-overlapping times.

Step 3 — Create a checkout session with the slot

For packs, send appointmentSlots (array) instead of appointmentSlot, with exactly sessionCount entries. Onflay validates that each slot is still free, stores the selection on the session, and returns a hosted checkout URL (checkoutUrl). Appointment sessions expire after 30 minutes if unpaid. Always set cancelUrl so the buyer can return to your booking UI if the slot becomes unavailable while they are on the payment page.

Step 4 — Redirect to hosted checkout

Send the buyer to checkoutUrl. They enter payment details; the pending page shows the selected session time(s). If the slot was taken between create and page load, hosted checkout shows a SLOT_UNAVAILABLE state. Prefer linking back via your cancelUrl.

Confirm payment (both flows)

Do not grant access from successUrl alone. Use Tier 2 confirmation:
Or headless: ?headless=true with the secret key (no return token). Poll until paid | failed | expired. After payment succeeds, Onflay creates the appointment row (meeting link / location as configured).

Error contract