> Portal Navigation:
> 
> - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version.
> - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages).
> - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`).
> - Top-level index of all portals: https://dev.wix.com/docs/llms.txt
> - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt

## Resource: Bookings Flow

## Article: Bookings Flow

## Article Link: https://dev.wix.com/docs/api-reference/business-solutions/bookings/skills/bookings-flow.md

## Article Content:

# RECIPE: Book an Appointment

## When to use this recipe

Any visitor request about a Wix Bookings service catalog, availability, or making an appointment. Examples:

- "What services do you offer?" / "Do you do couples massage?"
- "Is there a free slot for a haircut this Friday at 2pm?"
- "Find a haircut slot next Tuesday morning"
- "Book me a haircut with Maria tomorrow"
- "When is the next available massage?"

## Inputs you need before STEP 6

| Input | How to get it |
|---|---|
| Visitor token | STEP 1 (`GenerateVisitorToken`, or reuse one already in the conversation) |
| Business timezone | `GetBusinessDetails` tool if the MCP has it, otherwise the `timeZone` field of any STEP 3 response |
| Service GUID, `schedule.id`, `form.id`, `type`, duration, `payment.options` | STEP 2 (`POST /bookings/v2/services/query`) |
| Staff resource GUID (only if the user named a person) | STEP 2 with `conditionalFields: ["STAFF_MEMBER_DETAILS"]` → `staffMemberDetails.staffMembers[].staffMemberId` |
| A bookable slot (`localStartDate`, `localEndDate`, `scheduleId`, `location`, `availableResources`) | STEP 3 (`POST /_api/service-availability/v2/time-slots`) |
| Fresh confirmation the slot is still open | STEP 4 (`POST /_api/service-availability/v2/time-slots/get`) |
| Booking form field keys and the visitor's answers | STEP 5 (`GET /form-schema-service/v4/forms/{formId}/summary`) + ask the visitor |

## Decision tree — pick the shortest path

- **"What do you offer?" / "Do you do X?"** → STEP 1 + STEP 2. Answer from the catalog; offer to check availability.
- **"Is X free on <day> at <time>?"** → STEP 1 + STEP 2 + STEP 3 with a one-minute window at that time.
- **"Find an X slot <day> <morning/afternoon>"** → STEP 1 + STEP 2 + STEP 3 over the day-part window.
- **"When is the next X?"** → STEP 1 + STEP 2 + STEP 3 over 14 days with `timeSlotsPerDay: 1`, then drill into one day.
- **"Book me X [with <staff>] <day> [at <time>]"** → STEP 1 → STEP 2 → STEP 3 (with `resourceIds` if staff named) → STEP 5 (collect details) → STEP 4 (re-validate) → STEP 6 → STEP 7 if paying online.

This recipe covers **appointment** services (`type: "APPOINTMENT"`), the common case. For `CLASS` use List Event Time Slots and book with `bookedEntity.slot.eventId`; for `COURSE` book with `bookedEntity.schedule.scheduleId` (see References).

---

## Date and time rules

Apply these before STEP 3 on every request.

- **Business timezone is the reference.** Resolve "today", "tomorrow", "this Friday" against the current date in the business timezone, never UTC or your own clock. If the visitor states their own zone or city, either convert their time into the business zone, or pass their IANA zone as `timeZone` in STEP 3 and Wix returns slots in it.
- **Relative dates.** "Tomorrow" = today + 1. "This <weekday>" = the next occurrence on or after today. "Next <weekday>" = the following week's occurrence when today is that weekday or later, otherwise same as "this". "This weekend" = coming Saturday and Sunday. State the resolved date in your reply so the visitor can correct you.
- **Day parts.** Morning `08:00-12:00`, midday `11:00-14:00`, afternoon `12:00-17:00`, evening `17:00-21:00`, unspecified `00:00-23:59`. If the window is empty, widen to the whole day and say so.
- **Exact times.** For "at 2pm" query `fromLocalDate = <date>T14:00:00`, `toLocalDate = <date>T14:01:00` and check the returned `localStartDate` equals the requested time. Slot granularity is per service (15/30/60 min); if the exact minute is not offered, return the two nearest slots.
- **Formats.** Time-slot APIs take **local** ISO date-times with no offset (`2026-09-18T14:00:00`) plus an IANA `timeZone`; any offset in the string is ignored when `timeZone` is set. Create Booking takes **absolute** times (`2026-09-22T18:00:00.000Z` or `2026-09-22T11:00:00.000-07:00`). Convert local → absolute per date (DST changes the offset), and keep `endDate - startDate` equal to the service duration.
- **Past and policy limits.** Past times return an empty list. Slots flagged `tooEarlyToBook` / `tooLateToBook` are excluded by `bookable: true`. Never say a time is free without a fresh STEP 3 or STEP 4 call.

---

## STEP 1: Get a visitor token

If you do not already have a visitor token in the conversation context, call the `GenerateVisitorToken` tool to mint one. **Reuse the same token for every step** — the booking, the checkout and the checkout URL must all be created by the same visitor identity.

---

## STEP 2: Find the service (and its staff)

`POST https://www.wixapis.com/bookings/v2/services/query`

