Booking API for developers: how to integrate appointment scheduling into your app

Stanislav TyshchenkoEngineeringTutorial11 min readJun 13, 2026
Booking API integration guide for developers

Adding booking to an app sounds simple until you start building. Real-time availability across multiple staff and locations, cart state, payment handling, post-booking management — each piece is more complex than it looks from the outside. A booking API lets you hand off that complexity to a specialist backend and focus on the frontend.

This guide covers what a booking API actually does, what to look for when choosing one, and how the Opencals Storefront API is structured — with working code examples.

What a booking API needs to do

Not all booking APIs are equal. A real-time scheduling API needs to handle several distinct domains:

Services

What can be booked — products, variants, pricing

Availability

Real-time slot calculation across staff + locations

Cart + Checkout

Session state, payments, confirmation

Self-service

Customer reschedule, cancel, history

Some APIs cover only availability lookup and booking creation. You have to wire up the cart, payment, and post-booking management yourself. A complete booking API handles the full flow — which is what determines how much your team actually needs to build.

What to look for in a booking API

1

Full journey coverage

The API should cover the complete customer flow: browse services → pick staff and location → check availability → add to cart → checkout and pay → manage booking. Missing pieces mean you're building or bolting on additional infrastructure.

2

Real-time availability

Availability needs to account for existing bookings, staff working hours, buffer time between appointments, and multi-staff conflicts. This logic is hard to get right. Look for an API that exposes clean availability endpoints rather than raw calendar data you have to process yourself.

3

Multi-staff and multi-location

If your service business has more than one practitioner or site, the API needs to support per-staff schedules, per-location hours, and service-staff assignments. Availability queries need to filter correctly across these dimensions.

4

OpenAPI / TypeScript support

An OpenAPI spec and a typed TypeScript SDK mean you don't have to guess at request/response shapes. Type safety from the API call to the UI is worth a lot in a domain with complex nested objects (booking slots, cart line items, payment states).

5

Idempotent checkout

Payment flows fail in the real world. The checkout endpoint should be idempotent — repeating the same request should not create duplicate bookings or double charges.

6

Webhooks for post-booking events

Your backend often needs to react to booking events: appointment created, order paid, booking cancelled. Signed webhook events let you update your database, send custom notifications, or trigger downstream workflows without polling.

The Opencals Storefront API

The Opencals Storefront API is a REST API for building custom booking experiences. It covers the complete booking flow and is the same API that powers the Opencals Shopify app and dashboard.

Base URL: https://api.opencals.com
Auth: Authorization: Bearer sfk_your_api_key
Format: JSON throughout
Spec: OpenAPI 3.0 — interactive playground at opencals.com/docs

Authentication

API keys are scoped to a single store. You get one from the Opencals dashboard under Settings → API. The key prefix is sfk_ (storefront key).

bash
curl https://api.opencals.com/storefront/products \ -H "Authorization: Bearer sfk_live_abc123"

Customer JWT tokens

Some endpoints (customer self-service: view bookings, reschedule, cancel) require a customer JWT issued by your own auth flow, not the store API key. See the Authentication docs for details on the dual-auth model.

Core endpoints

List services

bash
GET /storefront/products

Returns the service catalog — name, description, duration, pricing, images, associated staff. This is your booking homepage data.

typescript
import { setupOpencals, ProductService } from "@opencals/storefront-sdk"; const opencals = setupOpencals({ apiKey: process.env.OPENCALS_API_KEY }); const { data: products } = await ProductService.listProducts({ opencals }); // products is typed: Product[] // product.variants holds per-variant pricing and duration

Check availability

bash
GET /storefront/appointments/availability ?productId=prod_123 &staffMemberId=staff_456 # optional — omit to show all available staff &locationId=loc_789 # optional for single-location stores &from=2026-07-01 &to=2026-07-07

Returns available time slots grouped by day. The API computes availability server-side — you get back a clean list of { date, slots: [{ start, end, staffMemberId }] } objects.

typescript
import { AppointmentService } from "@opencals/storefront-sdk"; const { data: availability } = await AppointmentService.getAvailability({ opencals, query: { productId: "prod_123", from: "2026-07-01", to: "2026-07-07", }, }); // availability.days is typed: AvailabilityDay[]

Create a cart and add a booking

bash
POST /storefront/cart # create cart → returns cartId POST /storefront/cart/items # add booking to cart

The cart persists server-side. Pass cartId in subsequent requests. A cart can hold multiple bookings — useful for "book haircut + colour" flows.

typescript
import { CartService } from "@opencals/storefront-sdk"; const { data: cart } = await CartService.createCart({ opencals }); const { data: updatedCart } = await CartService.addCartItem({ opencals, body: { cartId: cart.id, productId: "prod_123", variantId: "var_456", staffMemberId: "staff_789", startAt: "2026-07-03T14:00:00Z", }, });

Checkout

bash
POST /storefront/checkout/initiate # returns Stripe payment intent POST /storefront/checkout/confirm # confirm after payment

The checkout endpoint returns a Stripe Payment Intent client secret. You pass that to Stripe Elements or Stripe.js on the frontend to collect payment. On success, confirm the booking. The API is idempotent on the confirm step.

typescript
import { CheckoutService } from "@opencals/storefront-sdk"; // Step 1: initiate checkout const { data: checkout } = await CheckoutService.initiateCheckout({ opencals, body: { cartId: cart.id }, }); // checkout.clientSecret → pass to Stripe Elements // Step 2: after Stripe confirms payment, confirm the booking const { data: booking } = await CheckoutService.confirmCheckout({ opencals, body: { cartId: cart.id, paymentIntentId: checkout.paymentIntentId }, }); // booking is confirmed — appointment is locked in the calendar

Full booking flow

1

Load service catalog

GET /storefront/products — populate your services page. Cache this; it rarely changes.

2

Load staff and locations

GET /storefront/staff-members and GET /storefront/locations — populate the filters on your booking page.

3

Fetch availability

GET /storefront/appointments/availability for the selected service, staff, and date range. Render the calendar.

4

Create cart and add item

POST /storefront/cart to create a cart, then POST /storefront/cart/items. Store the cartId client-side.

5

Initiate checkout

POST /storefront/checkout/initiate. Render the Stripe Elements payment form with the returned clientSecret.

6

Confirm on payment success

After Stripe confirms payment, POST /storefront/checkout/confirm. The booking is created, the slot is blocked, and confirmation emails fire.

TypeScript SDK

Installing the SDK removes the boilerplate:

bash
npm install @opencals/storefront-sdk

Every service maps to a class (ProductService, AppointmentService, CartService, CheckoutService, CustomerService). Every request and response is typed from the OpenAPI spec, so TypeScript catches mistakes at build time rather than runtime.

The SDK ships with Zod schemas for runtime validation and formatting helpers for prices (formatPrice(amount, currency)), durations (formatDuration(minutes)), and timezones.

Open-source example

The fastest way to see the complete API integration in context is the Haar open-source template — a Next.js 15 salon booking website that covers the full flow end to end.

Deploy with Vercel

Clone it from GitHub, add your API key, and you have a working booking site in minutes. The source shows exactly how each part of the API is called in a production Next.js app.

Frequently Asked Questions

Early Access — 3 Months Free

Ready to transform your service business?

Join 150+ businesses already using Opencals. Get 3 months completely free with all features unlocked.

No credit card required
Setup in 10 minutes
Cancel anytime