@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.
Files changed (115) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +7 -8
  3. package/skills/wix-app/references/DASHBOARD_PAGE.md +1 -1
  4. package/skills/wix-app/references/STORES_VERSIONING.md +1 -1
  5. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +11 -50
  6. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +14 -10
  7. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +5 -8
  8. package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +5 -4
  9. package/skills/wix-headless-kit/SKILL.md +31 -14
  10. package/skills/wix-headless-kit/guides/api-run.md +116 -31
  11. package/skills/wix-headless-kit/guides/existing-site.md +9 -2
  12. package/skills/wix-headless-kit/guides/reference-mode.md +9 -1
  13. package/skills/wix-headless-kit/install/AGENTS.md +10 -7
  14. package/skills/wix-headless-kit/install/attach.mjs +35 -30
  15. package/skills/wix-headless-kit/install/background.mjs +32 -0
  16. package/skills/wix-headless-kit/install/bootstrap.mjs +28 -11
  17. package/skills/wix-headless-kit/install/check.mjs +2 -2
  18. package/skills/wix-headless-kit/install/context.mjs +62 -8
  19. package/skills/wix-headless-kit/install/deploy.mjs +36 -11
  20. package/skills/wix-headless-kit/install/env-ignore.mjs +16 -0
  21. package/skills/wix-headless-kit/install/install.mjs +95 -0
  22. package/skills/wix-headless-kit/install/pins.json +1 -1
  23. package/skills/wix-headless-kit/install/proc.mjs +46 -0
  24. package/skills/wix-headless-kit/install/setup.mjs +18 -27
  25. package/skills/wix-headless-kit/install/templates.mjs +4 -3
  26. package/skills/wix-headless-templates/blog/app/components/blog/RichContent.tsx +3 -2
  27. package/skills/wix-headless-templates/blog/project/package-lock.json +1287 -1299
  28. package/skills/wix-headless-templates/blog/project/package.json +1 -1
  29. package/skills/wix-headless-templates/blog/project/src/components/blog/RichContent.tsx +3 -2
  30. package/skills/wix-headless-templates/blog/rest/authors.ts +5 -5
  31. package/skills/wix-headless-templates/blog/rest/comments.ts +4 -4
  32. package/skills/wix-headless-templates/blog/rest/post-likes.ts +3 -3
  33. package/skills/wix-headless-templates/blog/rest/posts.ts +4 -4
  34. package/skills/wix-headless-templates/blog/rest/taxonomy.ts +5 -5
  35. package/skills/wix-headless-templates/blog/seed/SEED.md +1 -1
  36. package/skills/wix-headless-templates/blog/seed/seed-blog.mjs +4 -3
  37. package/skills/wix-headless-templates/bookings/rest/booking.ts +4 -4
  38. package/skills/wix-headless-templates/bookings/rest/services.ts +4 -4
  39. package/skills/wix-headless-templates/bookings/seed/SEED.md +1 -1
  40. package/skills/wix-headless-templates/bookings/seed/seed-bookings.mjs +4 -2
  41. package/skills/wix-headless-templates/cms/rest/collections.ts +3 -3
  42. package/skills/wix-headless-templates/cms/rest/items.ts +4 -4
  43. package/skills/wix-headless-templates/cms/seed/seed-cms.mjs +2 -1
  44. package/skills/wix-headless-templates/donations/rest/campaigns.ts +4 -4
  45. package/skills/wix-headless-templates/donations/rest/donate.ts +3 -3
  46. package/skills/wix-headless-templates/donations/seed/SEED.md +1 -1
  47. package/skills/wix-headless-templates/donations/seed/seed-donations.mjs +5 -3
  48. package/skills/wix-headless-templates/events/rest/events.ts +4 -4
  49. package/skills/wix-headless-templates/events/rest/orders.ts +4 -4
  50. package/skills/wix-headless-templates/events/rest/registration.ts +4 -4
  51. package/skills/wix-headless-templates/events/seed/SEED.md +1 -1
  52. package/skills/wix-headless-templates/events/seed/seed-events.mjs +5 -3
  53. package/skills/wix-headless-templates/faq/rest/faq.ts +4 -4
  54. package/skills/wix-headless-templates/faq/seed/seed-faq.mjs +2 -1
  55. package/skills/wix-headless-templates/forms/rest/forms.ts +4 -4
  56. package/skills/wix-headless-templates/forms/rest/submissions.ts +4 -4
  57. package/skills/wix-headless-templates/forms/seed/seed-forms.mjs +2 -1
  58. package/skills/wix-headless-templates/members/rest/auth.ts +3 -3
  59. package/skills/wix-headless-templates/members/rest/members.ts +4 -4
  60. package/skills/wix-headless-templates/members/seed/seed-members.mjs +2 -1
  61. package/skills/wix-headless-templates/portfolio/rest/portfolio.ts +4 -4
  62. package/skills/wix-headless-templates/portfolio/seed/SEED.md +4 -2
  63. package/skills/wix-headless-templates/portfolio/seed/seed-portfolio.mjs +8 -7
  64. package/skills/wix-headless-templates/pricing-plans/rest/plan-access.ts +3 -3
  65. package/skills/wix-headless-templates/pricing-plans/rest/plans.ts +4 -4
  66. package/skills/wix-headless-templates/pricing-plans/rest/purchase.ts +3 -3
  67. package/skills/wix-headless-templates/pricing-plans/seed/seed-pricing-plans.mjs +2 -1
  68. package/skills/wix-headless-templates/rentals/rest/rentals.ts +4 -4
  69. package/skills/wix-headless-templates/rentals/seed/SEED.md +1 -1
  70. package/skills/wix-headless-templates/rentals/seed/seed-rentals.mjs +4 -2
  71. package/skills/wix-headless-templates/restaurants/rest/menu.ts +4 -4
  72. package/skills/wix-headless-templates/restaurants/rest/ordering.ts +5 -5
  73. package/skills/wix-headless-templates/restaurants/rest/reservations.ts +4 -4
  74. package/skills/wix-headless-templates/restaurants/seed/SEED.md +1 -1
  75. package/skills/wix-headless-templates/restaurants/seed/seed-restaurants.mjs +6 -4
  76. package/skills/wix-headless-templates/shared/capabilities/site-search/rest/search.ts +4 -4
  77. package/skills/wix-headless-templates/shared/capabilities/site-search/seed/install.mjs +6 -4
  78. package/skills/wix-headless-templates/shared/seed/images.mjs +41 -5
  79. package/skills/wix-headless-templates/shared/seed/main.mjs +15 -0
  80. package/skills/wix-headless-templates/shared/seed/wix-cli.mjs +43 -11
  81. package/skills/wix-headless-templates/storefront/INSTRUCTIONS.md +1 -1
  82. package/skills/wix-headless-templates/storefront/rest/cart.ts +5 -5
  83. package/skills/wix-headless-templates/storefront/rest/catalog.ts +5 -5
  84. package/skills/wix-headless-templates/storefront/seed/SEED.md +44 -14
  85. package/skills/wix-headless-templates/storefront/seed/seed-store.mjs +23 -15
  86. package/skills/wix-manage/SKILL.md +28 -18
  87. package/skills/wix-manage/references/app-installation/install-wix-apps.md +5 -1
  88. package/skills/wix-manage/references/app-installation/list-installed-apps.md +19 -9
  89. package/skills/wix-manage/references/automations/activation-status.md +52 -0
  90. package/skills/wix-manage/references/automations/api-catalog.md +81 -0
  91. package/skills/wix-manage/references/automations/build-and-manage-automations.md +34 -0
  92. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -0
  93. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +277 -363
  94. package/skills/wix-manage/references/bookings/external-calendar-integration.md +3 -0
  95. package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +3 -0
  96. package/skills/wix-manage/references/cms/cms-data-items-crud.md +11 -2
  97. package/skills/wix-manage/references/cms/cms-publishing-flow.md +63 -16
  98. package/skills/wix-manage/references/custom-apps/use-app-skills-and-app-tools.md +3 -1
  99. package/skills/wix-manage/references/forms/update-form.md +3 -0
  100. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +3 -0
  101. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +3 -0
  102. package/skills/wix-manage/references/sites/create-headless-site.md +7 -50
  103. package/skills/wix-manage/references/sites/manage-oauth-apps.md +4 -4
  104. package/skills/wix-manage/references/sites/read-site-context.md +4 -0
  105. package/skills/wix-manage/references/sites/send-feedback-to-wix.md +92 -0
  106. package/skills/wix-manage/references/sites/upload-static-site.md +298 -283
  107. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +3 -0
  108. package/skills/wix-manage/references/stores/change-store-currency.md +3 -0
  109. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +3 -0
  110. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +3 -0
  111. package/skills/wix-manage/references/stores/update-product-with-options.md +192 -22
  112. package/skills/wix-manage/references/bookings/create-appointment-service.md +0 -243
  113. package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +0 -31
  114. package/skills/wix-manage/references/bookings/create-class-service.md +0 -222
  115. 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: Modifies existing products and variants using Catalog V3 Products API. Covers adding/removing option choices, variant-specific pricing, product visibility (hide, unhide, or show a product in the storefront — a product-level `visible` update, never a delete), and revision-based updates to prevent conflicts.
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
- - For simple text/HTML description updates, prefer `plainDescription`. Use `description` only when sending a Rich Content object.
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
- "expression": "Product name"
28
+ "search": {
29
+ "expression": "Product name",
30
+ "fields": ["name"],
31
+ "fuzzy": false
32
+ }
28
33
  }
29
34
  }'
30
35
  ```
31
36
 
32
- For product-name lookup, prefer Search Products before retrieving the product by ID. Search only resolves the product ID; it does not replace the Get Product call.
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 Only
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 normal user request like "set the product description to X", use `plainDescription` with valid HTML. The API converts it to rich content.
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
- Use `description` only when you intentionally need to send Rich Content:
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
- # this exact shape is the one that succeeds; the two shortcuts (choices by name only, or a variant
343
- # without its choices/price) each 400.
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
- A `DIGITAL` product is **sellable** only when its variant carries both a digital file and stock. Upload the file first ([Upload Media to Wix](../media/upload-media-to-wix.md) → Generate Upload URL, then `PUT` the bytes), then send its `file.id` on the variant — `digitalProperties` is a variant field, never a product field.
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
- "id": "{existingVariantId}",
404
- "price": { "actualPrice": { "amount": "9.99" } },
405
- "visible": true,
406
- "inventoryItem": { "inStock": true },
407
- "digitalProperties": { "digitalFile": { "id": "{fileId}" } }
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) | Set `inventoryItem.inStock: true` on the variant |
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