> **WARNING — `$contains` is not a supported filter operator on this endpoint.** Sending `"filter": { "name": { "$contains": "massage" } }` returns:
> ```
> 400 { "message": "Invalid filter. Filter contains unsupported operator []" }
> ```
> `$startsWith` works but is case-sensitive. For anything fuzzy ("do you do massage?", "haircut", "the couples one") fetch all non-hidden services and match `name`, `tagLine`, `description` and `category.name` client-side, case-insensitive, with synonyms.

**List the catalog with staff (use this by default):**

```bash
curl -X POST 'https://www.wixapis.com/bookings/v2/services/query' \
-H 'Authorization: <VISITOR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
  "query": {
    "filter": { "hidden": false },
    "paging": { "limit": 100 }
  },
  "conditionalFields": ["STAFF_MEMBER_DETAILS"]
}'
```

If `pagingMetadata.total` > 100, repeat with `paging.offset`.

### What you need from the response

```jsonc
{
  "services": [{
    "id": "<SERVICE_GUID>",                              // ← serviceId for STEP 3, 4, 6
    "type": "APPOINTMENT",                               // ← APPOINTMENT | CLASS | COURSE; this recipe = APPOINTMENT
    "name": "Haircut",
    "tagLine": "Precision Styling with Maria",
    "description": "Enjoy a professional haircut ...",
    "hidden": false,                                     // ← never offer hidden services
    "onlineBooking": { "enabled": true },                // ← false = must book via the business
    "schedule": {
      "id": "<SCHEDULE_GUID>",                           // ← scheduleId for STEP 6 (also on each slot)
      "availabilityConstraints": { "durations": [{ "minutes": 60 }] }  // ← service duration
    },
    "payment": {
      "rateType": "FIXED",
      "fixed": { "price": { "value": "50", "currency": "USD" } },
      "options": { "online": true }                      // ← decides selectedPaymentOption in STEP 6
    },
    "form": { "id": "00000000-0000-0000-0000-000000000000" },   // ← formId for STEP 5
    "locations": [{
      "type": "BUSINESS",
      "business": { "id": "<LOCATION_GUID>", "name": "Lumina Lane" },
      "calculatedAddress": { "formattedAddress": "123 Lumina Lane, Santa Monica, CA" }
    }],
    "staffMemberIds": ["<STAFF_RESOURCE_GUID>"],
    "staffMemberDetails": {                              // ← only with conditionalFields STAFF_MEMBER_DETAILS
      "staffMembers": [{ "staffMemberId": "<STAFF_RESOURCE_GUID>", "name": "Maria" }]
    },
    "category": { "name": "Our Services" }
  }],
  "pagingMetadata": { "count": 3, "total": 3 }
}
```

- **`staffMemberDetails.staffMembers[].staffMemberId`** is the *resource* GUID used by availability (`resourceIds`) and booking (`resource.id`). No separate staff query needed. If a service lacks staff details, `POST /bookings/v1/staff-members/query` with `{"query":{}}` works for visitors — use its `resourceId`, **not** `id`.
- If the user named a person who is not on the requested service, say who does provide it instead of forcing the booking.
- Answer "what do you offer" with name, one-line description, duration, price and staff for each non-hidden, online-bookable service.

