Developer documentation
The BookAppointment API and webhooks
A small, honest REST API over your own account data, and signed webhooks when things change. Read and create appointments, list your services and team, and keep your CRM, spreadsheet or back-office system in step. Included on the Business package.
Getting started
Authentication in three steps
Every request is authenticated with a key you create in your own admin. Keys are shown once and stored only as a scrambled copy, so keep them server-side — never in browser code.
1. Create a key
Settings → API & webhooks → New key. Name it after the system that will use it and tick only the permissions it needs.
2. Send it as a bearer token
Add Authorization: Bearer ba_live_… to every request. All endpoints live under /api/public/v1 and return JSON.
3. Subscribe to events
Add an https endpoint, tick the events you want, send a test delivery and watch the delivery log.
https://www.bookappointment.co.uk/api/public/v1curl "https://www.bookappointment.co.uk/api/public/v1/services" \
-H "Authorization: Bearer ba_live_your_key"Reference
Endpoints
Rate-friendly by design: list endpoints return up to 200 records. Pass a narrower date range rather than paging through the whole diary.
Appointments that start inside a date range. Defaults to the next 30 days. Optional query parameters: from, to (ISO 8601 timestamps) and status. Returns up to 200 rows, earliest first.
curl "https://www.bookappointment.co.uk/api/public/v1/bookings?from=2026-09-01T00:00:00Z&to=2026-09-08T00:00:00Z" \
-H "Authorization: Bearer ba_live_your_key"{
"data": [
{
"id": "1f3c...",
"start_at": "2026-09-03T09:30:00+00:00",
"end_at": "2026-09-03T10:00:00+00:00",
"status": "confirmed",
"payment_status": "paid",
"service_id": "8a12...",
"staff_id": "b904...",
"location_id": null,
"customer_name": "James Barnes",
"customer_phone": "+447700900123",
"customer_email": "james@example.com",
"notes": null,
"created_at": "2026-08-28T18:04:11+00:00"
}
]
}Create an appointment. The end time is worked out from the service duration, and double bookings are rejected with a 409. A booking.created webhook fires on success.
curl -X POST "https://www.bookappointment.co.uk/api/public/v1/bookings" \
-H "Authorization: Bearer ba_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"service_id": "8a12...",
"staff_id": "b904...",
"start_at": "2026-09-03T09:30:00Z",
"customer_name": "James Barnes",
"customer_phone": "+447700900123",
"customer_email": "james@example.com",
"notes": "Requested the usual"
}'{
"data": {
"id": "1f3c...",
"start_at": "2026-09-03T09:30:00+00:00",
"end_at": "2026-09-03T10:00:00+00:00",
"status": "confirmed"
}
}Permissions
bookings.readRead appointments in a date range.bookings.writeCreate appointments.customers.readRead customer records (reserved for upcoming customer endpoints).services.readRead services, durations and prices.staff.readRead team members.
Errors
401Missing, unknown or revoked API key.403The key is valid but does not carry the permission the endpoint needs.404The service or team member in your request does not belong to this account.409The requested slot clashes with an existing booking.422The body failed validation — the message names the problem field.500Something went wrong on our side. Retry with backoff.
Errors are returned as { "error": "message" }.
Webhooks
Get told the moment something changes
Add as many https endpoints as you like, each with its own signing secret and its own list of events. Deliveries are logged with the response we got back, and you can resend a test at any time.
Events
booking.createdA new appointment is made online, in the admin, by the AI assistant or through the API.booking.updatedAn appointment is moved, rescheduled or its details change.booking.cancelledAn appointment is cancelled by the customer or the business.customer.createdA new customer record is added to the account.payment.succeededA card payment, deposit or Tap to Pay charge completes.
POST https://your-app.example.com/hooks/bookappointment
content-type: application/json
x-bookappointment-event: booking.created
x-bookappointment-signature: t=1789200000,v1=6f2a…{
"event": "booking.created",
"created_at": "2026-09-03T09:30:04.221Z",
"data": {
"booking": {
"id": "1f3c...",
"start_at": "2026-09-03T09:30:00+00:00",
"end_at": "2026-09-03T10:00:00+00:00",
"status": "confirmed"
}
}
}Verify the signature
The signature header carries a timestamp and an HMAC-SHA256 of timestamp.rawBody, signed with your endpoint's secret. Compare it against the raw request body before you trust the payload, and reject anything older than a few minutes.
import crypto from "node:crypto";
export function verify(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(
header.split(",").map((p) => p.split("=") as [string, string]),
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}Ready to connect your systems?
API access and webhooks are included on the Business package. Not sure whether the API or a no-code automation tool suits you better? Talk to us and we'll point you the right way.