Developers
Developer API
Build booking into your own website or systems. Most businesses only need the embeddable widget — the REST API is for custom integrations.
Embeddable widget
No API key required — paste it into your site.
Get the exact snippet in your dashboard under API & widget:
<div id="kacti-booking"></div> <script src="https://kacti.ca/embed.js" data-business="your-business-slug" data-mode="inline" data-accent="#2563eb" defer></script>
data-mode—inlineorbutton(floating pop-up)data-service— optional service id to preselectdata-target— optional id of the container element- The iframe auto-resizes and fires a
kacti:booking-confirmedwindow event.
Authentication
Bearer tokens scoped to one business.
Create a key in your dashboard and send it as a bearer token. Keys can be locked to specific website domains.
curl https://kacti.ca/api/public/v1/services \ -H "Authorization: Bearer kacti_live_xxxxxxxx"
Endpoints
Everything under /api/public/v1.
/api/public/v1/businessBusiness profile, address, timezone and policies.
/api/public/v1/servicesActive services with duration, buffer and price.
/api/public/v1/employeesActive staff who can be booked.
/api/public/v1/availabilityBookable slots for a service on a date.
Query: service_id (required), date=YYYY-MM-DD (required), employee_id, tz_offset_min
/api/public/v1/bookingsCreate a guest booking. Price, availability and conflicts are validated server-side.
/api/public/v1/bookings/{id}Status of a booking created with your key.
curl -X POST https://kacti.ca/api/public/v1/bookings \
-H "Authorization: Bearer kacti_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"service_id": "…",
"employee_id": "…",
"start_at": "2026-03-04T14:00:00.000Z",
"guest_name": "Jane Doe",
"guest_email": "jane@example.com",
"guest_phone": "+1 555 123 4567"
}'Errors & limits
Predictable error shapes and per-key rate limits.
Errors return { error: { code, message } } with codes such as unauthorized, origin_not_allowed, invalid_request, not_found and rate_limited.
Rate limits apply per API key (reads are more generous than booking writes). Handle HTTP 429 by retrying after the Retry-After header.