---

## STEP 3: List available slots

`POST https://www.wixapis.com/_api/service-availability/v2/time-slots`

> **WARNING — `availableResources` comes back empty unless you send `includeResourceTypeIds`.** Without it every slot has `"availableResources": []` and you cannot tell who is free. Always include the staff resource type constant `1cd44cf8-756f-41c3-bd90-3e2ffcaf1155`.

**Slots in a window (day part or whole day):**

```bash
curl -X POST 'https://www.wixapis.com/_api/service-availability/v2/time-slots' \
-H 'Authorization: <VISITOR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
  "serviceId": "<SERVICE_GUID>",
  "fromLocalDate": "2026-09-22T08:00:00",
  "toLocalDate": "2026-09-22T12:00:00",
  "timeZone": "<BUSINESS_TIMEZONE>",
  "bookable": true,
  "includeResourceTypeIds": ["1cd44cf8-756f-41c3-bd90-3e2ffcaf1155"],
  "cursorPaging": { "limit": 100 }
}'
```

**Variants:**
- Exact time ("Friday at 2pm"): `fromLocalDate` = the time, `toLocalDate` = one minute later.
- Specific staff: add `"resourceIds": ["<STAFF_RESOURCE_GUID>"]`.
- Several business locations: add `"locations": [{ "id": "<LOCATION_GUID>", "locationType": "BUSINESS" }]`.
- "Next available" overview: 14-day range plus `"timeSlotsPerDay": 1`.
- More pages: pass `cursorPagingMetadata.cursors.next` as `cursorPaging.cursor`.

### What you need from the response

```jsonc
{
  "timeSlots": [{
    "serviceId": "<SERVICE_GUID>",
    "localStartDate": "2026-09-22T11:00:00",             // ← show to the visitor; convert to absolute for STEP 6
    "localEndDate": "2026-09-22T12:00:00",
    "bookable": true,
    "scheduleId": "<SCHEDULE_GUID>",                     // ← scheduleId for STEP 6
    "location": {
      "id": "<LOCATION_GUID>",                           // ← location.id for STEP 4 and 6
      "name": "Lumina Lane",
      "formattedAddress": "123 Lumina Lane, Santa Monica, CA",
      "locationType": "BUSINESS"                         // ← becomes OWNER_BUSINESS in STEP 6
    },
    "totalCapacity": 1,
    "remainingCapacity": 1,
    "bookingPolicyViolations": { "tooEarlyToBook": false, "tooLateToBook": false, "bookOnlineDisabled": false },
    "availableResources": [{
      "resourceTypeId": "1cd44cf8-756f-41c3-bd90-3e2ffcaf1155",
      "resources": [{ "id": "<STAFF_RESOURCE_GUID>", "name": "Maria" }]   // ← resource for STEP 6
    }]
  }],
  "timeZone": "America/Los_Angeles",                     // ← the business timezone if you passed none
  "cursorPagingMetadata": { "hasNext": false }
}
```

Empty `timeSlots` means nothing is open in that window (closed day, fully booked, or past). Widen the window and offer alternatives instead of answering a bare "no".

---

## STEP 4: Re-validate the chosen slot

`POST https://www.wixapis.com/_api/service-availability/v2/time-slots/get`

Call this immediately before STEP 6, after the visitor has picked a time and given their details. It returns the full resource list for that one slot.

```bash
curl -X POST 'https://www.wixapis.com/_api/service-availability/v2/time-slots/get' \
-H 'Authorization: <VISITOR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
  "serviceId": "<SERVICE_GUID>",
  "localStartDate": "2026-09-22T11:00:00",
  "localEndDate": "2026-09-22T12:00:00",
  "timeZone": "<BUSINESS_TIMEZONE>",
  "location": { "id": "<LOCATION_GUID>", "locationType": "BUSINESS" }
}'
```

### What you need from the response

