REST API
Building your own booking front end, a mobile app or an integration? The built-in booking form, manage page and customer dashboard all run on the same REST API you can call. Prices, availability, capacity and payment confirmation stay on the server, so a custom front end can’t book a slot the form couldn’t.
Basics
- Base:
/wp-json/core-bookings/v1/(or?rest_route=/core-bookings/v1/without pretty permalinks). - Booking access: a booking’s private token goes in the
X-Core-Bookings-Tokenheader. Never put tokens in query strings, analytics or logs. - Dashboard access: a customer dashboard session goes in
X-Core-Bookings-Portal. Waitlist entries useX-Core-Bookings-Waitlist, review linksX-Core-Bookings-Review. - Staff and managers: ordinary WordPress REST authentication: a cookie plus
X-WP-Nonce, or an Application Password. - Rate limits: public and customer routes allow 20 POST and 120 GET requests a minute per visitor address, with a separate bucket of 30 for
availability/next. Over the limit returnscb_rate_limited(429). - Errors: a
WP_Errorwith acb_code and HTTP status, for examplecb_slot_taken(409),cb_stale_version(409),cb_request_conflict(409) orcb_login_required(401). - Responses are sent with
Cache-Control: no-store, private.
Booking Flow
| Route | Method | What it does |
|---|---|---|
config | GET | Spam-protection site key and state, and the customer dashboard URL. No secrets. |
services | GET | Bookable services with staff, payment method, extras, policy, notice and horizon |
availability | GET | UTC slots for service_id, staff_id, date (YYYY-MM-DD), optional seats and choices |
availability/next | GET | Next open dates, with days (1 to 7) and staff_offset for paged searches |
quote | POST | Price preview, same inputs as a booking |
bookings | POST | Create a booking |
invitations/{token} | GET | Read an invitation link |
waitlist | POST | Join a waitlist |
gift-cards | POST | Buy a gift card (Promotions module) |
questions/upload, questions/upload/discard | POST | File answers for booking questions (Booking questions module) |
POST /wp-json/core-bookings/v1/bookings
{
"service_id": 1,
"staff_id": 2,
"start": "2026-11-12T10:00:00Z",
"timezone": "Europe/London",
"name": "Example Customer",
"email": "customer@example.com",
"seats": 1,
"consent": true,
"request_key": "a-new-uuid-for-this-booking-request",
"turnstile_token": "only-when-spam-protection-is-on"
}
Optional fields include extras, phone, notes, answers, choices, coupon, guests, invitation, locale and create_account. Store the returned id and token securely. Repeating a request with the same request_key and payload returns the same booking instead of a second one; a different payload with that key fails with cb_request_conflict. When spam protection is on, every attempt needs a fresh challenge token.
Routes for One Booking
Unless a row says otherwise, these need the booking’s X-Core-Bookings-Token, or WordPress authentication as a manager or the assigned staff member.
| Route | Method | What it does |
|---|---|---|
bookings/{id} | GET | The booking, including change_until and, while a hold is open, expires_at |
bookings/{id}/change | POST | action (cancel or reschedule), expected_version, start for a reschedule, optional reason |
bookings/{id}/checkout | POST | Start payment. Returns a Stripe or FluentCart URL, or the embedded Stripe details. |
bookings/{id}/balance | POST | Pay a remaining balance |
bookings/{id}/intake | POST | Open the intake form |
bookings/{id}/calendar | GET | Calendar file data for the booking |
payment-rules/bookings/{id}/balance | POST | Balance payment under Payment rules |
gift-cards/{id} | GET | Gift card status, with the gift card’s token in X-Core-Bookings-Token (Promotions module) |
reviews/{id} | GET, POST | Read and submit a review (uses X-Core-Bookings-Review) |
Customer Dashboard and Waitlist
| Route | Method | Access | What it does |
|---|---|---|---|
portal/request | POST | Public | Email a sign-in link (15 minutes, single use) |
portal/exchange | POST | Public | Exchange the link’s id and token for a one-hour session |
portal/account | GET | Public | Whether the signed-in WordPress user is linked to a customer |
portal/link, portal/link/confirm | POST | Signed-in user | Link a WordPress account to its customer profile |
portal/profile | GET | Session | Profile and visible fields |
portal/profile/meta | POST | Session | Save registered customer fields |
portal/records | GET | Session | Bookings and packs, with cursors |
portal/packs, portal/pack/{id} | POST, GET | Session | Buy and read session packs |
portal/memberships and /{id}/cancel, /{id}/billing | POST | Session | Memberships module |
portal/logout | POST | Session | End the session |
waitlist/{entry}/view, verify, claim, cancel | GET, POST | X-Core-Bookings-Waitlist | Manage a waitlist entry and claim an offer |
A signed-in WordPress user linked to a customer can call the session routes with WordPress authentication instead of the session header.
Staff, Manager and Transfer Routes
| Route | Method | Who | What it does |
|---|---|---|---|
admin/appointments/{id} | GET | Staff | The appointment panel |
admin/appointments/{id}/change | POST | Staff | Run an appointment action |
admin/appointments/{id}/move | POST | Staff | Move an appointment (calendar drag) |
admin/appointments/{id}/notes | POST | Staff | Add or delete an internal note |
admin/staff/{staff}/block | POST | Staff | Block time in a schedule |
admin/search | GET | Staff | Search appointments and customers (q) |
admin/customer/meta | POST | Managers | Save registered fields on a customer by email |
editor/catalog | GET | Post editors | Services and staff for the block editor |
editor/services | POST | Managers who can edit posts | Create a service from the block editor |
transfers/export | GET | Managers with export permission | JSON export; bookings=false for configuration only |
transfers/catalog, analyze, preview, apply | GET, POST | Managers with export permission | The import steps behind Import / Export |
Staff routes stay inside the staff member’s own appointments. The admin routes return the HTML the workspace renders, so for automation the abilities below are usually the better fit.
Webhook Receivers
Payment, calendar and messaging providers post to these, so you won’t call them yourself: webhooks/stripe, webhooks/paypal, webhooks/polar, webhooks/paddle, webhooks/google, webhooks/microsoft, messaging/twilio/status, messaging/twilio/inbound and messaging/whatsapp. Private calendar feeds are served from calendar-feed/{token}.ics.
Abilities Over REST
With the AI agent abilities module on, every offered ability is also available through the WordPress Abilities API at /wp-json/wp-abilities/v1/abilities/core-bookings/<name>/run. Read-only abilities use GET with ?input[...]; the rest use POST with {"input": {...}}. Authenticate with an Application Password. The same permission rules apply as in wp-admin.
curl -u "alex:xxxx xxxx xxxx xxxx xxxx xxxx" \
-X POST https://example.com/wp-json/wp-abilities/v1/abilities/core-bookings/update-appointment/run \
-H "Content-Type: application/json" \
-d '{"input":{"booking_id":"…","action":"approve","expected_version":3,"reason":"Approved by the owner"}}'
The ability list and who may run each one are in Let AI Agents Manage Your Bookings. For PHP-side changes, see Hooks and Filters.