One engine, every channel
API bookings run through the same code as the AI receptionist. A booking made over the phone and one made over HTTP cannot disagree.
api.switchly.ai
Check availability, book appointments and send confirmations straight from your own product. The same engine that answers the phone, without the phone.
REST over HTTPS
JSON in, JSON out
Versioned /v1
Ask what's free
GET/v1/availability?service_id=svc_cut&date=2026-06-13
"slots": [ { "start": "2026-06-13T10:30:00+02:00" }, { "start": "2026-06-13T11:15:00+02:00" } ]
Take the slot
POST/v1/appointments
"service_id": "svc_cut", "start_time": "2026-06-13T10:30:00+02:00", "customer_name": "Tony Marek", "customer_mobile": "+420777123456"
Booked and confirmed
201Created
"status": "booked", "secure_id": "4KQ2", "start_time": "2026-06-13T10:30:00+02:00", "duration_minutes": 45
Confirmation SMS sent to the customer. 4KQ2 is the code they quote to change it.
Why build on it
Opening hours, service durations, calendar conflicts, confirmation messages. Your integration sends a start time and gets an answer, not a pile of edge cases.
API bookings run through the same code as the AI receptionist. A booking made over the phone and one made over HTTP cannot disagree.
The availability check and the write happen under one lock per business, so two callers racing for the last slot get one winner and one clear 409 response.
Every booking sends the customer their SMS confirmation and notifies the business owner. Nothing extra to wire up.
Every failure returns a stable key and a plain message. Handle CONFLICT once and you have handled a taken slot.
Reference
Everything under /v1 is scoped to the business behind your API key. You cannot read or touch anyone else's data.
| Endpoint | What it does |
|---|---|
| GET/v1/me | The account and the assistant behind your API key. |
| GET/v1/assistant | Business profile: name, timezone, currency, opening hours, phone numbers. |
| GET/v1/assistant/services | Bookable services with duration and price. The IDs you book against. |
| GET/v1/availability | Free start times for one service on one day, already filtered by opening hours and existing bookings. |
| GET/v1/appointments | List bookings. Filter by date range, status or calendar; paginated. |
| POST/v1/appointments | Book a slot. Returns the appointment and its confirmation code. |
| GET/v1/appointments/{id} | One booking, including cancellation and modification history. |
| DELETE/v1/appointments/{id} | Cancel a booking. The customer gets the cancellation SMS automatically. |
Authentication
Create a key in the dashboard and send it on every request. There is no OAuth dance and no token to refresh.
# Book a slot
curl -X POST https://api.switchly.ai/v1/appointments \
-H "X-API-Key: $SWITCHLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"service_id": "svc_cut",
"start_time": "2026-06-13T10:30:00+02:00",
"customer_name": "Tony Marek",
"customer_mobile": "+420777123456"
}'
Authorization: Bearer <key> works too, whichever your HTTP client makes easier.
429 with the key RATE_LIMITED.
Failure modes
Every error arrives in one shape: a stable key you branch on, and a message for your logs. Nothing to parse out of prose.
| Status | Key | When |
|---|---|---|
| 400 | VALIDATION_ERROR | A field is missing or malformed, or the start time is in the past. |
| 401 | UNAUTHORIZED | The key is missing, unknown or no longer active. |
| 404 | NOT_FOUND | Unknown service, calendar or appointment. |
| 409 | CONFLICT | The slot is taken or outside opening hours, another booking got there first, or the appointment is already cancelled. |
| 429 | RATE_LIMITED | Too many requests on this key. Back off and retry. |
Create a key in the dashboard and make your first call in the time it takes to read this page.
Get an API key