```jsonc
{
  "timeSlot": {
    "bookable": true,                                    // ← must be true
    "remainingCapacity": 1,
    "bookingPolicyViolations": { "tooEarlyToBook": false, "tooLateToBook": false, "bookOnlineDisabled": false },
    "availableResources": [{
      "resourceTypeId": "1cd44cf8-756f-41c3-bd90-3e2ffcaf1155",
      "resources": [{ "id": "<STAFF_RESOURCE_GUID>", "name": "Maria" }]  // ← named staff must appear here
    }],
    "scheduleId": "<SCHEDULE_GUID>"
  },
  "timeZone": "America/Los_Angeles"
}
```

If `bookable` is false or the requested person is missing, go back to STEP 3 and offer alternatives.

---

## STEP 5: Get the booking form fields and collect the visitor's details

`GET https://www.wixapis.com/form-schema-service/v4/forms/<FORM_GUID>/summary`

```bash
curl -X GET 'https://www.wixapis.com/form-schema-service/v4/forms/00000000-0000-0000-0000-000000000000/summary' \
-H 'Authorization: <VISITOR_TOKEN>'
```

### What you need from the response

```jsonc
{
  "formSummary": {
    "id": "00000000-0000-0000-0000-000000000000",
    "fields": [
      { "target": "first_name",       "label": "First name",         "type": "STRING" },   // ← keys for formSubmission
      { "target": "last_name",        "label": "Last name",          "type": "STRING" },
      { "target": "email",            "label": "Email",              "type": "EMAIL" },
      { "target": "phone",            "label": "Phone",              "type": "PHONE" },
      { "target": "address",          "label": "Multi-line address", "type": "MULTILINE_ADDRESS" }, // only for at-customer-location services
      { "target": "add_your_message", "label": "Add your message",   "type": "STRING" }    // optional
    ]
  }
}
```

- **`fields[].target` are the exact JSON keys for `formSubmission` in STEP 6.** They are snake_case (`first_name`), not camelCase.
- The default form requires first name, last name, email and phone. Custom forms can add or require more; ask the visitor for every required field and never invent contact data.
- `phone` must be a valid E.164 number from a country the site allows. Reserved fake numbers (`+1555010xxxx`) are rejected.

---

## STEP 6: Create the booking

`POST https://www.wixapis.com/bookings/v2/bookings`

> **WARNING — camelCase form keys return 400.** This body fragment fails:
> ```json
> "formSubmission": { "firstName": "Test", "lastName": "Agent", "email": "...", "phone": "+15555550123" }
> ```
> ```
> 400 { "message": "Validation failed: first_name must have required property 'first_name', last_name must have required property 'last_name', firstName must NOT have additional properties, lastName must NOT have additional properties, phone Phone number's country code must correspond to one from allowed countries" }
> ```
> Use the `target` keys from STEP 5 and a real phone number.

```bash
curl -X POST 'https://www.wixapis.com/bookings/v2/bookings' \
-H 'Authorization: <VISITOR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
  "booking": {
    "bookedEntity": {
      "slot": {
        "serviceId": "<SERVICE_GUID>",
        "scheduleId": "<SCHEDULE_GUID>",
        "startDate": "2026-09-22T18:00:00.000Z",
        "endDate": "2026-09-22T19:00:00.000Z",
        "timezone": "<BUSINESS_TIMEZONE>",
        "resource": { "id": "<STAFF_RESOURCE_GUID>", "name": "Maria" },
        "location": { "id": "<LOCATION_GUID>", "name": "Lumina Lane", "locationType": "OWNER_BUSINESS" }
      }
    },
    "totalParticipants": 1,
    "selectedPaymentOption": "ONLINE"
  },
  "formSubmission": {
    "first_name": "<FIRST_NAME>",
    "last_name": "<LAST_NAME>",
    "email": "<EMAIL>",
    "phone": "<E164_PHONE>"
  },
  "participantNotification": { "notifyParticipants": true }
}'
```

Field mapping:

