End-to-End Booking Flow (REST)
Step-by-step flow for creating and settling bookings with the site owner's credentials — see who that covers, and where visitor-facing code goes instead, immediately below.
⚠️ These are owner-side calls, not visitor-facing code
Every call below runs with the site owner's credentials — an API key or the site's admin token. That covers two situations, and both are this recipe:
- an operator managing bookings, calling these APIs from a script, a management tool, or a back-office screen
- server-side code in a site or app acting as the owner — a backend function booking a client in, a scheduled job, a webhook handler
Either way the booking belongs to the site, not to the person being booked.
Building a site or app where a visitor books for themselves? These payloads are right, the identity is not. A visitor's booking and checkout run on an anonymous visitor token minted from the site's OAuth app client id. Using the owner's credentials for a visitor's purchase produces a checkout that belongs to the site: no cart persistence, no abandoned-checkout recovery, and no attribution to the customer. Read these first:
- Book an Appointment — the same flow from the visitor's side: visitor token, slot re-validation, booking form fields, checkout hand-off, and eight pitfalls from real conversations
- Retrieve Tokens — minting and refreshing the anonymous visitor token
- Allow Redirect URIs and Domains — registering your URLs so the visitor returns to your app after the Wix-hosted checkout
- Manage OAuth Apps — creating the OAuth app, whose id is the
client_idthe frontend mints visitor tokens from- Bookings Quick Start — the same flow through the JavaScript SDK on a headless site
Mixed apps are normal: the owner's credentials manage the catalog, staff, policies and coupons (the recipes here), while the visitor's own token books and pays.
Contents
- Query Available Services —
POST /bookings/v2/services/query. The three service types and how each one changes the rest of the flow, plus the four fields to carry forward:id,schedule.id,type,staffMemberIds. - Check Availability —
POST /_api/service-availability/v2/time-slots. Time Slots V2 replaces the deprecated Availability Calendar. Dates must be full local datetimes or the call 400s;availableResourcesstays empty unless you ask for it by resource type; thelocation.locationTypea slot returns is not the value Create Booking accepts. Classes come from a different endpoint and carry aneventId. - Create the Booking —
POST /_api/bookings-service/v2/bookings. One payload shape per service type: appointments need every slot field spelled out, classes need only the service and event ids and derive the rest, courses book a whole schedule. Participants aretotalParticipantsorparticipantsChoices, never both. The booking lands asCREATEDand is not on the calendar until step 4. - Confirm or Process Payment — two branches. Free and pay-at-location bookings are confirmed directly with a payment status. Paid bookings go into a cart that references the booking id, and whoever is paying is sent to its checkout URL; a server-to-server place-order path skips the payment page entirely, which only fits an operator or backend job booking someone in.
- Service Type Summary — appointment, class and course side by side:
which
bookedEntityeach uses, which availability API feeds it, and what makes it different.
Prerequisites
- Wix Bookings app installed (App ID:
13d21c63-b5ec-5912-8397-c3a5ddb27a97) - For paid services: Wix Payments or eCommerce configured
Note: If you receive errors from Bookings APIs, the Wix Bookings app may not be installed on the site. Use List Installed Apps to verify, and Install Wix Apps to install it if missing.
Required APIs
- Services API: Query Services
- Time Slots V2 API: List Availability Time Slots
- Bookings API: Create Booking, Confirm Booking
- eCommerce API: Create Cart
Step 1: Query Available Services
Endpoint: POST https://www.wixapis.com/bookings/v2/services/query
{
"query": {
"filter": {
"type": "APPOINTMENT"
},
"paging": {
"limit": 20
}
}
}Service Types:
APPOINTMENT— One-on-one sessions with a staff memberCLASS— Group sessions at scheduled timesCOURSE— Multi-session series (customers book the entire course)
Save from the response:
id— service IDschedule.id— schedule ID (needed for appointment bookings and course bookings)type— determines the booking flow (slot vs schedule)staffMemberIds— resource IDs of assigned staff (for appointments)
Step 2: Check Availability
Endpoint: POST https://www.wixapis.com/_api/service-availability/v2/time-slots
Important: The old Availability Calendar API (
/bookings/v2/availability/query) is deprecated. Always use Time Slots V2.
{
"serviceId": "<SERVICE_ID>",
"fromLocalDate": "2024-06-15T08:00:00",
"toLocalDate": "2024-06-16T18:00:00",
"timeZone": "America/New_York",
"bookable": true,
"includeResourceTypeIds": ["<RESOURCE_TYPE_ID>"]
}Date format
Dates must be in YYYY-MM-DDThh:mm:ss format (local datetime). Plain dates like 2024-06-15 will be rejected with a 400 error.
Parameters
| Parameter | Required | Description |
|---|---|---|
serviceId |
Yes | From Step 1 |
fromLocalDate |
Yes | Start of range in YYYY-MM-DDThh:mm:ss format |
toLocalDate |
Yes | End of range in YYYY-MM-DDThh:mm:ss format |
timeZone |
Yes | IANA timezone (e.g. America/New_York) |
bookable |
No | Set true to only get bookable slots |
includeResourceTypeIds |
No | Array of resource type IDs — populates availableResources in response |
Save from each time slot
serviceId,scheduleId— needed for Create BookinglocalStartDate,localEndDate— slot timesavailableResources[].resources[].id— resource ID (only populated ifincludeResourceTypeIdswas provided)location.locationType— warning: returnsBUSINESSbut Create Booking requiresOWNER_BUSINESS(see Step 3)
For Classes
Use List Event Time Slots instead. Each class session has an eventId — save it for the booking.
Step 3: Create the Booking
Endpoint: POST https://www.wixapis.com/_api/bookings-service/v2/bookings
For Appointments (use slot)
{
"booking": {
"bookedEntity": {
"slot": {
"serviceId": "<SERVICE_ID>",
"scheduleId": "<SCHEDULE_ID>",
"startDate": "2024-06-15T14:00:00",
"endDate": "2024-06-15T15:00:00",
"timezone": "America/New_York",
"resource": {
"id": "<RESOURCE_ID>"
},
"location": {
"locationType": "OWNER_BUSINESS"
}
}
},
"contactDetails": {
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com"
},
"totalParticipants": 1
}
}All slot fields are required for appointments when no eventId is provided:
| Field | Source | Notes |
|---|---|---|
serviceId |
Step 1 | Service GUID |
scheduleId |
Step 2 | From the time slot response |
startDate / endDate |
Step 2 | YYYY-MM-DDThh:mm:ss format |
timezone |
Step 2 | IANA tz format |
resource.id |
Step 2 | From availableResources in time slot response |
location.locationType |
— | Must be OWNER_BUSINESS, OWNER_CUSTOM, or CUSTOM. Time Slots returns BUSINESS but that value is not accepted here |
For Classes (use slot with eventId)
{
"booking": {
"bookedEntity": {
"slot": {
"serviceId": "<SERVICE_ID>",
"eventId": "<EVENT_ID>"
}
},
"contactDetails": {
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com"
},
"totalParticipants": 1
}
}When you provide eventId, all other slot fields (startDate, endDate, timezone, resource, location) are auto-derived from the event. You only need serviceId + eventId.
For Courses (use schedule)
{
"booking": {
"bookedEntity": {
"schedule": {
"scheduleId": "<SCHEDULE_ID>",
"serviceId": "<SERVICE_ID>",
"timezone": "America/New_York",
"location": {
"locationType": "OWNER_BUSINESS"
}
}
},
"contactDetails": {
"firstName": "Bob",
"lastName": "Test",
"email": "bob@example.com"
},
"totalParticipants": 1
}
}Participants
Specify exactly one of:
totalParticipants— for services with fixed pricing and no variantsparticipantsChoices— for services with variants and options
Result
Booking is created with status: CREATED. This is not yet visible in the booking calendar. You must either:
- Confirm it (Step 4, for offline/free payments), or
- Process payment (Step 4, for online payments) — confirmation happens automatically after checkout
Step 4: Confirm or Process Payment
For free or offline-payment bookings: Confirm directly
Endpoint: POST https://www.wixapis.com/_api/bookings-service/v2/bookings/<BOOKING_ID>/confirm
{
"revision": "<REVISION>",
"paymentStatus": "EXEMPT"
}Use the id and revision from the Create Booking response. Set paymentStatus to EXEMPT for free services or NOT_PAID for pay-at-location.
Result: Booking status changes to CONFIRMED and is visible in the booking calendar.
For online payments: Create a cart
Cart V2 unifies cart and checkout — there is no separate checkout entity. The created cart's id is what you use for the checkout URL and for placing the order.
4a. Create Cart
Endpoint: POST https://www.wixapis.com/ecom/v2/carts
{
"catalogItems": [
{
"catalogReference": {
"catalogItemId": "<BOOKING_ID>",
"appId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97"
},
"quantity": 1
}
]
}Use the booking ID as catalogItemId with the Wix Bookings app ID. Save cart.id from the response.
4b. Get Checkout URL
Endpoint: POST https://www.wixapis.com/ecom/v2/carts/{cartId}/get-checkout-url
Redirect the user to the returned checkoutUrl. After payment, the booking is automatically confirmed.
When the person paying is a visitor, create the cart and this URL with their visitor token, not the owner's credentials — see the note at the top. The call succeeds either way, which is what makes it easy to get wrong.
4c. Place Order — no payment page (alternative, server-to-server)
This one only makes sense on the owner's side: it creates the order outright, with nobody visiting a payment page. Right for an operator or backend job booking someone in; not a way to charge a visitor, who still has to be sent to checkout.
First calculate the cart to get a price-verification token:
Endpoint: POST https://www.wixapis.com/ecom/v2/carts/{cartId}/calculate
Save summary.priceVerificationToken from the response, then place the order:
Endpoint: POST https://www.wixapis.com/ecom/v2/carts/{cartId}/place-order
{
"priceVerificationToken": "<PRICE_VERIFICATION_TOKEN>"
}Creates an order directly without redirect.
Service Type Summary
| Service Type | bookedEntity |
Availability API | Key Difference |
|---|---|---|---|
| APPOINTMENT | slot (all fields required) |
Time Slots V2 | Single session, specific time, needs resource + scheduleId |
| CLASS | slot (only serviceId + eventId) |
Event Time Slots | Group session, auto-derives fields from event |
| COURSE | schedule |
Check capacity via Query Extended Bookings | Multi-session, books entire schedule |