@wix/agent-skills 1.31.0 → 1.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +7 -8
- package/skills/wix-app/references/DASHBOARD_PAGE.md +1 -1
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +11 -50
- package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +14 -10
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +5 -8
- package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +5 -4
- package/skills/wix-headless-kit/SKILL.md +15 -7
- package/skills/wix-headless-kit/guides/api-run.md +81 -26
- package/skills/wix-headless-kit/guides/existing-site.md +3 -2
- package/skills/wix-headless-kit/guides/reference-mode.md +9 -1
- package/skills/wix-headless-kit/install/AGENTS.md +7 -5
- package/skills/wix-headless-kit/install/attach.mjs +3 -3
- package/skills/wix-headless-kit/install/context.mjs +13 -3
- package/skills/wix-headless-kit/install/deploy.mjs +3 -3
- package/skills/wix-headless-kit/install/pins.json +1 -1
- package/skills/wix-headless-kit/install/setup.mjs +2 -2
- package/skills/wix-headless-kit/install/templates.mjs +2 -1
- package/skills/wix-headless-templates/blog/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/blog/seed/seed-blog.mjs +2 -2
- package/skills/wix-headless-templates/bookings/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/bookings/seed/seed-bookings.mjs +2 -1
- package/skills/wix-headless-templates/donations/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/donations/seed/seed-donations.mjs +3 -2
- package/skills/wix-headless-templates/events/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/events/seed/seed-events.mjs +3 -2
- package/skills/wix-headless-templates/portfolio/seed/SEED.md +4 -2
- package/skills/wix-headless-templates/portfolio/seed/seed-portfolio.mjs +6 -6
- package/skills/wix-headless-templates/rentals/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/rentals/seed/seed-rentals.mjs +2 -1
- package/skills/wix-headless-templates/restaurants/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/restaurants/seed/seed-restaurants.mjs +4 -3
- package/skills/wix-headless-templates/shared/seed/images.mjs +41 -5
- package/skills/wix-headless-templates/storefront/seed/SEED.md +17 -5
- package/skills/wix-headless-templates/storefront/seed/seed-store.mjs +21 -14
- package/skills/wix-manage/SKILL.md +25 -15
- package/skills/wix-manage/references/automations/activation-status.md +52 -0
- package/skills/wix-manage/references/automations/api-catalog.md +81 -0
- package/skills/wix-manage/references/automations/build-and-manage-automations.md +34 -0
- package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +277 -363
- package/skills/wix-manage/references/custom-apps/use-app-skills-and-app-tools.md +3 -1
- package/skills/wix-manage/references/sites/send-feedback-to-wix.md +92 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +258 -279
- package/skills/wix-manage/references/bookings/create-appointment-service.md +0 -243
- package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +0 -31
- package/skills/wix-manage/references/bookings/create-class-service.md +0 -222
- package/skills/wix-manage/references/bookings/create-course-service.md +0 -251
|
@@ -1,465 +1,379 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Create and Update Booking Services"
|
|
3
|
-
description:
|
|
3
|
+
description: "Creates and updates Wix Bookings services of every type — appointments, classes and courses — from a plain request such as 'a 60-minute consultation for $75', 'a yoga class for 12 people every Tuesday' or 'a 6-week photography course'. Covers choosing the service type, defaults for what the request leaves out, pricing (free, fixed, free-to-paid), staff, capacity, duration, categories, visibility, images, scheduling class and course sessions on the calendar, and changing existing services."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Create and Update Booking Services
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
One recipe for every Bookings service: pick the type, fill in what the user didn't say, create it, schedule its sessions when it's a class or a course, and report back. The second half covers changing a service that already exists.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
All service types are created with the same call (`POST https://www.wixapis.com/bookings/v2/bulk/services/create`); the type decides which fields the body carries and what has to happen after it.
|
|
11
|
+
|
|
12
|
+
Related recipes:
|
|
13
|
+
- A service booked by room or equipment instead of (or as well as) staff — "a massage in whichever treatment room is free" → [Multi-Resource Service Creation](multi-resource-service-creation.md). It creates the resource types and resources and gives the service body (`serviceResources`, and `primaryResourceType` for an appointment with no staff); this recipe's staff rules don't apply to such a service.
|
|
14
|
+
- Memberships, class packs or session bundles for a service → [Pricing Plans Bookings Integration](../pricing-plans/pricing-plans-bookings-integration.md).
|
|
15
|
+
- Adding staff, or giving a staff member custom working hours → [Bookings Staff Setup](bookings-staff-setup.md).
|
|
16
|
+
- Cancellation, booking-window or waitlist rules → [Booking Service Policy Setup](booking-service-policy-setup.md).
|
|
17
|
+
|
|
18
|
+
If a Bookings call fails because the Wix Bookings app isn't installed on the site, install it with [Install Wix Apps](../app-installation/install-wix-apps.md) (app ID `13d21c63-b5ec-5912-8397-c3a5ddb27a97`) and retry. Don't check for the app before the first call — the error says so when it's missing.
|
|
11
19
|
|
|
12
20
|
---
|
|
13
21
|
|
|
14
|
-
##
|
|
22
|
+
## Part 1 — Create a service
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
### Step 1: Pick the service type
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
| The user describes | Type | How customers book it |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| a consultation, appointment, meeting, 1-on-1, treatment, haircut, lesson at a time the customer picks | `APPOINTMENT` | The customer picks a free slot during the staff member's working hours. One customer per booking. |
|
|
29
|
+
| a class, group session, drop-in, "yoga every Tuesday", bootcamp class | `CLASS` | The business sets the session times; many customers book each session, and a customer can book one, some or all sessions. |
|
|
30
|
+
| a course, workshop series, program, "6-week course", "8 sessions", teacher training | `COURSE` | The business sets a fixed series with a start and an end; customers book the whole course, never a single session. |
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
When the wording fits none of these, create an `APPOINTMENT`. When it's ambiguous between a class and a course, the deciding question is whether customers can join a single session (class) or must sign up for the whole series (course). See [About Service Types](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-types) for the full comparison.
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
### Step 2: Fill in what the user didn't say
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
- `APPOINTMENT` - Appointments allow customers to book services at their preferred time during the business hours. For example, a hair salon might offer different appointment-based hair cutting and styling services. Appointments appear in the booking calendar once they're booked by a customer. Not-yet-booked times during the business hours are displayed as available slots to potential customers while booking. The availability of the service is based on the availability of the staff member providing it
|
|
26
|
-
- `CLASS` - A class is a single event or a series of recurring events that multiple customers can book. For example, a yoga studio might offer a twice-weekly vinyasa flow class. Classes may have a set end date or continue indefinitely. If a class includes more than a single event, customers can sign up for 1, several, or all of the events. Upon creation, classes are listed immediately in the booking calendar.
|
|
27
|
-
- `COURSE` - A course starts and ends on pre-defined dates with a limited number of events that multiple customers can book. For example, a yoga studio might offer a teacher training course with 5 events. In contrast to classes, customers must book the entire course. Upon creation, courses are displayed immediately in the booking calendar.
|
|
28
|
-
- Staff Member - a resource required in order to provide a service. [REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/create-staff-member) A staff member availability is defined by the schedule associated with the staff member, by default it is the main business schedule and cannot be modified by schedule APIs, but a staff member can have its own schedule by calling `assignWorkingHoursSchedule` which allows the staff member to have its own availability. The property `staffMember.usesDefaultWorkingHours` defines whether the default hours (business hours) are used.
|
|
29
|
-
- Schedule (availability) - availability is defined by `Events` ([REST](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/introduction)) defined on a schedule.
|
|
30
|
-
- The schedule which defines the service availability is based on the service type.
|
|
31
|
-
- For appointment service, it is based on the schedule of staff members which provides it (`service.staffMemberIds` which is mapped to `staffMember.resourceId`). In order to fetch the staff schedule you should retrieve the staff member with `RESOURCE_DETAILS` fieldmask and read the schedule id from the `staffMember.resource.eventsSchedule.id` - This is needed if you wish to define the staff member's availability as part of the process
|
|
32
|
-
- For classes and courses it is based on the schedule of the service itself (`service.schedule`)
|
|
33
|
-
- When creating an APPOINTMENT service and specifying `staffMemberIds`, ensure you are using the staff member's resourceId, not their primary staff member id.
|
|
34
|
-
- Service Images - the service may have several images - `service.media.mainMedia` - presented in the services list, `service.media.coverMedia` - presented in the service page and `service.media.items` - array of images presented as a gallery in the service page for site visitors.
|
|
35
|
-
- In order to add a media (image) to a service, it should first be defined in Wix Media Manager - search existing ([REST](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/search-files)) or new ([REST](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/bulk-import-file))
|
|
36
|
-
- Set only the image **id**, but nest it inside the media item's `image` object: `service.media.mainMedia.image.id` (likewise `service.media.coverMedia.image.id` and `service.media.items[].image.id`). The `id` is the binding field; `url` and dimensions are descriptive and need not be set. ⚠️ Setting the id directly on the media item (`service.media.mainMedia.id`, without the `image` wrapper) returns HTTP 200 but **silently drops** it — the image reads back empty (`image.id: ""`). Because it's a silent 200, a success status is not proof: always nest under `.image` and confirm with a re-query.
|
|
36
|
+
Use the user's values wherever they gave one. For the rest:
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
| Field | APPOINTMENT | CLASS | COURSE |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `name` | the user's wording | the user's wording | the user's wording |
|
|
41
|
+
| `description` | 1–2 sentences you write | 1–2 sentences, say it's a group class | 1–2 sentences, say it's a multi-session course (mention the session count if given) |
|
|
42
|
+
| `defaultCapacity` | `1` (required, must be 1) | `10` (participants per session) | `10` (participants for the whole course) |
|
|
43
|
+
| Duration | 60 minutes, via `schedule.availabilityConstraints.sessionDurations` | each session's start and end — only from the user (Step 5), never a default | each session's start and end — only from the user (Step 5), never a default |
|
|
44
|
+
| Staff | one staff member, via `staffMemberIds` (required unless the service is booked by a resource — see Related recipes) | the instructor goes on the session events, not the service | the instructor goes on the session events, not the service |
|
|
45
|
+
| `onlineBooking` | `{ "enabled": true }` | `{ "enabled": true }` | `{ "enabled": true }` |
|
|
46
|
+
| `category` | an existing category that fits, or a new one (Step 3) | an existing category that fits, or a new one (Step 3) | an existing category that fits, or a new one (Step 3) |
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
**Price.** Never invent one.
|
|
49
|
+
- The user gave a price → `rateType: "FIXED"` with that amount in `fixed.price.value`. For a class it's the price of one session; for a course it's the price of the whole course — don't divide it per session.
|
|
50
|
+
- The user said "free" → `rateType: "NO_FEE"`.
|
|
51
|
+
- The user gave no price → create the service free (`NO_FEE`), say so in the summary, and offer to set a price.
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
- **CLASS**: Business sets recurring times. Multiple customers book same session. Customers can book 1, some, or all sessions in series.
|
|
44
|
-
- **COURSE**: Business sets fixed series. Multiple customers book. Customers must book entire course (all sessions).
|
|
53
|
+
**Session schedule** (CLASS / COURSE). Never invent one — no default days, times or start date. A schedule is the user's to give: "Tuesdays 6–7pm" or "Wednesdays at 19:00 starting the 14th" is one; "a 6-week course", "8 sessions" or "a weekly class" gives only the length or the count, not the days and times. Without days and times, create the service, create no sessions, and ask for them (Step 5, Step 7). This holds when you're working on your own and can't wait for an answer, too: an instruction to proceed on reasonable assumptions covers the service's other fields, never its schedule — sessions you pick are a timetable the owner didn't choose, published to customers.
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
**Currency.** Send only `fixed.price.value`; leave `price.currency` out. The service always takes the site's payment currency — a currency you send is replaced with it (a `"JPY"` price on a USD site is stored as USD). Don't look up the site currency first; read it from the create response when you report the price.
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
**Visibility.** Services are visible by default. When the user asks for a hidden service ("a hidden test course"), add `"hidden": true` to the create body.
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
### Step 3: Read what the site already has
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
- **Behavior**: Service availability based on assigned staff schedules
|
|
54
|
-
- **Example**: Personal training session assigned to specific trainer
|
|
61
|
+
Run these reads before creating anything; they're independent, so run them together.
|
|
55
62
|
|
|
56
|
-
**
|
|
63
|
+
**Staff members** — required for an APPOINTMENT, and the instructor for CLASS or COURSE sessions. For a CLASS or COURSE whose schedule the user didn't give, skip this read: no sessions are created yet, so no instructor is needed.
|
|
57
64
|
|
|
58
|
-
-
|
|
59
|
-
- **Behavior**: Service uses its own schedule (`service.schedule`), not staff schedules
|
|
60
|
-
- **Workaround**: Staff association must be handled separately through calendar events or other mechanisms
|
|
61
|
-
- **Example**: Yoga class where any qualified instructor can teach
|
|
65
|
+
`POST https://www.wixapis.com/bookings/v1/staff-members/query`
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
```json
|
|
68
|
+
{ "query": {} }
|
|
69
|
+
```
|
|
64
70
|
|
|
65
|
-
|
|
71
|
+
Use each staff member's `resourceId` — not its `id` — everywhere this recipe asks for a staff ID. Pick the staff member the user named; otherwise the one with `default: true`; otherwise the first one. If the site has no staff members, create one with [Bookings Staff Setup](bookings-staff-setup.md) first.
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
- If the service type is `CLASS` or `COURSE` I MUST read the full articles service's _schedule_ and _events_ mentioned before
|
|
69
|
-
- If the service type is `APPOINTMENT` I MUST read the relevant full article about staff members ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/introduction)) in order to determine whether I should create a new staff member (or members)
|
|
70
|
-
- For free service I MUST set `service.payment.rateType` as `"NO_FEE"` and `service.payment.options.inPerson` as `true` (at least one payment option must be true)
|
|
71
|
-
- For paid service I MUST set the `service.payment.fixed.price.value` (must be above 0) as well as `service.payment.fixed.price.currency`
|
|
72
|
-
- When changing a free service to a paid service, I MUST update `service.payment.rateType` from `"NO_FEE"` to `"FIXED"` in the same request where I set `service.payment.fixed.price`; patching only `fixed.price` on a `NO_FEE` service fails validation.
|
|
73
|
+
**Categories:**
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
`POST https://www.wixapis.com/bookings/v2/categories/query`
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
| FIXED | false | true | ✓ |
|
|
80
|
-
| FIXED | true | true | ✓ |
|
|
81
|
-
| VARIED | true | false | ✓ |
|
|
82
|
-
| VARIED | false | true | ✓ |
|
|
83
|
-
| NO_FEE | false | true | ✓ |
|
|
84
|
-
| NO_FEE | true | false | ✗ (online not allowed for NO_FEE) |
|
|
85
|
-
| Any | false | false | ✗ (at least one must be true) |
|
|
77
|
+
```json
|
|
78
|
+
{ "query": {} }
|
|
79
|
+
```
|
|
86
80
|
|
|
87
|
-
|
|
88
|
-
- I should pay close attention to all required fields, data types, enum values, and specific ID types (e.g., resourceId vs. id) as defined in the detailed schema of each API endpoint. The overview article serves as a guide but doesn't replace the need to consult these specifics.
|
|
81
|
+
A service without a category isn't shown on the live site, and services aren't assigned one automatically, so every create body carries a `category.id`. Use the category the user named; otherwise an existing one that fits the service. A general one such as "Our Services" (a fresh Bookings install has it) fits anything, but a category meant for something else doesn't — a yoga class doesn't go under a template's "Styling". If no category fits, or the user named one that doesn't exist, create it — `POST https://www.wixapis.com/bookings/v2/categories` with `{ "category": { "name": "Yoga" } }` (the user's name for it, or a short name for the kind of service) — use the returned `category.id`, and mention the new category in the summary.
|
|
89
82
|
|
|
90
|
-
|
|
83
|
+
**Existing services** (duplicate check):
|
|
91
84
|
|
|
92
|
-
|
|
85
|
+
`POST https://www.wixapis.com/bookings/v2/services/query`
|
|
93
86
|
|
|
94
|
-
|
|
87
|
+
```json
|
|
88
|
+
{ "query": { "paging": { "limit": 100 } } }
|
|
89
|
+
```
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
- **UI Impact**: Many booking interfaces filter services by `category.id`, hiding uncategorized services
|
|
98
|
-
- **Best Practice**: Always assign services to appropriate categories during creation
|
|
91
|
+
A site with more than 100 services needs more pages: repeat with `"offset": 100`, `200`… inside `paging` until a page returns fewer than 100. If a service with the same or a very similar name exists, tell the user before creating another one.
|
|
99
92
|
|
|
100
|
-
|
|
93
|
+
### Step 4: Create the service
|
|
101
94
|
|
|
102
|
-
|
|
103
|
-
2. **Create new category if needed** using [Create Category](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)
|
|
104
|
-
3. **Assign category during service creation** by including `category.id` in the service object
|
|
105
|
-
4. **Update existing services** using [Update Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service) to add missing categories
|
|
95
|
+
`POST https://www.wixapis.com/bookings/v2/bulk/services/create` — one call creates up to 100 services. Always send `"returnEntity": true`: without it the response carries only `results[i].itemMetadata.id`, with no `schedule.id` to schedule sessions on.
|
|
106
96
|
|
|
107
|
-
**
|
|
97
|
+
**APPOINTMENT** (60-minute paid consultation):
|
|
108
98
|
|
|
109
99
|
```json
|
|
110
100
|
{
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
101
|
+
"returnEntity": true,
|
|
102
|
+
"services": [{
|
|
103
|
+
"name": "Strategy Consultation",
|
|
104
|
+
"description": "A one-on-one session to map out your next quarter.",
|
|
105
|
+
"type": "APPOINTMENT",
|
|
106
|
+
"defaultCapacity": 1,
|
|
107
|
+
"onlineBooking": { "enabled": true },
|
|
108
|
+
"staffMemberIds": ["<STAFF_RESOURCE_ID>"],
|
|
109
|
+
"schedule": { "availabilityConstraints": { "sessionDurations": [60] } },
|
|
110
|
+
"payment": {
|
|
111
|
+
"rateType": "FIXED",
|
|
112
|
+
"options": { "online": true, "inPerson": false },
|
|
113
|
+
"fixed": { "price": { "value": "75" } }
|
|
114
|
+
},
|
|
115
|
+
"category": { "id": "<CATEGORY_ID>" }
|
|
116
|
+
}]
|
|
116
117
|
}
|
|
117
118
|
```
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
### Querying Existing Services
|
|
120
|
+
**CLASS or COURSE** (paid yoga class for 12 — for a course, change `type` to `"COURSE"`):
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"returnEntity": true,
|
|
125
|
+
"services": [{
|
|
126
|
+
"name": "Vinyasa Yoga",
|
|
127
|
+
"description": "A flowing group yoga class for all levels.",
|
|
128
|
+
"type": "CLASS",
|
|
129
|
+
"defaultCapacity": 12,
|
|
130
|
+
"onlineBooking": { "enabled": true },
|
|
131
|
+
"payment": {
|
|
132
|
+
"rateType": "FIXED",
|
|
133
|
+
"options": { "online": true, "inPerson": false },
|
|
134
|
+
"fixed": { "price": { "value": "25" } }
|
|
135
|
+
},
|
|
136
|
+
"category": { "id": "<CATEGORY_ID>" }
|
|
137
|
+
}]
|
|
138
|
+
}
|
|
139
|
+
```
|
|
124
140
|
|
|
125
|
-
|
|
141
|
+
For a CLASS or COURSE, don't send `staffMemberIds` (it's read-only for these types — the API fills it from the staff on the service's recurring sessions, so staff on single, non-recurring sessions don't appear there; query the calendar events for the full list) or `sessionDurations`, and don't put sessions anywhere in this body (`course.sessions`, `CourseSession` and the like do not create sessions).
|
|
126
142
|
|
|
127
|
-
|
|
143
|
+
**Free service** — replace `payment` with:
|
|
128
144
|
|
|
129
|
-
|
|
145
|
+
```json
|
|
146
|
+
"payment": { "rateType": "NO_FEE", "options": { "online": false, "inPerson": true } }
|
|
147
|
+
```
|
|
130
148
|
|
|
131
|
-
|
|
132
|
-
2. **Create category if needed** using `createCategory` API ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)) if no suitable category exists
|
|
133
|
-
3. **Record category ID** for use in service creation - this prevents services from being hidden in UI filters
|
|
149
|
+
**Payment options** — at least one of `options.online` / `options.inPerson` must be `true`, even for a free service, and `online` is allowed only for paid rate types:
|
|
134
150
|
|
|
135
|
-
|
|
151
|
+
| `rateType` | `online` | `inPerson` | Valid? |
|
|
152
|
+
|---|---|---|---|
|
|
153
|
+
| `FIXED` | true | false | ✓ |
|
|
154
|
+
| `FIXED` | false | true | ✓ |
|
|
155
|
+
| `FIXED` | true | true | ✓ |
|
|
156
|
+
| `NO_FEE` | false | true | ✓ |
|
|
157
|
+
| `NO_FEE` | true | false | ✗ online needs FIXED or VARIED |
|
|
158
|
+
| any | false | false | ✗ one must be true |
|
|
136
159
|
|
|
137
|
-
|
|
138
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/categories/query' \
|
|
139
|
-
-H 'Authorization: <AUTH>' \
|
|
140
|
-
-H 'Content-Type: application/json' \
|
|
141
|
-
-d '{ "query": {} }'
|
|
142
|
-
```
|
|
160
|
+
Price-by-variant (`VARIED`), custom-text (`CUSTOM`), deposits and pricing plans are described in [About Service Payments](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-payments).
|
|
143
161
|
|
|
144
|
-
**
|
|
162
|
+
**Read the response.** A `200` can still carry a failed item, so check before reporting success:
|
|
145
163
|
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"results": [{
|
|
167
|
+
"itemMetadata": { "id": "<SERVICE_ID>", "originalIndex": 0, "success": true },
|
|
168
|
+
"item": {
|
|
169
|
+
"id": "<SERVICE_ID>",
|
|
170
|
+
"type": "CLASS",
|
|
171
|
+
"payment": { "rateType": "FIXED", "fixed": { "price": { "value": "25", "currency": "USD" } } },
|
|
172
|
+
"schedule": { "id": "<SERVICE_SCHEDULE_ID>" },
|
|
173
|
+
"revision": "1"
|
|
174
|
+
}
|
|
175
|
+
}],
|
|
176
|
+
"bulkActionMetadata": { "totalSuccesses": 1, "totalFailures": 0, "undetailedFailures": 0 }
|
|
177
|
+
}
|
|
151
178
|
```
|
|
152
179
|
|
|
153
|
-
|
|
180
|
+
- The service is directly under `results[i].item` — there is no `item.service`. Match items to your request by `itemMetadata.originalIndex`.
|
|
181
|
+
- `itemMetadata.success: false` comes with `itemMetadata.error` (code and description). Fix and resend only the failed services.
|
|
182
|
+
- Keep `item.id` (the service ID) and, for a CLASS or COURSE, `item.schedule.id` for Step 5.
|
|
154
183
|
|
|
155
|
-
|
|
184
|
+
**Optional fields:**
|
|
185
|
+
- **Images** — the file must already be in the Wix Media Manager ([Search Files](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/search-files), or [Bulk Import File](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/bulk-import-file) for a URL). Set only its id, nested under `image`: `"media": { "mainMedia": { "image": { "id": "<FILE_ID>" } } }` (`mainMedia` shows in the services list, `coverMedia` on the service page, `items[]` is the page gallery). An id set directly on the media item (`mainMedia.id`) returns `200` but is silently dropped — read the service back to confirm the image stuck.
|
|
186
|
+
- **Locations** — `"locations": [{ "type": "BUSINESS", "business": { "id": "<LOCATION_ID>" } }]` for a business location, `[{ "type": "CUSTOMER" }]` for an appointment at the customer's place (appointments only), or `[{ "type": "CUSTOM", "custom": { "address": { … } } }]`. All of a course's sessions take place at the same location. To change the locations of an existing service, use [Set Service Locations](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/set-service-locations), not Update Service. Details: [About Service Locations](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-locations).
|
|
156
187
|
|
|
157
|
-
|
|
158
|
-
2. For new staff, create using `createStaffMember` API ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/create-staff-member)) and keep the response `staffMember.id` and `resourceId`
|
|
159
|
-
3. If you wish to update working hours, call `getStaffMember` API ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/get-staff-member)) to get `resource.eventsSchedule.id`
|
|
188
|
+
### Step 5: Schedule the sessions (CLASS and COURSE)
|
|
160
189
|
|
|
161
|
-
|
|
190
|
+
A CLASS or COURSE has no sessions when it's created, so customers can't book it, and a course with no future sessions shows as ended on its service page. Sessions are Calendar events on the service's own schedule (`item.schedule.id` from Step 4).
|
|
162
191
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
-H 'Authorization: <AUTH>' \
|
|
166
|
-
-H 'Content-Type: application/json' \
|
|
167
|
-
-d '{
|
|
168
|
-
"query": {},
|
|
169
|
-
"fields": ["RESOURCE_DETAILS"]
|
|
170
|
-
}'
|
|
171
|
-
```
|
|
192
|
+
- **The user gave days and times** ("Tuesdays at 6pm", "8 Wednesday evenings from the 14th") → create the sessions now.
|
|
193
|
+
- **They didn't** → create only the service, ask for the session days and times, and tell the user plainly that the service can't be booked until sessions exist. Don't make up a schedule — not even when you're told to proceed without asking; in that case finish with the service alone and name exactly what's missing.
|
|
172
194
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
**Staff Selection Strategy:**
|
|
176
|
-
|
|
177
|
-
- If a staff member has `default: true` → use it
|
|
178
|
-
- If only one staff member exists → use it
|
|
179
|
-
- If multiple exist → pick the first or most appropriate
|
|
180
|
-
- If none exist → create one using the [Staff Setup recipe](bookings-staff-setup.md)
|
|
181
|
-
|
|
182
|
-
**Service Type Requirements:**
|
|
183
|
-
|
|
184
|
-
- **APPOINTMENT**: `staffMemberIds` is **required** - API will fail without it
|
|
185
|
-
- **CLASS/COURSE**: `staffMemberIds` is ignored; use `service.schedule` instead
|
|
186
|
-
|
|
187
|
-
### 2. Creating or Updating a service
|
|
188
|
-
|
|
189
|
-
Based on the information gathered above, use the relevant API based on the desired outcome.
|
|
190
|
-
|
|
191
|
-
- **Create services**: `bulkCreateServices` endpoint ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services))
|
|
192
|
-
- **Update single service**: `updateService` endpoint ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service))
|
|
193
|
-
- **Update services (bulk)**: `bulkUpdateServices` ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services))
|
|
194
|
-
- **Update by filter**: `bulkUpdateServicesByFilter` ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services-by-filter))
|
|
195
|
-
- **Get single service**: `getService` endpoint ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/get-service))
|
|
196
|
-
|
|
197
|
-
**Create Service Example (paid APPOINTMENT, 60 minutes):**
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
|
|
201
|
-
-H 'Authorization: <AUTH>' \
|
|
202
|
-
-H 'Content-Type: application/json' \
|
|
203
|
-
-d '{
|
|
204
|
-
"returnEntity": true,
|
|
205
|
-
"services": [{
|
|
206
|
-
"name": "Consultation",
|
|
207
|
-
"type": "APPOINTMENT",
|
|
208
|
-
"onlineBooking": { "enabled": true },
|
|
209
|
-
"staffMemberIds": ["<RESOURCE_ID_FROM_STEP_1>"],
|
|
210
|
-
"schedule": {
|
|
211
|
-
"availabilityConstraints": {
|
|
212
|
-
"sessionDurations": [60]
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
"payment": {
|
|
216
|
-
"rateType": "FIXED",
|
|
217
|
-
"options": { "online": true, "inPerson": false },
|
|
218
|
-
"fixed": {
|
|
219
|
-
"price": { "value": "50", "currency": "USD" }
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
"category": {
|
|
223
|
-
"id": "<CATEGORY_ID_FROM_STEP_0>"
|
|
224
|
-
}
|
|
225
|
-
}]
|
|
226
|
-
}'
|
|
227
|
-
```
|
|
195
|
+
Create the sessions with `POST https://www.wixapis.com/calendar/v3/bulk/events/create` (up to 50 events per call). The instructor in each event's `resources` is a staff `resourceId` from Step 3 — if you skipped that read because the schedule came later, run it now.
|
|
228
196
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
**Create Service Example (free APPOINTMENT, 60 minutes):**
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
|
|
235
|
-
-H 'Authorization: <AUTH>' \
|
|
236
|
-
-H 'Content-Type: application/json' \
|
|
237
|
-
-d '{
|
|
238
|
-
"returnEntity": true,
|
|
239
|
-
"services": [{
|
|
240
|
-
"name": "Free Consultation",
|
|
241
|
-
"type": "APPOINTMENT",
|
|
242
|
-
"onlineBooking": { "enabled": true },
|
|
243
|
-
"staffMemberIds": ["<RESOURCE_ID_FROM_STEP_1>"],
|
|
244
|
-
"schedule": {
|
|
245
|
-
"availabilityConstraints": {
|
|
246
|
-
"sessionDurations": [60]
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
"payment": {
|
|
250
|
-
"rateType": "NO_FEE",
|
|
251
|
-
"options": { "online": false, "inPerson": true }
|
|
252
|
-
},
|
|
253
|
-
"category": {
|
|
254
|
-
"id": "<CATEGORY_ID_FROM_STEP_0>"
|
|
255
|
-
}
|
|
256
|
-
}]
|
|
257
|
-
}'
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
**Create Service Example (CLASS with capacity):**
|
|
197
|
+
**Weekly CLASS** — every Tuesday 18:00–19:00 from the first Tuesday the user gave, no end date:
|
|
261
198
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
-d '{
|
|
269
|
-
"returnEntity": true,
|
|
270
|
-
"services": [{
|
|
271
|
-
"name": "Yoga Class",
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"returnEntity": true,
|
|
202
|
+
"events": [{
|
|
203
|
+
"event": {
|
|
204
|
+
"scheduleId": "<SERVICE_SCHEDULE_ID>",
|
|
272
205
|
"type": "CLASS",
|
|
273
|
-
"
|
|
274
|
-
"
|
|
275
|
-
"
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
"category": {
|
|
283
|
-
"id": "<CATEGORY_ID_FROM_STEP_0>"
|
|
284
|
-
}
|
|
285
|
-
}]
|
|
286
|
-
}'
|
|
206
|
+
"start": { "localDate": "<FIRST_TUESDAY>T18:00:00" },
|
|
207
|
+
"end": { "localDate": "<FIRST_TUESDAY>T19:00:00" },
|
|
208
|
+
"resources": [{ "id": "<STAFF_RESOURCE_ID>", "permissionRole": "WRITER" }],
|
|
209
|
+
"recurrenceRule": { "frequency": "WEEKLY", "interval": 1, "days": ["TUESDAY"] }
|
|
210
|
+
}
|
|
211
|
+
}]
|
|
212
|
+
}
|
|
287
213
|
```
|
|
288
214
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
**Required Fields:**
|
|
215
|
+
This creates one `MASTER` event, and the calendar generates a weekly `INSTANCE` for each Tuesday. To stop the series on a date, add `"until": { "localDate": "<LAST_SESSION_DATE>T19:00:00" }` to `recurrenceRule`.
|
|
292
216
|
|
|
293
|
-
|
|
294
|
-
- `type` - `APPOINTMENT`, `CLASS`, or `COURSE`
|
|
295
|
-
- `onlineBooking: { enabled: true }` - Required for all services
|
|
296
|
-
- `staffMemberIds` - **Required for APPOINTMENT only** (use `resourceId` values); ignored for CLASS/COURSE
|
|
297
|
-
- `schedule.availabilityConstraints.sessionDurations` - Duration in minutes (APPOINTMENT only)
|
|
298
|
-
- `defaultCapacity` - **Required for CLASS/COURSE** (max participants per session)
|
|
299
|
-
- `payment.options` - At least one of `online` or `inPerson` must be `true` (required for all services, including free; see validation table above)
|
|
217
|
+
**COURSE** — one event per session, all in one call (here the first two of a weekly series):
|
|
300
218
|
|
|
301
|
-
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"returnEntity": true,
|
|
222
|
+
"events": [
|
|
223
|
+
{ "event": {
|
|
224
|
+
"scheduleId": "<SERVICE_SCHEDULE_ID>",
|
|
225
|
+
"type": "COURSE",
|
|
226
|
+
"start": { "localDate": "<SESSION_1_DATE>T18:00:00" },
|
|
227
|
+
"end": { "localDate": "<SESSION_1_DATE>T20:00:00" },
|
|
228
|
+
"resources": [{ "id": "<STAFF_RESOURCE_ID>", "permissionRole": "WRITER" }]
|
|
229
|
+
} },
|
|
230
|
+
{ "event": {
|
|
231
|
+
"scheduleId": "<SERVICE_SCHEDULE_ID>",
|
|
232
|
+
"type": "COURSE",
|
|
233
|
+
"start": { "localDate": "<SESSION_2_DATE>T18:00:00" },
|
|
234
|
+
"end": { "localDate": "<SESSION_2_DATE>T20:00:00" },
|
|
235
|
+
"resources": [{ "id": "<STAFF_RESOURCE_ID>", "permissionRole": "WRITER" }]
|
|
236
|
+
} }
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
```
|
|
302
240
|
|
|
303
|
-
|
|
304
|
-
-
|
|
241
|
+
Rules for every session event:
|
|
242
|
+
- Wrap each one as `{ "event": { … } }`.
|
|
243
|
+
- `scheduleId` is the **service's** `schedule.id` — not a staff member's schedule — and `type` matches the service type (`CLASS` or `COURSE`).
|
|
244
|
+
- `resources` must hold at least one resource; without it the call fails with `400 resources must have at least 1 resource for class events`. Use the instructor's staff `resourceId`.
|
|
245
|
+
- Every resource needs `"permissionRole": "WRITER"`. Without it the whole call fails with `400 resources.permissionRole must not be UNKNOWN_ROLE`.
|
|
246
|
+
- `start.localDate` / `end.localDate` are local times without a `Z`, in the schedule's time zone (the site's, unless you set `event.timeZone`). A recurring event must start today or later — check the current date before you build the dates.
|
|
247
|
+
- A `recurrenceRule` takes exactly one day. For "Tuesdays and Thursdays", send two events, one per day.
|
|
248
|
+
- Leave `totalCapacity` out: sessions inherit the service's `defaultCapacity`, and setting it detaches that session from later capacity changes.
|
|
305
249
|
|
|
306
|
-
**
|
|
250
|
+
**Read the response** the same way as Step 4: check `bulkActionMetadata.totalFailures` and each `results[i].itemMetadata.success`, and fix and resend only the failed events. A `400` (no `results` at all) means nothing was created.
|
|
307
251
|
|
|
308
|
-
|
|
252
|
+
**Confirm the sessions exist** before you call the service bookable:
|
|
309
253
|
|
|
310
|
-
|
|
311
|
-
# First, get current service to obtain revision
|
|
312
|
-
curl -X GET 'https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>' \
|
|
313
|
-
-H 'Authorization: <AUTH>'
|
|
254
|
+
`POST https://www.wixapis.com/calendar/v3/events/query`
|
|
314
255
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
"revision": "<REVISION_FROM_GET>",
|
|
322
|
-
"category": {
|
|
323
|
-
"id": "<CATEGORY_ID>"
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}'
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
**Update free service to fixed price:**
|
|
330
|
-
|
|
331
|
-
When an existing service has `payment.rateType: "NO_FEE"` and the user asks to set a price, convert it to `FIXED` and set the price in the same update.
|
|
332
|
-
|
|
333
|
-
```bash
|
|
334
|
-
# First, get current service to obtain revision and current payment settings
|
|
335
|
-
curl -X GET 'https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>' \
|
|
336
|
-
-H 'Authorization: <AUTH>'
|
|
337
|
-
|
|
338
|
-
curl -X PATCH 'https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>' \
|
|
339
|
-
-H 'Authorization: <AUTH>' \
|
|
340
|
-
-H 'Content-Type: application/json' \
|
|
341
|
-
-d '{
|
|
342
|
-
"service": {
|
|
343
|
-
"revision": "<REVISION_FROM_GET>",
|
|
344
|
-
"payment": {
|
|
345
|
-
"rateType": "FIXED",
|
|
346
|
-
"options": { "online": false, "inPerson": true },
|
|
347
|
-
"fixed": {
|
|
348
|
-
"price": { "value": "200", "currency": "<SITE_CURRENCY>" }
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}'
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"fromLocalDate": "<TODAY>T00:00:00",
|
|
259
|
+
"toLocalDate": "<AFTER_LAST_SESSION>T00:00:00",
|
|
260
|
+
"query": { "filter": { "scheduleId": "<SERVICE_SCHEDULE_ID>" } }
|
|
261
|
+
}
|
|
353
262
|
```
|
|
354
263
|
|
|
355
|
-
|
|
264
|
+
The result lists the generated sessions (`INSTANCE` events for a weekly class, the single events for a course). For a course, the service itself also reports the span: `GET https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>` returns `schedule.firstSessionStart` and `schedule.lastSessionEnd` once sessions exist.
|
|
356
265
|
|
|
357
|
-
|
|
266
|
+
**Change sessions later** with `POST https://www.wixapis.com/calendar/v3/bulk/events/update`, sending each event's `id`, its current `revision` and only the fields that change:
|
|
358
267
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"events": [{
|
|
271
|
+
"event": {
|
|
272
|
+
"id": "<EVENT_ID>",
|
|
273
|
+
"revision": "<EVENT_REVISION>",
|
|
274
|
+
"start": { "localDate": "<NEW_DATE>T19:00:00" },
|
|
275
|
+
"end": { "localDate": "<NEW_DATE>T20:00:00" }
|
|
276
|
+
}
|
|
277
|
+
}]
|
|
278
|
+
}
|
|
279
|
+
```
|
|
363
280
|
|
|
364
|
-
|
|
281
|
+
For a weekly class, update the `MASTER` event (its id is in the create response, or query events with `"recurrenceType": ["MASTER"]`) to move every future session; updating one `INSTANCE` changes only that session. Details: [Bulk Update Event](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-update-event).
|
|
365
282
|
|
|
366
|
-
|
|
283
|
+
### Step 6: Appointment availability
|
|
367
284
|
|
|
368
|
-
|
|
369
|
-
- `event.scheduleId` — use the staff member's events schedule ID for APPOINTMENT availability, or `service.schedule.id` for CLASS/COURSE.
|
|
370
|
-
- `event.type` — set to `WORKING_HOURS` for staff availability, `CLASS` for class sessions, or `COURSE` for course sessions.
|
|
285
|
+
An APPOINTMENT has no events of its own: its free slots come from the working hours of the staff in `staffMemberIds`, which by default follow the business hours. If the user wants different hours for that staff member, follow [Bookings Staff Setup](bookings-staff-setup.md) — it detaches the staff member from the business hours and creates `WORKING_HOURS` events on the staff member's own schedule.
|
|
371
286
|
|
|
372
|
-
###
|
|
287
|
+
### Step 7: Report back
|
|
373
288
|
|
|
374
|
-
|
|
289
|
+
Base the summary on the API responses, not on what you sent:
|
|
290
|
+
1. **What was created** — name, type, price as stored (amount and currency; "per session" for a class, "for the whole course" for a course; "free" if no price was given, with an offer to set one), capacity, duration or staff for an appointment, category, and hidden if it is.
|
|
291
|
+
2. **Assumptions** — every default from Step 2 you applied ("I set capacity to 10 since you didn't say").
|
|
292
|
+
3. **Sessions** (CLASS / COURSE) — the sessions you created and confirmed: list each session's date and time (for a weekly class with no end date, the weekday, time and first date). If none exist yet, say the service can't be booked until it has sessions, and end with a direct question for them: the weekday(s), start and end time, and first date — for a course, the date of each session or the weekly pattern and how many sessions.
|
|
293
|
+
4. **What you can change** — offer to adjust price, capacity, duration, staff or schedule.
|
|
375
294
|
|
|
376
|
-
|
|
377
|
-
- **Cause**: APPOINTMENT services cannot be created without at least one staff member assigned
|
|
378
|
-
- **Solution**: Query staff members first (Step 1) to get a valid `resourceId`, then include it in `staffMemberIds`
|
|
295
|
+
---
|
|
379
296
|
|
|
380
|
-
|
|
297
|
+
## Part 2 — Change an existing service
|
|
381
298
|
|
|
382
|
-
|
|
383
|
-
- **Cause**: All services (including free) require at least one payment option to be `true`
|
|
384
|
-
- **Solution**: Add `"options": { "online": true, "inPerson": false }` (or `inPerson: true` for free services) to the `payment` object
|
|
299
|
+
### Find it and read its revision
|
|
385
300
|
|
|
386
|
-
|
|
301
|
+
When the user gave a service ID, use it. Otherwise list the services and match the name the user used:
|
|
387
302
|
|
|
388
|
-
|
|
389
|
-
- **Cause**: `payment.options.online: true` is only valid for paid services (FIXED or VARIED)
|
|
390
|
-
- **Solution**: For free services (NO_FEE), use `"options": { "online": false, "inPerson": true }`
|
|
303
|
+
`POST https://www.wixapis.com/bookings/v2/services/query`
|
|
391
304
|
|
|
392
|
-
|
|
305
|
+
```json
|
|
306
|
+
{ "query": { "paging": { "limit": 100 } } }
|
|
307
|
+
```
|
|
393
308
|
|
|
394
|
-
|
|
395
|
-
- **Cause**: The service is still `NO_FEE` while the update tries to set `fixed.price`
|
|
396
|
-
- **Solution**: Change `payment.rateType` to `"FIXED"` and include `payment.fixed.price` in the same update request
|
|
309
|
+
Page with `offset` as in Step 3 on a site with more than 100 services. If more than one service matches, ask the user which one; if none does, say so rather than creating one. Then read it to get its current `revision` and current values:
|
|
397
310
|
|
|
398
|
-
|
|
311
|
+
`GET https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>`
|
|
399
312
|
|
|
400
|
-
|
|
401
|
-
- **Root Cause**: Many UI implementations filter by `category.id` existence or specific category values
|
|
402
|
-
- **Solution**: Query all services, identify those missing categories, and update them using bulk update operations
|
|
403
|
-
- **Prevention**: Always assign categories during service creation (Step 0)
|
|
313
|
+
### Update it
|
|
404
314
|
|
|
405
|
-
**
|
|
315
|
+
`PATCH https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>` — send only the fields you're changing, with the current `revision` **inside** the `service` object (a `revision` at the top level fails with `revision must not be empty`):
|
|
406
316
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"service": {
|
|
320
|
+
"revision": "<REVISION_FROM_GET>",
|
|
321
|
+
"category": { "id": "<CATEGORY_ID>" }
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
410
325
|
|
|
411
|
-
|
|
326
|
+
The same shape changes the name, description, capacity, `hidden` (`true` hides the service from the site's booking pages, `false` shows it again) or `onlineBooking`. Update the existing service — don't delete and recreate it, which loses its bookings and sessions.
|
|
412
327
|
|
|
413
|
-
|
|
414
|
-
- **Solution**: Install Wix Bookings app using Apps Installer API before creating services
|
|
415
|
-
- **Verification**: Query existing services to confirm app installation
|
|
328
|
+
**Free → paid.** A `NO_FEE` service becomes paid only when one update sends the whole payment object — `rateType: "FIXED"`, `options` and `fixed.price` together. Send the `options` the GET returned (a free service usually has `inPerson: true`), so customers keep paying the way they already could; turn on `online` only when the user asks for online payment. Patching just `fixed.price` fails validation (`Payment of type FREE cannot be used with payment.rate`, or `payment.type Payment type must be set to FIXED`):
|
|
416
329
|
|
|
417
|
-
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"service": {
|
|
333
|
+
"revision": "<REVISION_FROM_GET>",
|
|
334
|
+
"payment": {
|
|
335
|
+
"rateType": "FIXED",
|
|
336
|
+
"options": { "online": false, "inPerson": true },
|
|
337
|
+
"fixed": { "price": { "value": "35" } }
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
```
|
|
418
342
|
|
|
419
|
-
|
|
420
|
-
- **Solution**: Always use `staffMember.resourceId`, not `staffMember.id`
|
|
421
|
-
- **Verification**: Query staff with `RESOURCE_DETAILS` fieldMask to get correct IDs
|
|
343
|
+
The price takes the site's currency, as on create. To change only the amount of a service that is already `FIXED`, send the same payment object with the new value.
|
|
422
344
|
|
|
423
|
-
**
|
|
345
|
+
**Several services at once.** [Bulk Update Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services) takes a list of services (each with its own `id` and `revision`); [Bulk Update Services By Filter](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services-by-filter) applies one change to every service a filter matches ("make all my services 60 minutes").
|
|
424
346
|
|
|
425
|
-
|
|
426
|
-
-
|
|
427
|
-
|
|
428
|
-
- CLASS/COURSE: Use service schedule ID (`service.schedule.id`)
|
|
347
|
+
**Changing the type** (`"type": "COURSE"` in the same PATCH) deletes the service's schedule and sessions and creates a new schedule. Confirm with the user before doing it, then schedule the sessions again on the new `schedule.id` (Step 5).
|
|
348
|
+
- An APPOINTMENT that already has future bookings can't change type — the update fails with `can't change a service of type appointment after it has been booked`. Tell the user; don't cancel their bookings to get around it.
|
|
349
|
+
- Changing to or from COURSE resets the service's locations to the site's default business location; restore any other location the user needs with [Set Service Locations](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/set-service-locations). Changing an APPOINTMENT to a CLASS or COURSE also clears its `staffMemberIds` and session durations.
|
|
429
350
|
|
|
430
|
-
**
|
|
351
|
+
**Deleting a service**: `DELETE https://www.wixapis.com/bookings/v2/services/<SERVICE_ID>` cancels its future sessions. Confirm with the user first.
|
|
431
352
|
|
|
432
|
-
|
|
433
|
-
- **Cause**: `revision` placed at top level of request body instead of inside `service` object
|
|
434
|
-
- **Solution**: Structure as `{ "service": { "revision": "...", ...fields } }` - get revision value from GET response first
|
|
353
|
+
---
|
|
435
354
|
|
|
436
|
-
|
|
355
|
+
## Errors
|
|
356
|
+
|
|
357
|
+
| Error | Cause | Fix |
|
|
358
|
+
|---|---|---|
|
|
359
|
+
| `service of type appointment requires at least one staff member id` | APPOINTMENT without `staffMemberIds` | Query staff (Step 3) and send a `resourceId` |
|
|
360
|
+
| `primary_resource_type is required for appointment services without staff members` | An APPOINTMENT booked by a room or equipment | Follow [Multi-Resource Service Creation](multi-resource-service-creation.md) for the body |
|
|
361
|
+
| `INVALID_PAYMENT_OPTIONS` — "mandatory to specify either payment.options.online or payment.options.inPerson as true" | No payment option set | Set `inPerson: true` (free) or `online: true` (paid) |
|
|
362
|
+
| `INVALID_PAYMENT_OPTIONS` — "online as true is applicable only to payments of types FIXED or VARIED" | `online: true` on a `NO_FEE` service | Free services use `online: false, inPerson: true` |
|
|
363
|
+
| `Payment of type FREE cannot be used with payment.rate` | Price set on a `NO_FEE` service without changing `rateType` | Send `rateType: "FIXED"`, `options` and `fixed.price` in one update |
|
|
364
|
+
| `revision must not be empty` / `service.revision is required` | `revision` missing or outside `service` | `{ "service": { "revision": "…", … } }`, revision from a fresh GET |
|
|
365
|
+
| `resources.permissionRole must not be UNKNOWN_ROLE` | Session resource without `permissionRole` | `"resources": [{ "id": "…", "permissionRole": "WRITER" }]` |
|
|
366
|
+
| `resources must have at least 1 resource for class events` | Session event without `resources` | Add the instructor's staff `resourceId` |
|
|
367
|
+
| Course page says "Ended" or "This service is not available" | The course has no future sessions | Create the sessions (Step 5) and confirm them |
|
|
368
|
+
| `428` app not installed | Wix Bookings isn't on the site | Install it with [Install Wix Apps](../app-installation/install-wix-apps.md) and retry |
|
|
437
369
|
|
|
438
|
-
|
|
439
|
-
- `onlineBooking` Field: The onlineBooking object (e.g., {"enabled": true}) is a required field when creating services, even if not explicitly highlighted as mandatory in the high-level overview. This is a schema-level requirement.
|
|
440
|
-
- Event Creation (BulkCreateEvents): When specifying recurrenceRule.days, I MUST use full day names (e.g., "TUESDAY", "FRIDAY")
|
|
441
|
-
- The recurrenceRule.days field within an event object can only accept a single day of the week (e.g., ["TUESDAY"]).
|
|
442
|
-
- If I need to set up recurring events for multiple days of the week (e.g., a staff member working every Tuesday and Friday), I MUST define a separate event for each day and send them as separate items for BulkCreateEvents.
|
|
443
|
-
- Start Dates for Recurring Events: Recurring events must have a start.localDate that is today or in the future, relative to the server's current time. If I am not sure what the current date and time are I MUST check it.
|
|
444
|
-
- When setting `event.type` as `WORKING_HOURS` (APPOINTMENT) I MUST call `assignWorkingHoursSchedule` BEFORE CREATING THE EVENTS so that the staff member is no longer linked to the business working hours
|
|
445
|
-
- When setting `event.type` as `CLASS` or `COURSE` I MUST use the service schedule id, so the service has to exist (created/updated) before setting the availability of it
|
|
370
|
+
---
|
|
446
371
|
|
|
447
|
-
##
|
|
372
|
+
## Reference
|
|
448
373
|
|
|
449
|
-
- [Query
|
|
450
|
-
- [
|
|
451
|
-
- [
|
|
452
|
-
- [
|
|
453
|
-
- [Create
|
|
454
|
-
- [
|
|
455
|
-
- [Query Staff Members](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members)
|
|
456
|
-
- [Bulk Create Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services)
|
|
457
|
-
- [Bulk Update Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services)
|
|
458
|
-
- [Bulk Update Services By Filter](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services-by-filter)
|
|
459
|
-
- [Assign Working Hours Schedule](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/assign-working-hours-schedule)
|
|
460
|
-
- [Bulk Create Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event)
|
|
461
|
-
- [Bulk Update Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-update-event)
|
|
462
|
-
- [Media Manager: Search Files](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/search-files)
|
|
463
|
-
- [Media Manager: Bulk Import File](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/bulk-import-file)
|
|
464
|
-
- [Query Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/query-services)
|
|
465
|
-
- [Apps Installer API](https://dev.wix.com/docs/api-reference/business-management/app-installation/install-app)
|
|
374
|
+
- Services: [Bulk Create Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services) · [Create Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/create-service) (field rules) · [Get Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/get-service) · [Query Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/query-services) · [Update Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service) · [Bulk Update Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services) · [Bulk Update Services By Filter](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-update-services-by-filter) · [Delete Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/delete-service)
|
|
375
|
+
- Concepts: [About Service Types](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-types) · [About Service Payments](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-payments) · [About Service Locations](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-locations)
|
|
376
|
+
- Categories: [Query Categories](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories) · [Create Category](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)
|
|
377
|
+
- Staff: [Query Staff Members](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members) · [Create Staff Member](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/create-staff-member) · [Assign Working Hours Schedule](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/assign-working-hours-schedule)
|
|
378
|
+
- Sessions: [Bulk Create Event](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event) · [Bulk Update Event](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-update-event) · [Query Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/query-events)
|
|
379
|
+
- Media: [Search Files](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/search-files) · [Bulk Import File](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/bulk-import-file)
|