| Field | Source |
|---|---|
| `slot.serviceId` | STEP 2 `services[].id` |
| `slot.scheduleId` | STEP 3 `timeSlots[].scheduleId` (= service `schedule.id`) |
| `slot.startDate` / `endDate` | STEP 3 `localStartDate` / `localEndDate` converted to absolute time in the business zone |
| `slot.timezone` | business timezone |
| `slot.resource` | one entry from STEP 4 `availableResources[].resources[]`; omit the whole `resource` object when the visitor has no preference and Wix will assign staff |
| `slot.location` | STEP 3 `location.id` + `name`, with `locationType` **`OWNER_BUSINESS`** (slots say `BUSINESS`; `CUSTOMER` and `CUSTOM` map unchanged) |
| `selectedPaymentOption` | `ONLINE` if `payment.options.online`; `OFFLINE` if only `inPerson`; `MEMBERSHIP` for pricing-plan members. Ask when both online and offline are allowed |
| `formSubmission` | STEP 5 `target` keys → visitor answers. Do **not** also send `booking.contactDetails` |

### What you need from the response

```jsonc
{
  "booking": {
    "id": "<BOOKING_GUID>",                              // ← catalogItemId for STEP 7
    "status": "CREATED",                                 // ← CREATED until paid/confirmed; PENDING/CONFIRMED for offline flows
    "paymentStatus": "UNDEFINED",
    "selectedPaymentOption": "ONLINE",
    "revision": "1",
    "bookedEntity": {
      "slot": {
        "startDate": "2026-09-22T11:00:00.000-07:00",    // ← local time with offset, good for the confirmation message
        "endDate": "2026-09-22T12:00:00.000-07:00",
        "resource": { "id": "<STAFF_RESOURCE_GUID>", "name": "Maria" },
        "location": { "name": "Lumina Lane", "formattedAddress": "123 Lumina Lane, ..." }
      },
      "title": "Haircut"
    },
    "contactDetails": { "firstName": "...", "lastName": "...", "email": "...", "phone": "..." }
  }
}
```

A `CREATED` booking does **not** hold the slot for the visitor until it is paid or confirmed, so run STEP 7 right away. If the call fails because the slot was just taken, return to STEP 3. If `selectedPaymentOption` was `OFFLINE`, stop here and tell the visitor the booking is submitted and (if the business approves manually) awaiting confirmation.

---

## STEP 7: Create the checkout and hand over the payment link

`POST https://www.wixapis.com/ecom/v1/checkouts`

> **WARNING — `catalogItemId` is the booking GUID, not the service GUID**, and `appId` is the Wix Bookings catalog app ID, not the site's app or the service's `appId` field value you might see elsewhere.

```bash
curl -X POST 'https://www.wixapis.com/ecom/v1/checkouts' \
-H 'Authorization: <VISITOR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
  "lineItems": [{
    "quantity": 1,
    "catalogReference": {
      "appId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
      "catalogItemId": "<BOOKING_GUID>"
    }
  }],
  "channelType": "WEB"
}'
```

### What you need from the response

```jsonc
{
  "checkout": {
    "id": "<CHECKOUT_GUID>",                             // ← for the checkout-url call
    "lineItems": [{
      "productName": { "original": "Haircut" },
      "price": { "formattedAmount": "$50.00" },
      "descriptionLines": [ /* date, duration, staff, address as plain text */ ]
    }],
    "priceSummary": { "total": { "formattedAmount": "$50.00" } }   // ← quote this to the visitor
  }
}
```

Then:

```bash
curl -X GET 'https://www.wixapis.com/ecom/v1/checkouts/<CHECKOUT_GUID>/checkout-url' \
-H 'Authorization: <VISITOR_TOKEN>'
```

```jsonc
{ "checkoutUrl": "https://<site-domain>/checkout?checkoutId=<CHECKOUT_GUID>" }   // ← send this to the visitor
```

Reply with the summary (service, local date and time, staff, location, total) and the checkout URL. Wix confirms the booking automatically after payment (`CONFIRMED`, or `PENDING` when the business approves manually). Unpaid `CREATED` bookings expire on their own.

---

## Common pitfalls (from real conversations)

These are the ways this flow has failed in practice. The steps warn about them inline; this section is the consolidated reference.

### 1. `$contains` on Query Services returns 400

```
POST /bookings/v2/services/query
body: { "query": { "filter": { "name": { "$contains": "massage" } } } }
→ 400 { "message": "Invalid filter. Filter contains unsupported operator []" }
```

