Skip to main content
The Public Booking API lets you build custom booking flows or embed a fully functional booking experience on your own website without using the hosted booking page.

Two ways to integrate

Pick the path that matches what you’re building:

Public Booking API

Build a custom booking UI: read the business’s services and pricing, show real availability, and create scheduled orders or leads. This is what the rest of this reference documents.

Website lead capture

Just want website form submissions to land in the CRM as leads? Copy the ready-made embed snippet from Settings → Website Leads — no custom code required.
The Public Booking API uses a per-tenant token for access control. There are no API keys or bearer tokens to manage.

Authentication & tokens

Every endpoint is scoped by a token in the URL path — there is no Authorization header. Two kinds of token are accepted, and either works on every endpoint: The token must match ^[a-zA-Z0-9_-]{1,255}$. A malformed token returns 400 invalid_token; a well-formed token that doesn’t resolve to a tenant with booking enabled returns 404 not_found.
The booking slug and lead token are public by design — they appear in your page source. They only grant access to the public booking endpoints for one workspace; they cannot read or modify any other CRM data. Never put a secret CRM credential in front-end code.

Base URL

How it works

All booking API endpoints share the same path prefix:
Replace {token} with your booking slug or lead token. The three endpoints cover the full booking flow:

Get config

Fetch services, body types, pricing, and page branding.

Get availability

Return open time slots for a given date.

Submit booking

Create an order or lead from customer input.

Rate limiting

The submit endpoint is rate limited to 5 requests per 10 minutes per IP address to prevent abuse. All other endpoints are unrestricted.

CAPTCHA requirement

The submit endpoint requires a Cloudflare Turnstile CAPTCHA token in the request body (the turnstile_token field). Add the Turnstile widget to your page and pass the token when submitting.
The booking page token is separate from Cloudflare Turnstile. Your Turnstile site key is configured by Cloudflare — the booking token comes from your CRM settings.

Order vs. lead creation

When a booking is submitted, the CRM creates either an order or a lead depending on how the tenant has configured their booking page: Either way, a successful submit returns { "success": true, "confirmation_message": ... }. The record (order or lead) appears in the business’s workspace immediately.

End-to-end integration flow

A complete custom booking integration walks through the three endpoints in order. The config call gives you everything to render the form; availability narrows it to a bookable slot; submit creates the record.
1

Fetch config

GET /config once on page load. Use the response to render your service list, vehicle body-type selector (for auto businesses), currency, and branding. Cache it for the session — it rarely changes.
2

Render services and body types

Build the form from services[] (id, name, base_price, estimated_duration) and, for auto businesses, body_types[] (id, name, surcharge_percent). Compute the displayed price as base_price × (1 + surcharge_percent/100) when a body type is selected.
3

Fetch availability

When the customer picks a date, call GET /availability?date=YYYY-MM-DD&service_ids=.... Pass the selected service IDs so slot length matches the real job duration. Render the returned slots[]; an empty array means no openings that day.
4

Submit the booking

Collect a Turnstile token, then POST /submit with the customer object, service_ids, the chosen slot start as date, and optional vehicle/membership/notes. On 200, show confirmation_message.
5

Handle errors

Map the documented error codes to user-facing messages — most importantly 409 slot_unavailable (the slot was taken while the customer filled the form; re-fetch availability) and 429 too_many_requests (rate limited; ask them to retry shortly).
A minimal end-to-end implementation in the browser:
End-to-end flow

Security model

The booking API is intentionally public — it’s meant to be called from a customer’s browser on any domain — so it does not rely on a secret API key. Instead, several layers work together to keep it safe to expose: Because of these layers, the endpoints safely send Access-Control-Allow-Origin: * — they can be called from any domain, which is what a public booking widget requires. The wide-open CORS header is not the security boundary; the token, Turnstile, rate limiting, and server-side validation are. Treat the booking token as public (it’s visible in your page source by design) and never put any secret CRM credential in front-end code.