Everything the widget does, your developers can do with HTTP — same flat plan, no “platform tier”. Embed per page, theme by code, listen for events.
Catalog, availability, bookings, gift cards, packages, coupons — a public v1 with CORS and rate limits. Build your own booking surface if you want to.
GET /api/v1/{key}/services
GET /api/v1/{key}/availability?serviceId=…&date=…
POST /api/v1/{key}/bookings
# → { "categories": [{ "name": "Signature Facials", … }],
# "services": [{ "slug": "signature-facials-0",
# "name": "Hydro-Glow Facial",
# "durationMin": 120, "price": "180" }] }
Set a widget's theme programmatically — an agency tool or a site builder can restyle a client's widget without opening the admin. Send a theme object, or just a site URL and the server derives the palette.
PATCH /api/v1/{key}/config
{ "theme": { "accent": "#c9a227", "bg": "#0b0b0f",
"fontHeading": "Playfair Display" } }
# …or let the server look at a website:
PATCH /api/v1/{key}/config
{ "siteUrl": "https://client-salon.com" }
booking_created, booking_canceled and friends — signed, with retries, to any URL. A down endpoint never blocks a booking.
POST https://your-endpoint.example/hooks
X-Signature: sha256=…
{ "event": "booking_created", … } # also: booking_canceled, …
# signed payloads · automatic retries · your URL, your tooling
Busy time flows both ways over iCal feeds. The embed posts its height to the parent page — the exact bridge this landing page runs on.
# iCal feeds: publish bookings out, ingest external busy time in —
# your Google/Apple calendar subscribes, and blocks time both ways.
// embed bridge (what powers the widgets on this very page)
window.addEventListener("message", (e) => {
if (e.origin !== "https://app.gobookingsuite.com") return;
if (e.data.type === "bk-embed-height")
frame.style.height = e.data.height + "px";
});