**Resolution:** drop the filter (or use `hidden: false` only), fetch up to 100 services, match client-side and case-insensitively across `name`, `tagLine`, `description`, `category.name`.

### 2. List Availability Time Slots returns `availableResources: []`

You omitted `includeResourceTypeIds`. Without it the slots are still correct but anonymous, so you cannot honour "with Maria" or name the stylist. **Resolution:** always send `"includeResourceTypeIds": ["1cd44cf8-756f-41c3-bd90-3e2ffcaf1155"]`; to restrict to one person also send `resourceIds`.

### 3. camelCase or made-up form keys fail Create Booking

```
POST /bookings/v2/bookings
body: { ..., "formSubmission": { "firstName": "…", "lastName": "…" } }
→ 400 "first_name must have required property 'first_name' … firstName must NOT have additional properties"
```

**Resolution:** keys are the `target` values from Get Form Summary (`first_name`, `last_name`, `email`, `phone`, …).

### 4. Phone rejected: "country code must correspond to one from allowed countries"

Placeholder numbers such as `+15555550123` fail validation. **Resolution:** collect the visitor's real number in E.164 form; do not fabricate one to get past the step.

### 5. Wrong `locationType` on the booking

Slots report `"locationType": "BUSINESS"`, but Create Booking expects **`OWNER_BUSINESS`** for a business location. Copy `id` and `name` from the slot and translate the type.

### 6. Treating a `CREATED` booking as done

`status: "CREATED"` is unpaid and unconfirmed; it neither blocks the slot nor appears in the business calendar. Always continue to STEP 7 for online payment, and say "pay here to confirm" rather than "you're booked".

### 7. Checkout with the service GUID

`catalogReference.catalogItemId` must be the **booking** GUID from STEP 6. The service GUID produces an unusable checkout. `appId` is always `13d21c63-b5ec-5912-8397-c3a5ddb27a97`.

### 8. Trying to read, cancel or reschedule as a visitor

`GET /bookings/v2/bookings/{id}` → **404**, `POST /bookings/v2/bookings/{id}/cancel` → **403** with a visitor token. Visitors cannot manage bookings through the API. **Resolution:** point them to the confirmation email link, the site's members area, or the business contact details from `GetBusinessDetails`.

---

## Constants

| Constant | Value |
|---|---|
| Wix Bookings catalog `appId` (checkout) | `13d21c63-b5ec-5912-8397-c3a5ddb27a97` |
| Staff member resource type ID | `1cd44cf8-756f-41c3-bd90-3e2ffcaf1155` |
| Default booking form ID | `00000000-0000-0000-0000-000000000000` |

Everything else — service, schedule, staff, location and form IDs, timezone, prices, durations — is per site. Discover it in STEP 2 and STEP 3 during the conversation; never reuse IDs from memory or from another site.

All endpoints in this recipe accept **visitor or member** authentication. Route every call through `GenerateVisitorToken` + `CallWixSiteAPI` / `ExecuteWixAPI` with the same token.

---

## References

- [Query Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/query-services.md)
- [Query Staff Members](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members.md)
- [List Availability Time Slots](https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots/time-slots-v2/list-availability-time-slots.md)
- [Get Availability Time Slot](https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots/time-slots-v2/get-availability-time-slot.md)
- [List Event Time Slots (classes)](https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots/time-slots-v2/list-event-time-slots.md)
- [Get Form Summary](https://dev.wix.com/docs/rest/crm/forms/form-schemas/get-form-summary.md)
- [Create Booking](https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/create-booking.md)
- [Bookings Writer sample flows](https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/sample-flows.md)
- [Flow: Single-Service Booking](https://dev.wix.com/docs/api-reference/business-solutions/bookings/flow-single-service-booking.md)
- [Bookings and Wix Forms integration](https://dev.wix.com/docs/api-reference/business-solutions/bookings/wix-forms-integration.md)
- [About Time Zones](https://dev.wix.com/docs/api-reference/business-solutions/bookings/about-time-zones.md)
- [Create Checkout](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/checkout/checkout/create-checkout.md)
- [Get Checkout URL](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/checkout/checkout/get-checkout-url.md)