@wix/agent-skills 1.31.0 → 1.31.2
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/STORES_VERSIONING.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 +31 -14
- package/skills/wix-headless-kit/guides/api-run.md +116 -31
- package/skills/wix-headless-kit/guides/existing-site.md +9 -2
- package/skills/wix-headless-kit/guides/reference-mode.md +9 -1
- package/skills/wix-headless-kit/install/AGENTS.md +10 -7
- package/skills/wix-headless-kit/install/attach.mjs +35 -30
- package/skills/wix-headless-kit/install/background.mjs +32 -0
- package/skills/wix-headless-kit/install/bootstrap.mjs +28 -11
- package/skills/wix-headless-kit/install/check.mjs +2 -2
- package/skills/wix-headless-kit/install/context.mjs +62 -8
- package/skills/wix-headless-kit/install/deploy.mjs +36 -11
- package/skills/wix-headless-kit/install/env-ignore.mjs +16 -0
- package/skills/wix-headless-kit/install/install.mjs +95 -0
- package/skills/wix-headless-kit/install/pins.json +1 -1
- package/skills/wix-headless-kit/install/proc.mjs +46 -0
- package/skills/wix-headless-kit/install/setup.mjs +18 -27
- package/skills/wix-headless-kit/install/templates.mjs +4 -3
- package/skills/wix-headless-templates/blog/app/components/blog/RichContent.tsx +3 -2
- package/skills/wix-headless-templates/blog/project/package-lock.json +1287 -1299
- package/skills/wix-headless-templates/blog/project/package.json +1 -1
- package/skills/wix-headless-templates/blog/project/src/components/blog/RichContent.tsx +3 -2
- package/skills/wix-headless-templates/blog/rest/authors.ts +5 -5
- package/skills/wix-headless-templates/blog/rest/comments.ts +4 -4
- package/skills/wix-headless-templates/blog/rest/post-likes.ts +3 -3
- package/skills/wix-headless-templates/blog/rest/posts.ts +4 -4
- package/skills/wix-headless-templates/blog/rest/taxonomy.ts +5 -5
- package/skills/wix-headless-templates/blog/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/blog/seed/seed-blog.mjs +4 -3
- package/skills/wix-headless-templates/bookings/rest/booking.ts +4 -4
- package/skills/wix-headless-templates/bookings/rest/services.ts +4 -4
- package/skills/wix-headless-templates/bookings/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/bookings/seed/seed-bookings.mjs +4 -2
- package/skills/wix-headless-templates/cms/rest/collections.ts +3 -3
- package/skills/wix-headless-templates/cms/rest/items.ts +4 -4
- package/skills/wix-headless-templates/cms/seed/seed-cms.mjs +2 -1
- package/skills/wix-headless-templates/donations/rest/campaigns.ts +4 -4
- package/skills/wix-headless-templates/donations/rest/donate.ts +3 -3
- package/skills/wix-headless-templates/donations/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/donations/seed/seed-donations.mjs +5 -3
- package/skills/wix-headless-templates/events/rest/events.ts +4 -4
- package/skills/wix-headless-templates/events/rest/orders.ts +4 -4
- package/skills/wix-headless-templates/events/rest/registration.ts +4 -4
- package/skills/wix-headless-templates/events/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/events/seed/seed-events.mjs +5 -3
- package/skills/wix-headless-templates/faq/rest/faq.ts +4 -4
- package/skills/wix-headless-templates/faq/seed/seed-faq.mjs +2 -1
- package/skills/wix-headless-templates/forms/rest/forms.ts +4 -4
- package/skills/wix-headless-templates/forms/rest/submissions.ts +4 -4
- package/skills/wix-headless-templates/forms/seed/seed-forms.mjs +2 -1
- package/skills/wix-headless-templates/members/rest/auth.ts +3 -3
- package/skills/wix-headless-templates/members/rest/members.ts +4 -4
- package/skills/wix-headless-templates/members/seed/seed-members.mjs +2 -1
- package/skills/wix-headless-templates/portfolio/rest/portfolio.ts +4 -4
- package/skills/wix-headless-templates/portfolio/seed/SEED.md +4 -2
- package/skills/wix-headless-templates/portfolio/seed/seed-portfolio.mjs +8 -7
- package/skills/wix-headless-templates/pricing-plans/rest/plan-access.ts +3 -3
- package/skills/wix-headless-templates/pricing-plans/rest/plans.ts +4 -4
- package/skills/wix-headless-templates/pricing-plans/rest/purchase.ts +3 -3
- package/skills/wix-headless-templates/pricing-plans/seed/seed-pricing-plans.mjs +2 -1
- package/skills/wix-headless-templates/rentals/rest/rentals.ts +4 -4
- package/skills/wix-headless-templates/rentals/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/rentals/seed/seed-rentals.mjs +4 -2
- package/skills/wix-headless-templates/restaurants/rest/menu.ts +4 -4
- package/skills/wix-headless-templates/restaurants/rest/ordering.ts +5 -5
- package/skills/wix-headless-templates/restaurants/rest/reservations.ts +4 -4
- package/skills/wix-headless-templates/restaurants/seed/SEED.md +1 -1
- package/skills/wix-headless-templates/restaurants/seed/seed-restaurants.mjs +6 -4
- package/skills/wix-headless-templates/shared/capabilities/site-search/rest/search.ts +4 -4
- package/skills/wix-headless-templates/shared/capabilities/site-search/seed/install.mjs +6 -4
- package/skills/wix-headless-templates/shared/seed/images.mjs +41 -5
- package/skills/wix-headless-templates/shared/seed/main.mjs +15 -0
- package/skills/wix-headless-templates/shared/seed/wix-cli.mjs +43 -11
- package/skills/wix-headless-templates/storefront/INSTRUCTIONS.md +1 -1
- package/skills/wix-headless-templates/storefront/rest/cart.ts +5 -5
- package/skills/wix-headless-templates/storefront/rest/catalog.ts +5 -5
- package/skills/wix-headless-templates/storefront/seed/SEED.md +44 -14
- package/skills/wix-headless-templates/storefront/seed/seed-store.mjs +23 -15
- package/skills/wix-manage/SKILL.md +28 -18
- package/skills/wix-manage/references/app-installation/install-wix-apps.md +5 -1
- package/skills/wix-manage/references/app-installation/list-installed-apps.md +19 -9
- 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/booking-service-policy-setup.md +3 -0
- package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +277 -363
- package/skills/wix-manage/references/bookings/external-calendar-integration.md +3 -0
- package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +3 -0
- package/skills/wix-manage/references/cms/cms-data-items-crud.md +11 -2
- package/skills/wix-manage/references/cms/cms-publishing-flow.md +63 -16
- package/skills/wix-manage/references/custom-apps/use-app-skills-and-app-tools.md +3 -1
- package/skills/wix-manage/references/forms/update-form.md +3 -0
- package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +3 -0
- package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +3 -0
- package/skills/wix-manage/references/sites/create-headless-site.md +7 -50
- package/skills/wix-manage/references/sites/manage-oauth-apps.md +4 -4
- package/skills/wix-manage/references/sites/read-site-context.md +4 -0
- package/skills/wix-manage/references/sites/send-feedback-to-wix.md +92 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +298 -283
- package/skills/wix-manage/references/stores/add-store-pages-to-site.md +3 -0
- package/skills/wix-manage/references/stores/change-store-currency.md +3 -0
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +3 -0
- package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +3 -0
- package/skills/wix-manage/references/stores/update-product-with-options.md +192 -22
- 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
|
@@ -4,6 +4,9 @@ description: Adds missing checkout and cart pages to a site when Stores app is i
|
|
|
4
4
|
---
|
|
5
5
|
# Add Store Pages to Site
|
|
6
6
|
|
|
7
|
+
> These calls need the Wix Stores app on the site (`appDefId` `215238eb-22a5-4c36-9e7b-e7c08025e04e`); a `428`, a `400` naming the app, or an empty result on a site that should have content means it is not there. [List Installed Apps](../app-installation/list-installed-apps.md) shows what the site has; [Install Wix Apps](../app-installation/install-wix-apps.md) adds it by that id.
|
|
8
|
+
|
|
9
|
+
|
|
7
10
|
This recipe demonstrates how to add checkout and cart pages to a Wix site when the Stores app is installed but pages are missing.
|
|
8
11
|
|
|
9
12
|
## Overview
|
|
@@ -5,6 +5,9 @@ description: "Changes the store's payment currency through Site Properties and e
|
|
|
5
5
|
|
|
6
6
|
# Change Store Currency
|
|
7
7
|
|
|
8
|
+
> These calls need the Wix Stores app on the site (`appDefId` `215238eb-22a5-4c36-9e7b-e7c08025e04e`); a `428`, a `400` naming the app, or an empty result on a site that should have content means it is not there. [List Installed Apps](../app-installation/list-installed-apps.md) shows what the site has; [Install Wix Apps](../app-installation/install-wix-apps.md) adds it by that id.
|
|
9
|
+
|
|
10
|
+
|
|
8
11
|
Use the [Change a Site's Regional Properties (Currency, Time Zone, Language) via Site Properties API](../site-properties/change-payment-currency-site-properties.md) recipe to set the requested payment currency and read it back. Confirm the change with the user before updating it.
|
|
9
12
|
|
|
10
13
|
Catalog product responses may temporarily show the previous currency after carts and checkout use the new one. Allow time for propagation, then recheck.
|
|
@@ -5,6 +5,9 @@ description: Mandatory first recipe for every Wix Stores Catalog V3 create-produ
|
|
|
5
5
|
|
|
6
6
|
# Create Product (Catalog V3)
|
|
7
7
|
|
|
8
|
+
> These calls need the Wix Stores app on the site (`appDefId` `215238eb-22a5-4c36-9e7b-e7c08025e04e`); a `428`, a `400` naming the app, or an empty result on a site that should have content means it is not there. [List Installed Apps](../app-installation/list-installed-apps.md) shows what the site has; [Install Wix Apps](../app-installation/install-wix-apps.md) adds it by that id.
|
|
9
|
+
|
|
10
|
+
|
|
8
11
|
Use this recipe for one or multiple Catalog V3 products. Catalog V1 remains supported through [Create Product (Catalog V1)](create-product-catalog-v1.md).
|
|
9
12
|
|
|
10
13
|
> [!IMPORTANT]
|
|
@@ -5,6 +5,9 @@ description: Find, search, query, and list products from a Wix Store using Catal
|
|
|
5
5
|
|
|
6
6
|
# RECIPE: Business Recipe – Find Products in a Wix Store (Query and Search, Catalog V3)
|
|
7
7
|
|
|
8
|
+
> These calls need the Wix Stores app on the site (`appDefId` `215238eb-22a5-4c36-9e7b-e7c08025e04e`); a `428`, a `400` naming the app, or an empty result on a site that should have content means it is not there. [List Installed Apps](../app-installation/list-installed-apps.md) shows what the site has; [Install Wix Apps](../app-installation/install-wix-apps.md) adds it by that id.
|
|
9
|
+
|
|
10
|
+
|
|
8
11
|
Find products in a Wix store using the Catalog V3 Search Products and Query Products APIs.
|
|
9
12
|
|
|
10
13
|
## Article: How to Find Products
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Update Product with Options (Catalog V3)"
|
|
3
|
-
description:
|
|
3
|
+
description: "Start here for existing Catalog V3 product updates, including digital products that fail at add-to-cart with ITEM_NOT_FOUND_IN_CATALOG. Includes name lookup, Get Product, and PATCH in one flow, plus importing a supplied PDF and attaching it to the existing variant. Covers options, variant prices and SKUs, product visibility (hide/unhide through `visible`, never delete), description edits that preserve Rich Content, and revision-based updates. Read another recipe only for a field or operation this flow does not cover."
|
|
4
4
|
---
|
|
5
5
|
**RECIPE**: Business Recipe - Updating a Wix Store Product (Catalog V3)
|
|
6
6
|
|
|
@@ -14,7 +14,8 @@ Every Catalog V3 product update is revision-based:
|
|
|
14
14
|
- Use [Get Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/get-product) to retrieve the current product, its `product.revision`, and its existing variants. Search Products and Query Products responses do not include `variantsInfo.variants`, so a variant or price update assembled from a search result sends an empty variants array and is rejected. Re-read the product before every variant-level update.
|
|
15
15
|
- Include `product.id` and the current `product.revision` in every [Update Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/update-product) PATCH body.
|
|
16
16
|
- Update Product is a partial update: only `product`, `product.id`, and `product.revision` are required, and top-level fields you omit (for example `name`, `ribbon`, `brand`) are left unchanged. The full-array overwrite rule applies only to the repeated fields `options`, `modifiers`, and `variantsInfo.variants`.
|
|
17
|
-
-
|
|
17
|
+
- Get Product returns a default set of fields. When an update keeps or carries over existing projected data, request that data in `fields` before building the PATCH. For any edit that keeps part of the existing product description, request `DESCRIPTION`; a read without it has no Rich Content document to preserve.
|
|
18
|
+
- For description changes, see [Update Description](#update-description): replacing the whole description uses `plainDescription`; editing any existing content uses the Rich Content `description` field.
|
|
18
19
|
|
|
19
20
|
### Find the product by name
|
|
20
21
|
|
|
@@ -24,12 +25,16 @@ curl -X POST "https://www.wixapis.com/stores/v3/products/search" \
|
|
|
24
25
|
-H "Authorization: <AUTH>" \
|
|
25
26
|
-d '{
|
|
26
27
|
"search": {
|
|
27
|
-
"
|
|
28
|
+
"search": {
|
|
29
|
+
"expression": "Product name",
|
|
30
|
+
"fields": ["name"],
|
|
31
|
+
"fuzzy": false
|
|
32
|
+
}
|
|
28
33
|
}
|
|
29
34
|
}'
|
|
30
35
|
```
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
Read `products` from the search response. Prefer an exact name match; otherwise select a clear, unambiguous match, such as a name differing only in capitalization. If no result clearly identifies the requested product, or multiple products could match, ask the user which product they mean. Use the selected `products[].id` in Get Product; search only resolves the ID.
|
|
33
38
|
|
|
34
39
|
### Get the current revision
|
|
35
40
|
|
|
@@ -38,6 +43,15 @@ curl -X GET "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
38
43
|
-H "Authorization: <AUTH>"
|
|
39
44
|
```
|
|
40
45
|
|
|
46
|
+
To edit an existing description, request its Rich Content document in the same read:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
curl -X GET "https://www.wixapis.com/stores/v3/products/{productId}?fields=DESCRIPTION" \
|
|
50
|
+
-H "Authorization: <AUTH>"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`product.description` is returned only when `DESCRIPTION` is requested. Request every other projected field that you need to carry over with its documented `fields` value as well.
|
|
54
|
+
|
|
41
55
|
## Common Update Patterns
|
|
42
56
|
|
|
43
57
|
### Hide or Show a Product
|
|
@@ -66,9 +80,16 @@ Visibility behaviour to report back accurately:
|
|
|
66
80
|
- For a product **with** options, product and variant visibility are independent: setting `product.visible` to `false` leaves each `variantsInfo.variants[].visible` as it was.
|
|
67
81
|
- Point-of-sale visibility is a separate field, `visibleInPos`. Only change it when the user asks about POS. It is always `false` for `productType: DIGITAL`.
|
|
68
82
|
|
|
69
|
-
### Update Description
|
|
83
|
+
### Update Description
|
|
84
|
+
|
|
85
|
+
Choose the flow from the user's request:
|
|
86
|
+
|
|
87
|
+
- "Set the description to X", "replace the description", or "write a new description": **Replace the Description**.
|
|
88
|
+
- "Add", "append", "prepend", "insert", "fix a typo", or "remove" existing text: **Edit the Existing Description**. Any request that keeps part of the current description is an edit.
|
|
89
|
+
|
|
90
|
+
#### Replace the Description
|
|
70
91
|
|
|
71
|
-
For a
|
|
92
|
+
For a request like "set the product description to X", use `plainDescription` with valid HTML. The API converts it to rich content.
|
|
72
93
|
|
|
73
94
|
Do not send a plain string in `description`. `description` is a Rich Content object.
|
|
74
95
|
|
|
@@ -85,7 +106,7 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
85
106
|
}'
|
|
86
107
|
```
|
|
87
108
|
|
|
88
|
-
|
|
109
|
+
For a full replacement with node types beyond the paragraph below, read [Author Ricos Rich Content](../rich-content/author-ricos-rich-content.md). Existing-document edits use the read-modify-write flow below:
|
|
89
110
|
|
|
90
111
|
```bash
|
|
91
112
|
curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
@@ -123,6 +144,77 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
123
144
|
}'
|
|
124
145
|
```
|
|
125
146
|
|
|
147
|
+
Both fields replace the whole description. To keep any existing content, use **Edit the Existing Description**.
|
|
148
|
+
|
|
149
|
+
#### Edit the Existing Description
|
|
150
|
+
|
|
151
|
+
For prepend, append, and text removal, execute the documented calls directly: the examples in this recipe and the request/response contract below provide the fields this flow needs. Reuse this contract rather than rediscovering the Search, Get, and Update schemas. Consult further API documentation when the request requires a field or node type not covered here, or when a documented call fails. Read [Author Ricos Rich Content](../rich-content/author-ricos-rich-content.md) when creating other node types.
|
|
152
|
+
|
|
153
|
+
| Call | Request | Response fields used next |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| Search Products, when given a name | Use [Find the product by name](#find-the-product-by-name); `search.search` contains `expression`, `fields: ["name"]`, and `fuzzy: false`. | `products[]` contains `id` and `name`; select the product using the name-matching guidance above. |
|
|
156
|
+
| Get Product | `GET https://www.wixapis.com/stores/v3/products/{productId}?fields=DESCRIPTION` | `product.id`, `product.revision`, and the full `product.description`. |
|
|
157
|
+
| Update Product | `PATCH https://www.wixapis.com/stores/v3/products/{productId}` with `{ product: { id, revision, description }, fields: ["DESCRIPTION"] }`, using the read ID/revision and complete edited document. | `product.description` verifies the edit; `product.revision` is the new revision. |
|
|
158
|
+
|
|
159
|
+
The request-level `fields` array projects response data; it is separate from `search.search.fields`, which selects the fields searched. A description-only PATCH needs only the three product fields shown above; variant, option, price, and physical-property fields belong to other update flows.
|
|
160
|
+
|
|
161
|
+
Use a single read-modify-write operation: locate the product, read its description and revision, make the requested change in memory, then PATCH once and verify the response.
|
|
162
|
+
|
|
163
|
+
1. Read [Get Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/get-product) with `?fields=DESCRIPTION`. Its response wraps the document as `product.description` and the current revision as `product.revision`. If the description is missing or has no `nodes`, stop and ask before replacing it.
|
|
164
|
+
2. Copy the complete returned `product.description`, including node IDs, decorations, `metadata`, and `documentStyle`, **before locating any nodes to edit**. Traverse the copy and keep references to its nodes; edit that same copy and send it in the PATCH. For prepend/append, insert one new `PARAGRAPH` at the beginning/end of its `nodes`. For a wording change, modify only the matching `TEXT` node's `textData.text`.
|
|
165
|
+
3. For removal, trim only the requested substring from the matching TEXT run and keep its decorations. When the whole run or node is targeted, remove that entry from its parent `nodes` array. If text spans runs, trim the matching portion of each run. Preserve all other nodes, spacer paragraphs, and document properties. If the requested change is already present, report that state and finish without a write.
|
|
166
|
+
4. Check the in-memory PATCH document before sending: the targeted text has the requested value and untouched content matches the read document. Then send [Update Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/update-product) to `PATCH https://www.wixapis.com/stores/v3/products/{productId}` with `product.id`, the read revision, the full edited `product.description`, and top-level `fields: ["DESCRIPTION"]`. Leave other product fields out of this description-only update; `plainDescription` is for whole-description replacements.
|
|
167
|
+
5. Verify `product.description` in the PATCH response: the requested change is present and untouched nodes, decorations, and document properties remain. Confirm completion from that response and finish. A successful PATCH has already performed the edit; verification does not require another PATCH. If the response is incomplete, read once with `?fields=DESCRIPTION` to verify. If a revision conflict rejects the write, read the latest document and reapply the requested change only if it is still needed.
|
|
168
|
+
|
|
169
|
+
For a prepend, build the complete PATCH body from the Get Product response (`getResponse` below). For an append, use `push` instead of `unshift`:
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
const product = getResponse.product;
|
|
173
|
+
const description = structuredClone(product.description);
|
|
174
|
+
description.nodes.unshift({
|
|
175
|
+
type: "PARAGRAPH",
|
|
176
|
+
nodes: [{
|
|
177
|
+
type: "TEXT",
|
|
178
|
+
textData: { text: "New text.", decorations: [] }
|
|
179
|
+
}],
|
|
180
|
+
paragraphData: { textStyle: { textAlignment: "AUTO" } }
|
|
181
|
+
});
|
|
182
|
+
const patchBody = {
|
|
183
|
+
product: { id: product.id, revision: product.revision, description },
|
|
184
|
+
fields: ["DESCRIPTION"]
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Send `patchBody` as the JSON body of the PATCH above. The copy retains the returned document's other properties and existing nodes, including links and buttons; the response's `product.description` includes the edited document because the request projects `DESCRIPTION`.
|
|
189
|
+
|
|
190
|
+
For example, remove only `read ` from a TEXT run containing `read the guide`, retaining its BOLD and LINK decorations and siblings. Locate the run in the cloned document, including nested nodes, rather than assuming a paragraph/run index. This example handles a phrase within one TEXT run; a phrase spanning runs uses the per-run trimming in step 3, with all run references taken from the copy.
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const product = getResponse.product;
|
|
194
|
+
const description = structuredClone(product.description);
|
|
195
|
+
const target = "read the guide";
|
|
196
|
+
const replacement = "the guide";
|
|
197
|
+
const matches = [];
|
|
198
|
+
function locate(node) {
|
|
199
|
+
if (node.type === "TEXT" && node.textData.text.includes(target)) matches.push(node.textData);
|
|
200
|
+
for (const child of node.nodes ?? []) locate(child);
|
|
201
|
+
}
|
|
202
|
+
locate(description);
|
|
203
|
+
if (matches.length !== 1) throw new Error("Clarify which text occurrence to edit");
|
|
204
|
+
const textData = matches[0];
|
|
205
|
+
const originalText = textData.text;
|
|
206
|
+
const start = originalText.indexOf(target);
|
|
207
|
+
if (start !== originalText.lastIndexOf(target)) throw new Error("Clarify which text occurrence to edit");
|
|
208
|
+
textData.text = originalText.slice(0, start) + replacement + originalText.slice(start + target.length);
|
|
209
|
+
if (textData.text === originalText || textData.text.includes(target)) {
|
|
210
|
+
throw new Error("The PATCH document must contain the requested edit before writing");
|
|
211
|
+
}
|
|
212
|
+
const patchBody = {
|
|
213
|
+
product: { id: product.id, revision: product.revision, description },
|
|
214
|
+
fields: ["DESCRIPTION"]
|
|
215
|
+
};
|
|
216
|
+
```
|
|
217
|
+
|
|
126
218
|
### Update Options and Variants
|
|
127
219
|
|
|
128
220
|
When adding or changing options and variants, send the full option definitions and one variant for each option-choice combination. Use `optionChoiceNames` to reference choices.
|
|
@@ -339,8 +431,11 @@ its `id`, its `choices` (by `optionChoiceIds` — or `optionChoiceNames`, see *G
|
|
|
339
431
|
|
|
340
432
|
```bash
|
|
341
433
|
# A choice image + a variant's sale price, one PATCH. Both arrays are complete and keep their ids —
|
|
342
|
-
|
|
343
|
-
|
|
434
|
+
|
|
435
|
+
> These calls need the Wix Stores app on the site (`appDefId` `215238eb-22a5-4c36-9e7b-e7c08025e04e`); a `428`, a `400` naming the app, or an empty result on a site that should have content means it is not there. [List Installed Apps](../app-installation/list-installed-apps.md) shows what the site has; [Install Wix Apps](../app-installation/install-wix-apps.md) adds it by that id.
|
|
436
|
+
|
|
437
|
+
# keep the option and choice IDs when rebuilding the options array, and each variant
|
|
438
|
+
# with its choices and price. Omitting those identities or required variant fields can reject the update.
|
|
344
439
|
curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
345
440
|
-H "Content-Type: application/json" -H "Authorization: <AUTH>" \
|
|
346
441
|
-d '{ "product": { "id": "{productId}", "revision": "{currentRevision}",
|
|
@@ -357,9 +452,67 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
357
452
|
"choices": [ { "optionChoiceIds": { "optionId": "{optionId}", "choiceId": "{choiceId2}" } } ] } ] } } }'
|
|
358
453
|
```
|
|
359
454
|
|
|
455
|
+
### Prepare a Price or SKU Update
|
|
456
|
+
|
|
457
|
+
For an existing product's price or SKU, use the name lookup above, then Get Product. Request `?fields=VARIANT_OPTION_CHOICE_NAMES&fields=MERCHANT_DATA&fields=PRODUCT_CHOICES_MEDIA_REFERENCES&fields=PRODUCT_CHOICES_DISPLAY_IMAGE` so the same read supplies variant choice names, permitted cost data, and choice media to preserve. The response is `{ product: { id, revision, options, variantsInfo: { variants } } }`; search results cannot supply the variants.
|
|
458
|
+
|
|
459
|
+
Build the complete writable options and variants from that response, then change only the requested field. **Every variants PATCH also includes the complete `options` array**, even for an SKU-only change; for a product without options, send `options: []`. Omitting options caused `428 MISSING_OPTIONS_ON_UPDATE_VARIANTS`. A variant retains its `id`, `choices`, price, and other writable fields. The example below copies the writable fields used by these flows and strips calculated monetary values; inventory status and variant media are read-only and are not part of this update.
|
|
460
|
+
|
|
461
|
+
```javascript
|
|
462
|
+
const product = getResponse.product;
|
|
463
|
+
const pick = (source, keys) => Object.fromEntries(keys
|
|
464
|
+
.filter(key => source[key] !== undefined)
|
|
465
|
+
.map(key => [key, structuredClone(source[key])]));
|
|
466
|
+
const amountOnly = value => ({ amount: value.amount });
|
|
467
|
+
const options = (product.options ?? []).map(option => ({
|
|
468
|
+
...pick(option, ["id", "name", "optionRenderType"]),
|
|
469
|
+
choicesSettings: { choices: option.choicesSettings.choices.map(choice =>
|
|
470
|
+
pick(choice, ["choiceId", "name", "choiceType", "colorCode", "media", "displayImage"])) }
|
|
471
|
+
}));
|
|
472
|
+
const variants = product.variantsInfo.variants.map(variant => {
|
|
473
|
+
const copy = pick(variant, ["id", "visible", "sku", "barcode", "physicalProperties"]);
|
|
474
|
+
copy.choices = (variant.choices ?? []).map(choice => ({
|
|
475
|
+
optionChoiceNames: pick(choice.optionChoiceNames, ["optionName", "choiceName", "renderType"])
|
|
476
|
+
}));
|
|
477
|
+
copy.price = { actualPrice: amountOnly(variant.price.actualPrice) };
|
|
478
|
+
if (variant.price.compareAtPrice) copy.price.compareAtPrice = amountOnly(variant.price.compareAtPrice);
|
|
479
|
+
if (variant.revenueDetails?.cost) copy.revenueDetails = { cost: amountOnly(variant.revenueDetails.cost) };
|
|
480
|
+
if (variant.digitalProperties) {
|
|
481
|
+
copy.digitalProperties = variant.digitalProperties.digitalFile
|
|
482
|
+
? { digitalFile: { id: variant.digitalProperties.digitalFile.id } } : {};
|
|
483
|
+
}
|
|
484
|
+
if (copy.physicalProperties?.pricePerUnit) delete copy.physicalProperties.pricePerUnit.value;
|
|
485
|
+
return copy;
|
|
486
|
+
});
|
|
487
|
+
const variantPatchProduct = {
|
|
488
|
+
id: product.id, revision: product.revision, options,
|
|
489
|
+
variantsInfo: { variants }
|
|
490
|
+
};
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
For the single-variant product case (a user asking to change a simple product's price), use the prepared body above:
|
|
494
|
+
|
|
495
|
+
```javascript
|
|
496
|
+
if (variants.length !== 1) throw new Error("Clarify which variants should receive the price change");
|
|
497
|
+
variants[0].price.actualPrice.amount = "25"; // requested price
|
|
498
|
+
const pricePatchBody = { product: variantPatchProduct };
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
For a named option choice such as `Size = Large`, use its returned choice names to select one variant, then change its SKU:
|
|
502
|
+
|
|
503
|
+
```javascript
|
|
504
|
+
const matches = variants.filter(variant => variant.choices.some(choice =>
|
|
505
|
+
choice.optionChoiceNames.optionName === "Size" && choice.optionChoiceNames.choiceName === "Large"));
|
|
506
|
+
if (matches.length !== 1) throw new Error("Clarify which variant should receive the SKU change");
|
|
507
|
+
matches[0].sku = "MUG-L-001"; // requested SKU
|
|
508
|
+
const skuPatchBody = { product: variantPatchProduct };
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Send the selected body to `PATCH https://www.wixapis.com/stores/v3/products/{productId}` in the same ExecuteWixAPI invocation as the name lookup and Get Product. Its response is `{ product: { id, revision, variantsInfo: { variants } } }`; verify the changed variant by its retained ID and confirm from that response. These examples provide the request fields and response paths for price and SKU changes; proceed directly after reading this recipe. Discover further schemas only for fields not covered here or a documented call that fails.
|
|
512
|
+
|
|
360
513
|
### Update Variant Price Only
|
|
361
514
|
|
|
362
|
-
Read `{existingVariantId}` off the Get Product response; a Search or Query Products result does not carry it.
|
|
515
|
+
Read `{existingVariantId}` off the Get Product response; a Search or Query Products result does not carry it. The curl below is for a single-variant product without options. For an optioned product, use the complete options/variants body in **Prepare a Price or SKU Update**.
|
|
363
516
|
|
|
364
517
|
```bash
|
|
365
518
|
curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
@@ -369,10 +522,12 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
369
522
|
"product": {
|
|
370
523
|
"id": "{productId}",
|
|
371
524
|
"revision": "{currentRevision}",
|
|
525
|
+
"options": [],
|
|
372
526
|
"variantsInfo": {
|
|
373
527
|
"variants": [
|
|
374
528
|
{
|
|
375
529
|
"id": "{existingVariantId}",
|
|
530
|
+
"choices": [],
|
|
376
531
|
"price": {
|
|
377
532
|
"actualPrice": {
|
|
378
533
|
"amount": "29.99"
|
|
@@ -387,7 +542,23 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
387
542
|
|
|
388
543
|
### Attach a Digital File
|
|
389
544
|
|
|
390
|
-
|
|
545
|
+
For an existing digital product rejected at add-to-cart with `ITEM_NOT_FOUND_IN_CATALOG`, use this repair flow. For a supplied external PDF URL, the table below is the complete request/response contract; execute it directly after reading this recipe. Use its linked method URLs as source citations. Further schema discovery is needed only for a field not covered here or a documented call that fails.
|
|
546
|
+
|
|
547
|
+
First locate the existing product with the name lookup above, then Get Product for its revision and variants. If the requested product is absent or ambiguous, ask for the correct product or site and stop before uploading media. Repairing an existing product does not authorize creating a replacement.
|
|
548
|
+
|
|
549
|
+
A `DIGITAL` product is sellable only when its variant has both a digital file and stock. For a product already in stock, keep that stock unchanged and attach only the missing file. `digitalProperties` belongs to the variant.
|
|
550
|
+
|
|
551
|
+
| Call | Request | Response fields used next |
|
|
552
|
+
|---|---|---|
|
|
553
|
+
| [Search Products](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/search-products) | Use the `search.search` name lookup above. | `products[].id` and `name` select the existing product. |
|
|
554
|
+
| [Get Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/get-product) | `GET https://www.wixapis.com/stores/v3/products/{productId}?fields=VARIANT_OPTION_CHOICE_NAMES&fields=MERCHANT_DATA&fields=PRODUCT_CHOICES_MEDIA_REFERENCES&fields=PRODUCT_CHOICES_DISPLAY_IMAGE` | `product.id`, `revision`, `productType`, `options`, and `variantsInfo.variants` supply the complete writable state. |
|
|
555
|
+
| [Import File](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/import-file) | `POST https://www.wixapis.com/site-media/v1/files/import` with `{ "url": "{suppliedPdfUrl}", "mimeType": "application/pdf", "displayName": "download.pdf", "private": true }` | `file.id` and `file.operationStatus`. Import the exact supplied URL once; retain this ID. |
|
|
556
|
+
| [Get File Descriptor](https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/get-file-descriptor), only while PENDING | `GET https://www.wixapis.com/site-media/v1/files/get-file-by-id?fileId={fileId}` | `file.operationStatus`: wait for `READY`, stop on `FAILED`. The response is wrapped in `file`. |
|
|
557
|
+
| [Update Product](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/update-product) | `PATCH https://www.wixapis.com/stores/v3/products/{productId}` with `{ product: { id, revision, options, variantsInfo: { variants } } }` | `product.variantsInfo.variants[].digitalProperties.digitalFile.id` confirms the attachment on the retained variant ID. |
|
|
558
|
+
|
|
559
|
+
Chain these requests in one ExecuteWixAPI invocation; with `wix.request`, the REST response body is in `response.data`. Private import keeps the stored download private. For a local file rather than a supplied URL, read [Upload Media to Wix](../media/upload-media-to-wix.md) and use its Generate Upload URL flow instead.
|
|
560
|
+
|
|
561
|
+
Prepare the complete options/variants body as in **Prepare a Price or SKU Update**, retain every variant ID, choice and price, and set the requested variant's `digitalProperties.digitalFile.id` to the imported file ID. For one existing variant with no options:
|
|
391
562
|
|
|
392
563
|
```bash
|
|
393
564
|
curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
@@ -397,22 +568,21 @@ curl -X PATCH "https://www.wixapis.com/stores/v3/products/{productId}" \
|
|
|
397
568
|
"product": {
|
|
398
569
|
"id": "{productId}",
|
|
399
570
|
"revision": "{currentRevision}",
|
|
571
|
+
"options": [],
|
|
400
572
|
"variantsInfo": {
|
|
401
|
-
"variants": [
|
|
402
|
-
{
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
]
|
|
573
|
+
"variants": [{
|
|
574
|
+
"id": "{existingVariantId}",
|
|
575
|
+
"choices": [],
|
|
576
|
+
"price": { "actualPrice": { "amount": "{existingPrice}" } },
|
|
577
|
+
"visible": true,
|
|
578
|
+
"digitalProperties": { "digitalFile": { "id": "{fileId}" } }
|
|
579
|
+
}]
|
|
410
580
|
}
|
|
411
581
|
}
|
|
412
582
|
}'
|
|
413
583
|
```
|
|
414
584
|
|
|
415
|
-
Confirm from `product.variantsInfo.variants[].digitalProperties.digitalFile` in the response.
|
|
585
|
+
Copy any other writable variant fields from the read product using the preparation example. Chain the product lookup, read, selected upload path, and one PATCH in one ExecuteWixAPI invocation. Confirm from `product.variantsInfo.variants[].digitalProperties.digitalFile.id` in the PATCH response; no extra product read is needed when that response supplies it.
|
|
416
586
|
|
|
417
587
|
## Important Notes
|
|
418
588
|
|
|
@@ -439,4 +609,4 @@ Confirm from `product.variantsInfo.variants[].digitalProperties.digitalFile` in
|
|
|
439
609
|
| `Missing option choices` or `INVALID_DEFAULT_VARIANT` | Product has options but at least one variant has no matching choices | Rebuild `variantsInfo.variants` so every variant includes choices for all product options |
|
|
440
610
|
| `DIGITAL_PRODUCT_CANNOT_BE_VISIBLE_IN_POS` | Sent `visibleInPos: true` on a digital product | Digital products can't be visible in POS; leave `visibleInPos` out of the body |
|
|
441
611
|
| `ITEM_NOT_FOUND_IN_CATALOG` at add-to-cart, product exists | A `DIGITAL` variant has no `digitalProperties.digitalFile` | Attach a file — see [Attach a Digital File](#attach-a-digital-file) |
|
|
442
|
-
| `exceeds available inventory` at add-to-cart, product exists | The variant has no stock (`DIGITAL` products included) |
|
|
612
|
+
| `exceeds available inventory` at add-to-cart, product exists | The variant has no stock (`DIGITAL` products included) | Update its stock through the Inventory API; inventory is separate from an Update Product PATCH |
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "Create Appointment Service"
|
|
3
|
-
description: "Create an appointment booking service — e.g. 'set up consultations', 'create a 1-on-1 session', 'add a personal training appointment', 'create a meeting service for $25'. Handles staff assignment (required), session duration, pricing, and 1-on-1 capacity defaults via bulkCreateServices API."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Create Appointment Service from Prompt
|
|
7
|
-
|
|
8
|
-
## When to Use
|
|
9
|
-
|
|
10
|
-
- User wants to create an appointment-based service: "set up consultations", "create a 1-on-1 session", "add a personal training appointment", "create a meeting service"
|
|
11
|
-
- The service type is APPOINTMENT — customer picks an available time slot during staff working hours
|
|
12
|
-
- For general service creation where the type is ambiguous, see [Create Booking Service from Prompt](./create-booking-service-from-prompt.md)
|
|
13
|
-
|
|
14
|
-
## Prerequisites
|
|
15
|
-
|
|
16
|
-
- For full API field definitions, validation rules, and troubleshooting, see [Create and Update Booking Services](./create-and-update-booking-services.md)
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Step 1: Gather Business Context
|
|
21
|
-
|
|
22
|
-
Run these queries to collect site data for informed defaults.
|
|
23
|
-
|
|
24
|
-
### 1a. Query Staff Members (CRITICAL for Appointments)
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
curl -X POST 'https://www.wixapis.com/bookings/v1/staff-members/query' \
|
|
28
|
-
-H 'Authorization: <AUTH>' \
|
|
29
|
-
-H 'Content-Type: application/json' \
|
|
30
|
-
-d '{
|
|
31
|
-
"query": {},
|
|
32
|
-
"fields": ["RESOURCE_DETAILS"]
|
|
33
|
-
}'
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Save each staff member's `resourceId` (not `id`). Note which one has `default: true`.
|
|
37
|
-
|
|
38
|
-
**APPOINTMENT services REQUIRE at least one staff member.** If no staff members exist, create one first using [Bookings Staff Setup](./bookings-staff-setup.md).
|
|
39
|
-
|
|
40
|
-
### 1b. Query Service Categories
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/categories/query' \
|
|
44
|
-
-H 'Authorization: <AUTH>' \
|
|
45
|
-
-H 'Content-Type: application/json' \
|
|
46
|
-
-d '{ "query": {} }'
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 1c. Query Existing Services (Duplicate Check)
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/services/query' \
|
|
53
|
-
-H 'Authorization: <AUTH>' \
|
|
54
|
-
-H 'Content-Type: application/json' \
|
|
55
|
-
-d '{ "query": { "paging": { "limit": 100 } } }'
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Warn the user if a service with a similar name already exists.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Step 2: Apply Appointment Defaults
|
|
63
|
-
|
|
64
|
-
For any fields the user did not explicitly specify:
|
|
65
|
-
|
|
66
|
-
| Field | Default | Notes |
|
|
67
|
-
|---|---|---|
|
|
68
|
-
| Duration | 60 minutes | Set via `schedule.availabilityConstraints.sessionDurations` |
|
|
69
|
-
| Capacity | 1 | Appointments are typically 1-on-1 |
|
|
70
|
-
| Staff | Auto-assign | Use `default: true` staff, or first available |
|
|
71
|
-
| Online booking | Enabled | `onlineBooking.enabled: true` |
|
|
72
|
-
|
|
73
|
-
### Pricing (if not specified)
|
|
74
|
-
|
|
75
|
-
- If user specifies a price → `rateType: "FIXED"`
|
|
76
|
-
- If user says "free" → `rateType: "NO_FEE"`, `options.inPerson: true`, `options.online: false`
|
|
77
|
-
- If no price mentioned → infer from context (consultations ~$50-100, sessions ~$30-60) or default to free
|
|
78
|
-
|
|
79
|
-
### Staff Assignment
|
|
80
|
-
|
|
81
|
-
- **1 staff member** → auto-assign using their `resourceId`
|
|
82
|
-
- **Multiple staff members** → use the one with `default: true`, or the first one
|
|
83
|
-
- **No staff members** → create one first using [Bookings Staff Setup](./bookings-staff-setup.md), then proceed
|
|
84
|
-
|
|
85
|
-
### Category
|
|
86
|
-
|
|
87
|
-
- If categories exist → assign the most relevant one
|
|
88
|
-
- If no categories exist → create a "General" category:
|
|
89
|
-
```bash
|
|
90
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/categories' \
|
|
91
|
-
-H 'Authorization: <AUTH>' \
|
|
92
|
-
-H 'Content-Type: application/json' \
|
|
93
|
-
-d '{ "category": { "name": "General" } }'
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Service Name & Description
|
|
97
|
-
|
|
98
|
-
- Use the user's wording for the service name
|
|
99
|
-
- Generate a brief, professional description (1-2 sentences)
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## Step 3: Create the Appointment Service
|
|
104
|
-
|
|
105
|
-
**Paid appointment:**
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
|
|
109
|
-
-H 'Authorization: <AUTH>' \
|
|
110
|
-
-H 'Content-Type: application/json' \
|
|
111
|
-
-d '{
|
|
112
|
-
"returnEntity": true,
|
|
113
|
-
"services": [{
|
|
114
|
-
"name": "<SERVICE_NAME>",
|
|
115
|
-
"description": "<GENERATED_DESCRIPTION>",
|
|
116
|
-
"type": "APPOINTMENT",
|
|
117
|
-
|
|
118
|
-
"onlineBooking": { "enabled": true },
|
|
119
|
-
"staffMemberIds": ["<RESOURCE_ID>"],
|
|
120
|
-
"schedule": {
|
|
121
|
-
"availabilityConstraints": {
|
|
122
|
-
"sessionDurations": [<DURATION_MINUTES>]
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
"payment": {
|
|
126
|
-
"rateType": "FIXED",
|
|
127
|
-
"options": { "online": true, "inPerson": false },
|
|
128
|
-
"fixed": {
|
|
129
|
-
"price": { "value": "<PRICE>" }
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
"category": {
|
|
133
|
-
"id": "<CATEGORY_ID>"
|
|
134
|
-
}
|
|
135
|
-
}]
|
|
136
|
-
}'
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
**Free appointment:**
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
|
|
143
|
-
-H 'Authorization: <AUTH>' \
|
|
144
|
-
-H 'Content-Type: application/json' \
|
|
145
|
-
-d '{
|
|
146
|
-
"returnEntity": true,
|
|
147
|
-
"services": [{
|
|
148
|
-
"name": "<SERVICE_NAME>",
|
|
149
|
-
"description": "<GENERATED_DESCRIPTION>",
|
|
150
|
-
"type": "APPOINTMENT",
|
|
151
|
-
|
|
152
|
-
"onlineBooking": { "enabled": true },
|
|
153
|
-
"staffMemberIds": ["<RESOURCE_ID>"],
|
|
154
|
-
"schedule": {
|
|
155
|
-
"availabilityConstraints": {
|
|
156
|
-
"sessionDurations": [<DURATION_MINUTES>]
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
"payment": {
|
|
160
|
-
"rateType": "NO_FEE",
|
|
161
|
-
"options": { "online": false, "inPerson": true }
|
|
162
|
-
},
|
|
163
|
-
"category": {
|
|
164
|
-
"id": "<CATEGORY_ID>"
|
|
165
|
-
}
|
|
166
|
-
}]
|
|
167
|
-
}'
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### APPOINTMENT-Specific Reminders
|
|
171
|
-
|
|
172
|
-
- `staffMemberIds` is **required** — uses `resourceId` values, not staff member `id`
|
|
173
|
-
- `schedule.availabilityConstraints.sessionDurations` sets the appointment length
|
|
174
|
-
- Availability is based on the assigned staff member's working hours schedule
|
|
175
|
-
|
|
176
|
-
Save the `serviceId` from the response: `results[0].item.id` (the created service is directly under `item` — there is no `item.service`). This requires `returnEntity: true` on the request; without it the response carries only `results[0].itemMetadata.id`.
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
## Step 4: Summary Message
|
|
181
|
-
|
|
182
|
-
Provide a summary including:
|
|
183
|
-
|
|
184
|
-
1. **What was created** — service name, price, duration, assigned staff member
|
|
185
|
-
2. **Assumptions made** — list defaults used (e.g., "I set the duration to 60 minutes since you didn't specify")
|
|
186
|
-
3. **Next steps** — "Click Save to finalize, then set up your availability"
|
|
187
|
-
4. **Offer to adjust** — "Want me to change the price, duration, or staff assignment?"
|
|
188
|
-
|
|
189
|
-
**Example:**
|
|
190
|
-
|
|
191
|
-
> I created **"Strategy Consultation"**:
|
|
192
|
-
>
|
|
193
|
-
> - **Type**: Appointment (1-on-1)
|
|
194
|
-
> - **Price**: $75 per session
|
|
195
|
-
> - **Duration**: 60 minutes
|
|
196
|
-
> - **Staff**: Assigned to Sarah Johnson
|
|
197
|
-
> - **Category**: Consulting
|
|
198
|
-
>
|
|
199
|
-
> I assumed a 60-minute duration since you didn't specify. You can review and adjust the details in the service form.
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## Error Handling
|
|
204
|
-
|
|
205
|
-
| Error | Cause | Action |
|
|
206
|
-
|---|---|---|
|
|
207
|
-
| 400 "staffMemberIds required" | No staff assigned | Query staff; if none exist, create one via [Bookings Staff Setup](./bookings-staff-setup.md) |
|
|
208
|
-
| 400 "INVALID_PAYMENT_OPTIONS" | Payment misconfigured | Free: `inPerson: true`, `online: false`. Paid: price > 0 |
|
|
209
|
-
| 403 | Permission denied | Inform user they lack permission |
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Payment Validation Quick Reference
|
|
214
|
-
|
|
215
|
-
| rateType | `options.online` | `options.inPerson` | Valid? |
|
|
216
|
-
|----------|------------------|-------------------|--------|
|
|
217
|
-
| FIXED | true | false | ✓ |
|
|
218
|
-
| FIXED | false | true | ✓ |
|
|
219
|
-
| FIXED | true | true | ✓ |
|
|
220
|
-
| NO_FEE | false | true | ✓ |
|
|
221
|
-
| NO_FEE | true | false | ✗ |
|
|
222
|
-
| Any | false | false | ✗ |
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## What This Skill Does NOT Cover
|
|
227
|
-
|
|
228
|
-
- **Schedule/availability setup** — staff working hours need separate configuration. See [Bookings Staff Setup](./bookings-staff-setup.md)
|
|
229
|
-
- **Pricing plans** — memberships and session packs are separate. See [Create and Update Pricing Plans](../pricing-plans/create-and-update-pricing-plans.md)
|
|
230
|
-
- **Service images** — requires Media Manager API (see [create-and-update-booking-services.md](./create-and-update-booking-services.md))
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
## API Documentation Reference
|
|
235
|
-
|
|
236
|
-
- [Bulk Create Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services)
|
|
237
|
-
- [Query Services](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/query-services)
|
|
238
|
-
- [Query Categories](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories)
|
|
239
|
-
- [Create Category](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)
|
|
240
|
-
- [Query Staff Members](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members)
|
|
241
|
-
- [Create Staff Member](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/create-staff-member)
|
|
242
|
-
- [About Service Types](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-types)
|
|
243
|
-
- [About Service Payments](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-payments)
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "Create Booking Service from Prompt"
|
|
3
|
-
description: "Create a booking service from a user prompt — e.g. 'create a yoga class for $50', 'set up consultations for $75', 'add a personal training appointment', 'create a 6-week photography workshop', 'create a hidden free test course with 8 online sessions'. Determines the service type (APPOINTMENT, CLASS, or COURSE) and delegates to the type-specific recipe. For COURSE services with session dates/counts, follow the course recipe's separate Calendar bulkCreateEvents step; Services V2 alone does not create bookable course sessions."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Create Booking Service from Natural Language Prompt
|
|
7
|
-
|
|
8
|
-
## When to Use
|
|
9
|
-
|
|
10
|
-
- User describes a service they want to create using natural language (e.g., "create a yoga class for $50", "set up consultation sessions", "add a personal training appointment", "create a hidden free test course with 8 online sessions")
|
|
11
|
-
- The intent is autonomous creation — fill in reasonable defaults rather than asking the user for every field
|
|
12
|
-
|
|
13
|
-
## Step 1: Determine Service Type
|
|
14
|
-
|
|
15
|
-
| User mentions | Type | Recipe |
|
|
16
|
-
|---|---|---|
|
|
17
|
-
| consultation, appointment, meeting, 1-on-1, one-on-one, session | `APPOINTMENT` | [Create Appointment Service](./create-appointment-service.md) |
|
|
18
|
-
| class, yoga, pilates, group session, group workout, bootcamp class | `CLASS` | [Create Class Service](./create-class-service.md) |
|
|
19
|
-
| workshop, program, course, training program, multi-session, fixed series, 8 sessions | `COURSE` | [Create Course Service](./create-course-service.md) |
|
|
20
|
-
| (unclear or unspecified) | `APPOINTMENT` | [Create Appointment Service](./create-appointment-service.md) |
|
|
21
|
-
|
|
22
|
-
## Step 2: Follow the Type-Specific Recipe
|
|
23
|
-
|
|
24
|
-
Once the service type is determined, follow the corresponding recipe linked above. Each recipe covers:
|
|
25
|
-
|
|
26
|
-
1. Gathering business context (staff where required, categories, duplicate check)
|
|
27
|
-
2. Applying type-specific defaults (pricing, capacity, duration, staff assignment)
|
|
28
|
-
3. Creating the service via `bulkCreateServices`
|
|
29
|
-
4. For COURSE services with session dates/counts, creating separate Calendar events via `bulkCreateEvents` on the returned `service.schedule.id`
|
|
30
|
-
5. Navigating to the service form for user review
|
|
31
|
-
6. Providing a summary of what was created and assumptions made
|