@wix/agent-skills 1.31.1 → 1.32.0
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/README.md +4 -12
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +39 -15
- package/skills/wix-app/references/BACKEND_API.md +1 -1
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +11 -8
- package/skills/wix-app/references/SDK_MODULE_MAP.md +1 -1
- package/skills/wix-app/references/STORES_VERSIONING.md +24 -2
- package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +9 -13
- package/skills/wix-app/references/dashboard-page/IMAGE_RENDERING.md +61 -0
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +54 -64
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +14 -21
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +37 -30
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +43 -29
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +40 -39
- package/skills/wix-app/references/editor-react-component/PARTS.md +8 -6
- package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +22 -2
- package/skills/wix-app/scripts/scan-a11y-eslint.cjs +39 -16
- package/skills/wix-app/scripts/sdk-curated.json +45 -0
- package/skills/wix-app/scripts/sdk-lookup.cjs +1180 -0
- package/skills/wix-base44-connector/SKILL.md +4 -2
- package/skills/wix-base44-connector/scripts/utils.cjs +5 -2
- package/skills/wix-headless-kit/SKILL.md +20 -8
- package/skills/wix-headless-kit/guides/api-run.md +92 -68
- package/skills/wix-headless-kit/guides/existing-site.md +6 -0
- package/skills/wix-headless-kit/install/AGENTS.md +3 -2
- package/skills/wix-headless-kit/install/attach.mjs +32 -27
- 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 +49 -5
- package/skills/wix-headless-kit/install/deploy.mjs +33 -8
- 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 +16 -25
- package/skills/wix-headless-kit/install/templates.mjs +2 -2
- 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-blog.mjs +2 -1
- 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-bookings.mjs +2 -1
- 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-donations.mjs +2 -1
- 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-events.mjs +2 -1
- 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-portfolio.mjs +2 -1
- 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-rentals.mjs +2 -1
- 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-restaurants.mjs +2 -1
- 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/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 +27 -9
- package/skills/wix-headless-templates/storefront/seed/seed-store.mjs +2 -1
- package/skills/wix-manage/SKILL.md +31 -9
- 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/actions.md +134 -0
- package/skills/wix-manage/references/automations/activation-status.md +64 -48
- package/skills/wix-manage/references/automations/api-catalog.md +213 -77
- package/skills/wix-manage/references/automations/automation-model.md +199 -0
- package/skills/wix-manage/references/automations/bracket-expressions.md +132 -0
- package/skills/wix-manage/references/automations/build-and-manage-automations.md +305 -26
- package/skills/wix-manage/references/automations/triggers.md +190 -0
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -0
- 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/collaborators/manage-site-collaborators.md +128 -0
- package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +3 -1
- package/skills/wix-manage/references/forms/read-forms-and-submissions.md +277 -0
- package/skills/wix-manage/references/forms/update-form.md +8 -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/seo/manage-url-redirects.md +33 -4
- package/skills/wix-manage/references/sites/create-headless-site.md +16 -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/upload-static-site.md +368 -261
- 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-vibe-headless/references/shared/app/components/WixManageBanner.jsx +3 -3
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Automations Trigger Configuration"
|
|
3
|
+
description: "Select and configure automation triggers, trigger filters and event payload schemas using the site catalog."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **Stage scope:** this stage covers only what [Build and Manage Wix Automations](https://dev.wix.com/docs/api-reference/business-management/automations/skills/build-and-manage-wix-automations) lists; do not perform anything marked "Later stages only" or any workflow that needs a guide marked "not yet published". "Stage", "Later stages only" and "not yet published" describe how this skill is being rolled out; never mention them to the user. Explain a limit in product terms: what can't be done through the API here and where the user can do it instead (for example, in the automations builder).
|
|
7
|
+
|
|
8
|
+
# Triggers — Discovery, Payload Schema, Filters
|
|
9
|
+
|
|
10
|
+
**TL;DR**
|
|
11
|
+
|
|
12
|
+
- A trigger is `appId` (GUID) + `triggerKey` (string). Find real ones with **Resolve Triggers** (installed apps only); never invent a key or reuse one from an example.
|
|
13
|
+
- There is no trigger `description` field. Choose by `displayName` + `triggerKey` + **payload schema** + available **filters** — names are ambiguous.
|
|
14
|
+
- Only filters listed in the trigger's `filters` array can be used. A payload field without a filter definition is NOT filterable (use a condition step instead — see Automations Conditions (not yet published)).
|
|
15
|
+
- A saved filter is `{ id, fieldKey, filterExpression }` with one of exactly two builder-readable expression shapes (§4.2). Values are always a literal array. Entity values are **ids**, never names.
|
|
16
|
+
- Required filters, and required follow-ups of any filter you set, must be present. The builder writes BOOLEAN (and defaulted NUMBER) filters itself — save them too (§4.1).
|
|
17
|
+
- Triggers with `implementedMethods.getDynamicSchema: true` expose more payload fields once their schema-changing filters are chosen — fetch the dynamic schema (§5) before mapping anything downstream.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. APIs used here
|
|
22
|
+
|
|
23
|
+
Site-scoped (`wix-site-id` header), SDK module `triggerCatalog`: Resolve Triggers (installed apps) · Get Trigger By App Id And Key (filters, payload schema) · Get Trigger Dynamic Schema · Get Identities Schema · Query Triggers (whole catalog, regardless of installation). Paths and request shapes: [Automations API Catalog](https://dev.wix.com/docs/api-reference/business-management/automations/skills/automations-api-catalog) §3.
|
|
24
|
+
|
|
25
|
+
## 2. Finding the right trigger
|
|
26
|
+
|
|
27
|
+
1. **List cheaply**: Resolve Triggers with `basicFieldsOnly: true` (drops schemas and filters) and pages of ≤ 25; page until `paging.total` is reached, de-duplicating ([Automations API Catalog](https://dev.wix.com/docs/api-reference/business-management/automations/skills/automations-api-catalog) §6).
|
|
28
|
+
2. **Narrow**: when you know the app, pass `appId` (returns all that app's triggers regardless of maturity; the app must be installed). You may also put `appId` / `triggerKey` in `query.filter`; if the filter is rejected, page and filter locally.
|
|
29
|
+
3. **Search locally** over `displayName` and `triggerKey`: the user's phrase → the domain noun ("booking", "form", "order", "member") → synonyms ("appointment"/"session", "purchase"/"order placed"). Keys usually start with the app prefix (`wix_bookings-`, …).
|
|
30
|
+
4. **Fetch details** for the 1–3 best candidates only: Get Trigger By App Id And Key.
|
|
31
|
+
5. **Disambiguate by schema, not name** ("Session booked" vs "Appointment request approved" for "booking confirmed"): read `payloadDataSchema` titles and `filters` to confirm the event and that the downstream data exists. If two remain equally plausible and it matters, ask.
|
|
32
|
+
6. Only in Query Triggers, not Resolve Triggers → its app isn't installed (tell the user to install it) or, with `maturity` `CREATED` / not GA, it isn't available to sites yet (§5 of Automations Feasibility and Planning (not yet published)).
|
|
33
|
+
|
|
34
|
+
Selection guidance for overlapping families:
|
|
35
|
+
|
|
36
|
+
- Compare, in order: which trigger offers the filters you need → which exposes the payload (or dynamic schema) you need → site context → default to the newer/standard family.
|
|
37
|
+
- Forms: default to the **Wix Forms App** family — app `225dd912-7dea-4738-8688-4b8c6955ffc2`, key `wix_form_app-form_submitted`. Use the older app `14ce1214-b278-a7e4-1373-00cebd1bef7c`, key `wix_forms-form_submit` only when the site's forms live there (check which app the form id comes from). For a named form or choice value, prefer the trigger whose filter expresses it over a generic trigger + condition.
|
|
38
|
+
- Scheduled trigger → §4 of Automations Schemas and Scheduling (not yet published). Webhook / custom trigger → later stages only (not in stage 2).
|
|
39
|
+
|
|
40
|
+
## 3. Reading the trigger object
|
|
41
|
+
|
|
42
|
+
| Field | Use |
|
|
43
|
+
| -------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
44
|
+
| `appId`, `triggerKey` | Copy verbatim into `configuration.trigger`. |
|
|
45
|
+
| `displayName` | What the user sees. Not a unique key. |
|
|
46
|
+
| `payloadDataSchema` | JSON Schema of the event payload — the only trigger data you may reference. |
|
|
47
|
+
| `filters[]` (≤5, each with `followUpFilters[]` ≤5) | The only filterable fields (§4). |
|
|
48
|
+
| `implementedMethods.getDynamicSchema` | `true` → payload grows with filter choice (§5). |
|
|
49
|
+
|
|
50
|
+
Payload schema annotations you will meet:
|
|
51
|
+
|
|
52
|
+
- `format`: `uuid`, `date-time`, `date`, `email`, `uri`, `number` (a numeric string — wrap it in `toNumber()` in numeric functions).
|
|
53
|
+
- `identityType: "contact" | "member"` on an id field → the aggregated payload also contains a root-level `contact` / `member` object (keys and rules: [Automations Graph and Data Model](https://dev.wix.com/docs/api-reference/business-management/automations/skills/automations-graph-and-data-model) §4). `visitor` ids stay plain fields with no enrichment.
|
|
54
|
+
- `itemsSelectionConfiguration.providerKey` / `.tag` → the field holds an **entity id** (service, form, label, product, …). Compare it only to ids (see Automations Entity and Provider Configuration (not yet published)).
|
|
55
|
+
- `wixCustomType` fixed shapes: `MONEY` `{value: string, currency: string}` · `ORDER_ID`/`ORDER_PAYMENT_ID`/`RECEIPT_ID`/`RECEIPT_PRESET_ID` uuid strings · `ATTACHMENT` `{fileName, downloadUrl}` · `IMAGE_URL` uri string · `FIELDS` array of `{label, value}` · `RECEIPT` complex object.
|
|
56
|
+
- `futureDate: true` on a date-time field → the trigger supports a "before the event" offset (§5 of Automations Schemas and Scheduling (not yet published)).
|
|
57
|
+
- `hidden: true` → not shown in pickers but still referenceable. `examples` show real value shapes.
|
|
58
|
+
|
|
59
|
+
## 4. Filters
|
|
60
|
+
|
|
61
|
+
### 4.1 Filter definition (catalog)
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"id": "<filter-uuid>",
|
|
66
|
+
"fieldKeyType": "STATIC_FIELD_KEY",
|
|
67
|
+
"staticFieldKey": "service_id",
|
|
68
|
+
"valueInput": {
|
|
69
|
+
"type": "ENTITY_SELECTOR",
|
|
70
|
+
"label": "Select services",
|
|
71
|
+
"required": false,
|
|
72
|
+
"reevaluateDynamicSchema": true,
|
|
73
|
+
"entitySelector": {
|
|
74
|
+
"id": "<provider-key>",
|
|
75
|
+
"multiSelect": true,
|
|
76
|
+
"queryFieldToFilterIdMapping": {},
|
|
77
|
+
"queryFieldToValueMapping": {}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"followUpFilters": []
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Values you put in the expression, by `valueInput.type` (anything else is dropped or rewritten when the panel opens):
|
|
85
|
+
|
|
86
|
+
- `ENTITY_SELECTOR`: entity ids as **quoted strings**, of the kind named by `entitySelector.id` / the field's `itemsSelectionConfiguration` — from the vertical's public API or the user (Automations Entity and Provider Configuration (not yet published)). `multiSelect: false` → one id.
|
|
87
|
+
- `STATIC_ITEMS`: quoted strings equal to a `staticValues[].value` that has a `displayName` (not the `displayName`, not the item `id`, never bare numbers).
|
|
88
|
+
- `USER_INPUT` `NUMBER`: exactly ONE bare number within `numberInputOptions.minValue`/`maxValue`. `BOOLEAN`: exactly ONE bare `true`/`false`.
|
|
89
|
+
|
|
90
|
+
The builder writes some filters by itself when the trigger panel opens; save them too or the automation shows an unsaved change: every `USER_INPUT` `BOOLEAN` filter (user's value, else `booleanInputOptions.defaultValue`, else `false`) and every `NUMBER` filter that has a numeric `defaultValue` (user's value, else that default).
|
|
91
|
+
|
|
92
|
+
### 4.2 Saved filter and the two allowed expression shapes
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"id": "<same filter id as the catalog>",
|
|
97
|
+
"fieldKey": "<staticFieldKey verbatim>",
|
|
98
|
+
"filterExpression": "{{contains([\"<id-1>\",\"<id-2>\"];var(\"service_id\"))}}"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Shape A — scalar field** (`staticFieldKey` has no `[0]`):
|
|
103
|
+
`{{contains([<values>];var("<fieldKey>"))}}`
|
|
104
|
+
|
|
105
|
+
**Shape B — array-backed field** (`staticFieldKey` contains one `[0]`, e.g. `formIds[0]`, `forms[0].data.id`). `[0]` stands for "every item", not item zero. Split into `arrayPath` (before `[0]`) and `itemPath` (after `[0].`, may be empty):
|
|
106
|
+
|
|
107
|
+
- empty `itemPath`: `{{arraySome([<values>];contains(var("<arrayPath>");$_))}}`
|
|
108
|
+
- non-empty: `{{arraySome([<values>];contains(arrayMap(var("<arrayPath>");"<itemPath>");$_))}}`
|
|
109
|
+
|
|
110
|
+
MUST:
|
|
111
|
+
|
|
112
|
+
- `id` = the catalog filter `id`; `fieldKey` = `staticFieldKey` character for character, `[0]` included.
|
|
113
|
+
Read both from the trigger's full `filters[]`: Get Trigger By App Id And Key (§2 step 4), or a
|
|
114
|
+
Resolve Triggers result without `basicFieldsOnly`. A compact listing (`basicFieldsOnly`, a
|
|
115
|
+
`fields` projection, or your own local strip of the catalog) has no filter definitions; if your
|
|
116
|
+
copy lacks `filters[]`, fetch the trigger — never invent an `id` or `fieldKey`.
|
|
117
|
+
- Values are ALWAYS a literal array, even for one value (`["x"]`). Types match the field: strings quoted, numbers/booleans bare.
|
|
118
|
+
- `;` between arguments, double quotes only, no spaces, one non-empty expression per filter (an empty/missing `filterExpression` is a builder error), max 5 filters.
|
|
119
|
+
- String literals inside `{{…}}` (values and the `var` path) are URI-encoded like every bracket literal ([Automations Mapping Expressions](https://dev.wix.com/docs/api-reference/business-management/automations/skills/automations-mapping-expressions) §1).
|
|
120
|
+
- Order `filters` as the catalog lists them, depth-first (each filter, then its follow-ups): the builder re-appends each filter in that order on panel open and compares deep-equal.
|
|
121
|
+
|
|
122
|
+
NEVER:
|
|
123
|
+
|
|
124
|
+
- `var("forms[0].id")` — validates, but checks only the first item.
|
|
125
|
+
- `contains(var("formIds");"x")` (value outside an array) — the builder cannot read it back.
|
|
126
|
+
- Any other function (`stringEq`, `arrayIncludesAnyOf`, `not`, …) in a filter — the filter panel only parses `contains` and `arraySome`.
|
|
127
|
+
- Filters on a field key with two array boundaries (`forms[0].ids[0]`), a literal index (`forms[1].id`) or a leaf that is an object/array rather than a string/number/boolean. There is no valid expression: configure the supported filters, tell the user this one is unavailable, and offer a condition step if the data is in the payload.
|
|
128
|
+
|
|
129
|
+
Updating an array-backed filter: change only the values array; keep the shape and `fieldKey`.
|
|
130
|
+
|
|
131
|
+
### 4.3 Required, follow-up and dependent filters
|
|
132
|
+
|
|
133
|
+
- `valueInput.required: true` on a top-level filter → the filter MUST be saved. No user preference is not a reason to ask: pick a sensible default from the filter's own options (an "Any/All" option the trigger offers is fine); there is no wildcard expression. If it is also single-select (`multiSelect: false`), the trigger fires for exactly ONE chosen entity: a request for "any label/any service…" cannot be met with this trigger — offer: pick one, one automation per entity, or a different trigger. Check this during feasibility, before planning.
|
|
134
|
+
- A follow-up filter marked required is mandatory **only if its parent filter is set**. Setting a parent obliges you to set all its required follow-ups.
|
|
135
|
+
- NEVER save a follow-up without its parent: the builder hides it and deletes it when the panel opens. Only `ENTITY_SELECTOR` follow-ups of `ENTITY_SELECTOR` parents are shown at all.
|
|
136
|
+
- `entitySelector.queryFieldToFilterIdMapping` (`{"workflowId": "<parent-filter-id>"}`): options depend on the parent's value. Choose the parent first, then fetch child ids scoped to it (workflow → stage, program → step).
|
|
137
|
+
- `queryFieldToValueMapping` (`{"eventType": "RSVP"}`): options are pre-narrowed; pick ids from that subset, nothing extra in the expression.
|
|
138
|
+
|
|
139
|
+
Dependent example:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
"filters": [
|
|
143
|
+
{ "id": "<program-filter-id>", "fieldKey": "programId",
|
|
144
|
+
"filterExpression": "{{contains([\"<program-id>\"];var(\"programId\"))}}" },
|
|
145
|
+
{ "id": "<step-filter-id>", "fieldKey": "programStepId",
|
|
146
|
+
"filterExpression": "{{contains([\"<step-id-1>\",\"<step-id-2>\"];var(\"programStepId\"))}}" }
|
|
147
|
+
]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 4.4 `DYNAMIC_FIELD_KEY` filters
|
|
151
|
+
|
|
152
|
+
The field to filter on is itself selected (`dynamicFieldKey.entitySelector`, dependent on a parent such as the form). Resolve the parent first, then:
|
|
153
|
+
|
|
154
|
+
- **The key** = the id of the field as that field-key selector lists it — the builder saves it as `fieldKey` and passes the same string to the value picker as its `fieldTarget`. For Wix Forms ("Option chosen on a form") that is the form field's **`target`** from the Forms API (`multi_choice_5734`) — not the dynamic-schema property key (`field:multi_choice_5734`, used only in `var()` paths of later steps) and not the field's uuid `id`.
|
|
155
|
+
- **The expression** is **Shape A** with that same key: `{{contains(["<value-1>"];var("<key>"))}}`. The builder reads the chosen key back from the `var(...)` and treats the filter as required; Shape B is never used here.
|
|
156
|
+
- **The values**: if `valueInput` is an `ENTITY_SELECTOR` scoped to that field (form choices), use the choice option's `value` from the Forms API (what a submission stores, e.g. `"Walter"`), quoted and URI-encoded (§4.2). The value picker's own ids aren't public, so this is a best match, and Validate checks neither key nor values: tell the user to open the trigger in the builder and confirm the field and choice show by name.
|
|
157
|
+
- Can't list the fields → ask the user.
|
|
158
|
+
|
|
159
|
+
## 5. Dynamic-schema triggers — filters come first
|
|
160
|
+
|
|
161
|
+
When `implementedMethods.getDynamicSchema` is `true`:
|
|
162
|
+
|
|
163
|
+
1. Decide the filter values, especially those with `valueInput.reevaluateDynamicSchema: true` (which form, which service).
|
|
164
|
+
2. Call Get Trigger Dynamic Schema with what the builder sends: one entry per **saved** filter (`fieldKey` verbatim, its string values); if no filter is saved, each `reevaluateDynamicSchema` filter's `staticFieldKey` with `values: []`:
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"appId": "<app-id>",
|
|
168
|
+
"triggerKey": "<trigger-key>",
|
|
169
|
+
"selectedFilterOptions": [
|
|
170
|
+
{ "fieldKey": "formId", "values": ["<form-id>"] }
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
**Merge** the response into the static schema: take `payloadDataSchema` and overlay `dynamicSchema.properties` on its `properties` (dynamic wins on a key clash). The dynamic schema alone usually lacks static fields such as `contactId` — never use it by itself.
|
|
175
|
+
3. Map and condition only on fields present in that schema. Labels differ from keys — copy keys from the schema.
|
|
176
|
+
4. No filter chosen ⇒ entity-specific fields (form answers) are **unknown, not absent**, whatever the `values: []` call returns. Never map or condition on a form-answer field without the form filter: use only static fields (`contactId`, submission time, …) or ask which form, set that filter, then fetch the dynamic schema.
|
|
177
|
+
|
|
178
|
+
## 6. Webhook and custom triggers
|
|
179
|
+
|
|
180
|
+
> **Later stages only:** not available in stage 2; this section is published in stage 3.
|
|
181
|
+
|
|
182
|
+
## 7. Pre-save checklist
|
|
183
|
+
|
|
184
|
+
- [ ] `appId` + `triggerKey` came from Resolve Triggers on this site.
|
|
185
|
+
- [ ] Every filter `id` exists in the catalog trigger (or a follow-up); `fieldKey` is verbatim.
|
|
186
|
+
- [ ] Every expression is Shape A or Shape B (Shape A for dynamic field keys); values in a literal array; types per §4.1; ids, not names; no follow-up without its parent.
|
|
187
|
+
- [ ] Every `BOOLEAN` filter, and every `NUMBER` filter with a default, is saved.
|
|
188
|
+
- [ ] All required filters present; required follow-ups present for every set parent.
|
|
189
|
+
- [ ] For dynamic-schema triggers, downstream steps use the schema returned for the chosen filters.
|
|
190
|
+
- [ ] Final gate: Validate Automation returns no `triggerValidationErrors`.
|
|
@@ -5,6 +5,9 @@ description: Sets up booking policies, cancellation rules, and waitlist configur
|
|
|
5
5
|
|
|
6
6
|
# Technical Step-by-Step Instructions: Configuring Wix Bookings Service Policies (Real-World, API-First)
|
|
7
7
|
|
|
8
|
+
> These calls need the Wix Bookings app on the site (`appDefId` `13d21c63-b5ec-5912-8397-c3a5ddb27a97`); 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
|
## Description
|
|
9
12
|
|
|
10
13
|
Below are the recommended steps to successfully configure booking, cancellation, and waitlist policies for Wix Bookings services. This recipe covers policy inheritance, service-specific overrides, and common policy configurations for different business models.
|
|
@@ -4,6 +4,9 @@ description: OAuth-based integration with Google Calendar, Microsoft Outlook, an
|
|
|
4
4
|
---
|
|
5
5
|
# Technical Step-by-Step Instructions: Connecting External Calendars (Google, Microsoft, Apple) to Wix Bookings (Real-World, API-First)
|
|
6
6
|
|
|
7
|
+
> These calls need the Wix Bookings app on the site (`appDefId` `13d21c63-b5ec-5912-8397-c3a5ddb27a97`); 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
|
## Description
|
|
8
11
|
|
|
9
12
|
Below are the recommended steps to successfully connect and sync external calendars (Google Calendar, Microsoft Outlook, Apple Calendar) with Wix Bookings, with real-world troubleshooting and fixes for common API issues. This recipe covers the complete OAuth flow, sync configuration, and verification procedures.
|
|
@@ -4,6 +4,9 @@ description: Creates resource types and individual resources using Resources API
|
|
|
4
4
|
---
|
|
5
5
|
# Technical Step-by-Step Instructions: Creating Multi-Resource Bookings Services (Rooms, Equipment, Staff) - Real-World, API-First
|
|
6
6
|
|
|
7
|
+
> These calls need the Wix Bookings app on the site (`appDefId` `13d21c63-b5ec-5912-8397-c3a5ddb27a97`); 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
|
## Description
|
|
8
11
|
|
|
9
12
|
Below are the recommended steps to successfully create Wix Bookings services that require multiple resource types (e.g., Room + Equipment + Instructor). This recipe covers the **gaps** in individual API documentation: resource architecture planning, entity relationship patterns, availability dependencies, and real-world coordination challenges that aren't clear from reading individual API references.
|
|
@@ -4,6 +4,9 @@ description: "Add, query, update, and delete items in CMS collections, one at a
|
|
|
4
4
|
---
|
|
5
5
|
# CMS Data Items CRUD
|
|
6
6
|
|
|
7
|
+
> These calls need the Wix CMS app on the site (`appDefId` `e593b0bd-b783-45b8-97c2-873d42aacaf4`); 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
|
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`.
|
|
8
11
|
|
|
9
12
|
This recipe covers Create, Read, Update, Delete (CRUD) operations for Wix CMS data items, plus count, upsert, truncate, aggregate, and reference-field links.
|
|
@@ -175,6 +178,8 @@ curl -X GET \
|
|
|
175
178
|
|
|
176
179
|
**Endpoint**: `PUT https://www.wixapis.com/wix-data/v2/items/{itemId}`
|
|
177
180
|
|
|
181
|
+
> **Warning**: This replaces the entire item — fields not in `dataItem.data` are deleted. To change only some fields, use [Patch Data Item](#patch-data-item-partial-update---single-item).
|
|
182
|
+
|
|
178
183
|
**Request Body**:
|
|
179
184
|
```json
|
|
180
185
|
{
|
|
@@ -233,6 +238,8 @@ Unlike Update, this only modifies the specified fields — all other fields rema
|
|
|
233
238
|
|
|
234
239
|
> There is no update-by-filter endpoint. To update the items matching a filter, query them first (see [Query Data Items](#query-data-items)), then send their ids to bulk update or bulk patch.
|
|
235
240
|
|
|
241
|
+
> **Note**: This replaces the entire item. Include all fields you want to keep, not just the ones you're changing.
|
|
242
|
+
|
|
236
243
|
> **Important**: Use `id` (not `_id`) at the element level. The `data` object should NOT contain `_id`.
|
|
237
244
|
|
|
238
245
|
```json
|
|
@@ -242,14 +249,18 @@ Unlike Update, this only modifies the specified fields — all other fields rema
|
|
|
242
249
|
{
|
|
243
250
|
"id": "item-guid-1",
|
|
244
251
|
"data": {
|
|
252
|
+
"title": "Wireless Headphones Pro",
|
|
245
253
|
"price": 159.99,
|
|
254
|
+
"description": "Premium wireless headphones",
|
|
246
255
|
"inStock": true
|
|
247
256
|
}
|
|
248
257
|
},
|
|
249
258
|
{
|
|
250
259
|
"id": "item-guid-2",
|
|
251
260
|
"data": {
|
|
261
|
+
"title": "Wired Earbuds",
|
|
252
262
|
"price": 89.99,
|
|
263
|
+
"description": "Compact wired earbuds",
|
|
253
264
|
"inStock": false
|
|
254
265
|
}
|
|
255
266
|
}
|
|
@@ -257,8 +268,6 @@ Unlike Update, this only modifies the specified fields — all other fields rema
|
|
|
257
268
|
}
|
|
258
269
|
```
|
|
259
270
|
|
|
260
|
-
> **Note**: This replaces the entire item. Include all fields you want to keep, not just the ones you're changing.
|
|
261
|
-
|
|
262
271
|
## Bulk Patch Items (Partial Update)
|
|
263
272
|
|
|
264
273
|
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/patch`
|
|
@@ -4,6 +4,9 @@ description: "Interact with CMS collections that gate their items behind a draft
|
|
|
4
4
|
---
|
|
5
5
|
# CMS Draft & Publish Workflow
|
|
6
6
|
|
|
7
|
+
> These calls need the Wix CMS app on the site (`appDefId` `e593b0bd-b783-45b8-97c2-873d42aacaf4`); 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
|
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`.
|
|
8
11
|
|
|
9
12
|
Some CMS collections gate their items behind a **draft/publish workflow** instead of writing straight to the live site. Such a collection has the **Draft Items plugin** installed. Each item is in one of three states — **DRAFT**, **PUBLISHED**, or **CHANGED** (a published item with a pending draft edit) — and edits are staged as drafts until explicitly published.
|
|
@@ -59,6 +62,8 @@ curl -X GET \
|
|
|
59
62
|
- **Draft Items plugin present** → the collection gates items behind draft/publish. Its `draftItemsPluginOptions.draftsCollectionId` gives the paired drafts collection to author and edit drafts against.
|
|
60
63
|
- **Draft Items plugin absent** → plain collection; every insert/update goes straight live. No draft surface exists.
|
|
61
64
|
|
|
65
|
+
Once the Draft Items plugin is installed, do not insert, update, patch, remove, or save items directly in the published collection. Read `draftItemsPluginOptions.draftsCollectionId` from the plugin and write new items and pending edits to that drafts collection. Then call **Publish Data Item Draft** (`POST /wix-data/v2/items/publish-draft`) to publish an item to the published collection. This lifecycle operation takes the published collection ID; it is the supported way to move a draft into the live collection.
|
|
66
|
+
|
|
62
67
|
---
|
|
63
68
|
|
|
64
69
|
## 2. Read items
|
|
@@ -90,7 +95,7 @@ Reads target a specific surface — there is no merged view:
|
|
|
90
95
|
|
|
91
96
|
### Author a brand-new draft
|
|
92
97
|
|
|
93
|
-
Insert into the **drafts** collection. The item starts as **DRAFT**.
|
|
98
|
+
Insert into the **drafts** collection. Do not insert into the published collection while the Draft Items plugin is installed. The item starts as **DRAFT** and becomes live only after you call **Publish Data Item Draft**.
|
|
94
99
|
|
|
95
100
|
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items`
|
|
96
101
|
|
|
@@ -109,13 +114,30 @@ Update or patch against the **drafts** collection (`articles__drafts`). See [CMS
|
|
|
109
114
|
|
|
110
115
|
### Edit a PUBLISHED item → produces CHANGED
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
**PUT and PATCH against the published collection fail while the Draft Items plugin is installed.** Create a draft of the published item, then edit that draft in the paired drafts collection. The published version remains live and unchanged until the draft is published.
|
|
113
118
|
|
|
114
|
-
|
|
119
|
+
1. Call [Create Data Item Draft](https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/create-data-item-draft) with the published collection ID and item ID. It returns `dataItem`, a full draft copy with the same item ID; `dataItem.dataCollectionId` identifies the paired drafts collection. The item is now CHANGED.
|
|
120
|
+
2. Update or patch the returned draft using the drafts collection ID. Use Patch Data Item to preserve fields you did not change; Update Data Item replaces the draft's entire payload.
|
|
121
|
+
3. Call Publish Data Item Draft with the published collection ID to make the edits live.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Create a draft of a PUBLISHED item; the lifecycle call takes the published collection ID.
|
|
125
|
+
curl -X POST 'https://www.wixapis.com/wix-data/v2/items/create-draft' \
|
|
126
|
+
-H 'Content-Type: application/json' \
|
|
127
|
+
-H 'Authorization: <AUTH>' \
|
|
128
|
+
-d '{"dataCollectionId":"articles","dataItemId":"<id>"}'
|
|
129
|
+
# Patch the resulting draft; use its returned dataCollectionId, not the published collection ID.
|
|
130
|
+
curl -X PATCH 'https://www.wixapis.com/wix-data/v2/items/<id>' \
|
|
131
|
+
-H 'Content-Type: application/json' \
|
|
132
|
+
-H 'Authorization: <AUTH>' \
|
|
133
|
+
-d '{"dataCollectionId":"<draftsCollectionId>","patch":{"dataItemId":"<id>","fieldModifications":[{"fieldPath":"body","action":"SET_FIELD","setFieldOptions":{"value":"Revised article body"}}]}}'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
For a CHANGED item, edit its existing draft directly. Create Data Item Draft returns `ALREADY_EXISTS` if a draft already exists; query the paired drafts collection when the item's state is unknown.
|
|
115
137
|
|
|
116
138
|
### Publish a pending draft (DRAFT/CHANGED → PUBLISHED)
|
|
117
139
|
|
|
118
|
-
|
|
140
|
+
Call **Publish Data Item Draft** to publish the pending draft. It replaces the published item's data with the draft's content; the draft is then deleted. Pass the **published** collection ID. This lifecycle operation is the allowed way to write the draft's content to the published collection.
|
|
119
141
|
|
|
120
142
|
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/publish-draft`
|
|
121
143
|
|
|
@@ -161,12 +183,12 @@ curl -X POST \
|
|
|
161
183
|
}'
|
|
162
184
|
```
|
|
163
185
|
|
|
164
|
-
`copyToDraft` controls the
|
|
186
|
+
`copyToDraft` controls whether the published data is copied into the drafts collection:
|
|
165
187
|
|
|
166
188
|
| `copyToDraft` | Behavior | Use for |
|
|
167
189
|
|---------------|----------|---------|
|
|
168
|
-
| `true` (default) | Removes the live copy
|
|
169
|
-
| `false` | Removes the live copy **without** creating a draft. No `dataItem` returned. |
|
|
190
|
+
| `true` (default) | Removes the live copy and copies its data into a draft. Any existing pending draft for that ID is **overwritten**, discarding its unpublished edits. | Take the item offline and retain the previously-published content as a draft. |
|
|
191
|
+
| `false` | Removes the live copy **without** creating a draft. Any existing pending draft is **preserved unchanged**. No `dataItem` is returned. | Remove the live version while leaving any pending draft intact. |
|
|
170
192
|
|
|
171
193
|
- Response (`copyToDraft: true`) carries the **new draft**, not the removed live item.
|
|
172
194
|
- Returns `NOT_FOUND` if no published item exists with that id.
|
|
@@ -181,17 +203,38 @@ curl -X DELETE \
|
|
|
181
203
|
-H 'Authorization: <AUTH>'
|
|
182
204
|
```
|
|
183
205
|
|
|
184
|
-
### Delete
|
|
206
|
+
### Delete a published item permanently
|
|
185
207
|
|
|
186
|
-
|
|
208
|
+
> Permanent deletion is irreversible. Confirm with the user before calling Unpublish Data Item with `copyToDraft: false` or deleting a draft, unless the request already names the items to remove.
|
|
209
|
+
|
|
210
|
+
To permanently delete a published item, call **Unpublish Data Item** with `copyToDraft: false` to remove it from the published collection. This preserves any existing pending draft, so query the paired drafts collection for that item ID next. Delete the draft only if the query returns it; when no draft exists, skip the DELETE call. For a CHANGED item, this deletes its preserved pending draft. For a PUBLISHED item with no pending draft, unpublishing completes the deletion.
|
|
187
211
|
|
|
188
212
|
```bash
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
#
|
|
192
|
-
curl -X
|
|
213
|
+
# Stop on HTTP failures, malformed query responses, or failed deletes.
|
|
214
|
+
set -euo pipefail
|
|
215
|
+
# remove the published version without creating a draft
|
|
216
|
+
curl --fail --silent --show-error -X POST 'https://www.wixapis.com/wix-data/v2/items/unpublish' \
|
|
217
|
+
-H 'Content-Type: application/json' \
|
|
218
|
+
-H 'Authorization: <AUTH>' \
|
|
219
|
+
-d '{"dataCollectionId":"articles","dataItemId":"<id>","copyToDraft":false}'
|
|
220
|
+
# Query the paired drafts collection for this ID. Use the draftsCollectionId read from the plugin.
|
|
221
|
+
ITEM_ID='<id>'
|
|
222
|
+
DRAFTS_COLLECTION_ID='<draftsCollectionId>'
|
|
223
|
+
drafts=$(curl --fail --silent --show-error -X POST 'https://www.wixapis.com/wix-data/v2/items/query' \
|
|
224
|
+
-H 'Content-Type: application/json' \
|
|
225
|
+
-H 'Authorization: <AUTH>' \
|
|
226
|
+
-d "{\"dataCollectionId\":\"$DRAFTS_COLLECTION_ID\",\"consistentRead\":true,\"query\":{\"filter\":{\"_id\":\"$ITEM_ID\"},\"paging\":{\"limit\":1}}}")
|
|
227
|
+
# Require a valid dataItems array; a failed query must not be treated as an empty result.
|
|
228
|
+
draft_count=$(printf '%s' "$drafts" | jq -er '.dataItems | if type == "array" then length else error("Expected dataItems array") end')
|
|
229
|
+
# Delete only when the query found the draft; an empty dataItems array means there is nothing to delete.
|
|
230
|
+
if [ "$draft_count" -gt 0 ]; then
|
|
231
|
+
curl --fail --silent --show-error -X DELETE "https://www.wixapis.com/wix-data/v2/items/$ITEM_ID?dataCollectionId=$DRAFTS_COLLECTION_ID" \
|
|
232
|
+
-H 'Authorization: <AUTH>'
|
|
233
|
+
fi
|
|
193
234
|
```
|
|
194
235
|
|
|
236
|
+
If an item was never published and exists only in the drafts collection (DRAFT), delete it directly from the paired drafts collection. Do not call Unpublish Data Item; it returns `NOT_FOUND` when no published item exists.
|
|
237
|
+
|
|
195
238
|
---
|
|
196
239
|
|
|
197
240
|
## 4. Enable / disable the workflow on a collection
|
|
@@ -206,6 +249,7 @@ curl -X POST 'https://www.wixapis.com/wix-data/v2/collections/add-draft-items-pl
|
|
|
206
249
|
-H 'Authorization: <AUTH>' \
|
|
207
250
|
-d '{
|
|
208
251
|
"dataCollectionId": "articles",
|
|
252
|
+
"draftItemsOptions": {},
|
|
209
253
|
"publishPluginConflictAction": "FAIL_WHEN_PUBLISH_INSTALLED"
|
|
210
254
|
}'
|
|
211
255
|
```
|
|
@@ -258,16 +302,19 @@ At the REST level, every read/author/publish/unpublish call here goes through th
|
|
|
258
302
|
| PUBLISHED | Edit into a pending draft (→ CHANGED) | Create the draft (`createDataItemDraft`), then edit it on the drafts collection | Write Data Items |
|
|
259
303
|
| — | Create new draft (→ DRAFT) | `POST https://www.wixapis.com/wix-data/v2/items` on the drafts collection | Write Data Items |
|
|
260
304
|
| DRAFT / CHANGED | Publish (→ PUBLISHED) | `POST https://www.wixapis.com/wix-data/v2/items/publish-draft` (published id) | Write Data Items |
|
|
261
|
-
| PUBLISHED / CHANGED |
|
|
262
|
-
| PUBLISHED / CHANGED |
|
|
305
|
+
| PUBLISHED / CHANGED | Remove from live collection, keep as draft (→ DRAFT) | **Unpublish Data Item** — `POST https://www.wixapis.com/wix-data/v2/items/unpublish`, `copyToDraft:true` | Write Data Items |
|
|
306
|
+
| PUBLISHED / CHANGED | Remove live copy without creating a draft; preserve any existing draft | **Unpublish Data Item** — `POST https://www.wixapis.com/wix-data/v2/items/unpublish`, `copyToDraft:false` | Write Data Items |
|
|
263
307
|
| CHANGED | Revert to live version (discard edit) | `DELETE https://www.wixapis.com/wix-data/v2/items/{id}?dataCollectionId=<drafts id>` | Write Data Items |
|
|
264
|
-
|
|
|
308
|
+
| PUBLISHED / CHANGED | Permanently delete (confirm first unless the request names the item) | `POST https://www.wixapis.com/wix-data/v2/items/unpublish` with `copyToDraft:false` (published id), then query and delete any remaining draft | Write Data Items |
|
|
309
|
+
| DRAFT (never published) | Permanently delete (confirm first unless the request names the item) | `DELETE https://www.wixapis.com/wix-data/v2/items/{id}?dataCollectionId=<drafts id>` | Write Data Items |
|
|
265
310
|
| plain, no plugin | Enable workflow | `POST https://www.wixapis.com/wix-data/v2/collections/add-draft-items-plugin` | Manage Data Collections |
|
|
266
311
|
|
|
267
312
|
---
|
|
268
313
|
|
|
269
314
|
## Agent gotchas
|
|
270
315
|
|
|
316
|
+
- **Never write item data directly to the published collection while Draft Items is installed.** Create and edit items in the paired drafts collection, then call **Publish Data Item Draft** to publish. Lifecycle calls such as publish still take the published collection ID.
|
|
317
|
+
- **Choose the permanent-delete path from the item's state, and confirm first.** Permanent deletion is irreversible: confirm with the user before Unpublish Data Item with `copyToDraft: false` or a draft DELETE unless the request already names the items to remove. For PUBLISHED or CHANGED items, call Unpublish Data Item with the published collection ID and `copyToDraft: false`, then query and delete any remaining draft from the paired drafts collection. For a DRAFT that was never published, delete it directly from the paired drafts collection; Unpublish Data Item would return `NOT_FOUND`.
|
|
271
318
|
- **Resolve the drafts collection from the plugin.** Read `draftItemsPluginOptions.draftsCollectionId` off the published collection's Draft Items plugin rather than assuming a `__drafts` suffix.
|
|
272
319
|
- **Status is server-authoritative.** Derive DRAFT/PUBLISHED/CHANGED from the published + drafts surfaces (or the value the API returns). Never compute it locally, and never render an optimistic status before the write confirms (**confirm-then-render**).
|
|
273
320
|
- **Pass the *published* collection id** to `publish-draft` and `unpublish` — not the drafts collection id. Author and edit drafts against the drafts collection id.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Manage Site Collaborators"
|
|
3
|
+
description: Manages who has access to a Wix site as a collaborator (contributor) — finds the site's current collaborators, invites someone, removes a collaborator, and resends or revokes a pending collaborator invite. Use when the user wants to give someone access to the site, take it away, or follow up on an invitation that has not been accepted.
|
|
4
|
+
---
|
|
5
|
+
# Manage Site Collaborators
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
Changes who can work on a site: invite a collaborator, remove one, or resend / revoke an invitation that has not been accepted yet.
|
|
9
|
+
|
|
10
|
+
## API Endpoints
|
|
11
|
+
Each call runs at one of two scopes. Use the scope shown. A site call is made with site scope and the site ID in the tool's site ID parameter; that is the only way the site reaches Wix, so never add a site ID to the request body. An account call is made with account scope, which ignores the site ID.
|
|
12
|
+
|
|
13
|
+
| Scope | Call | Purpose |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Site | `GET https://www.wixapis.com/roles-management/v2/contributors/query` | list the site's collaborators |
|
|
16
|
+
| Site | `POST https://www.wixapis.com/roles-management/contributor/remove` | remove a collaborator |
|
|
17
|
+
| Account | `GET https://www.wixapis.com/roles-management/roles` | look up role IDs for invites |
|
|
18
|
+
| Site | `POST https://www.wixapis.com/invites/site-invite/bulk` | send invites (returns the `inviteId`s) |
|
|
19
|
+
| Site | `POST https://www.wixapis.com/invites/site-invite/{inviteId}/resend` | resend a pending invite |
|
|
20
|
+
| Site | `POST https://www.wixapis.com/invites/site-invite/{inviteId}/revoke` | revoke a pending invite |
|
|
21
|
+
|
|
22
|
+
Docs: [Contributors](https://dev.wix.com/docs/api-reference/account-level/user-management/sites/contributors/introduction), [Site Invites](https://dev.wix.com/docs/api-reference/account-level/user-management/sites/site-invites/introduction)
|
|
23
|
+
|
|
24
|
+
## What the APIs can and cannot look up
|
|
25
|
+
|
|
26
|
+
- **This recipe has everything you need for every call below: endpoint, request and response shape. Do not search the docs, read the method articles or query the API spec before calling.** Go straight to the call. If the user names someone only by email or name, your final message must ask for their account ID (or invite ID for an invite) — say this even when the lookup shows only the owner.
|
|
27
|
+
- **Never call Remove Contributor, revoke or resend until you have the exact ID from the user or from an earlier response.** Look-ups by email or name are not possible, so ask first. If the user names someone only by email or name, read this recipe, then reply asking for the account ID (and how to find it) — at most one Query Site Contributors call, and do not search other APIs for an email-to-account lookup or try bulk or guessed deletes. Your final message must say that collaborators can only be identified by account ID, and ask the user to provide it — even if the query failed or returned nothing useful.
|
|
28
|
+
- **Collaborators are identified by account ID, not email.** Query Site Contributors returns only `accountId` and `accountOwnerId` per collaborator. If the user names a collaborator by email or name, ask them for that person's account ID, or for how to find it, before removing anyone. Do not guess which account ID belongs to which person.
|
|
29
|
+
- **Invites are identified by `inviteId`.** There is no endpoint to list a site's pending invites. The `inviteId` is returned when the invite is created (`invites[].id` in the Bulk Invite response, Step 6) — keep it if you will need to resend or revoke later in the conversation. If the user does not have it, say that it cannot be looked up through the API and ask them to provide it.
|
|
30
|
+
- **Get Roles is the only account-level call** (account scope). Query Site Contributors, Remove Contributor, Bulk Invite, resend and revoke are site-level: make them with site scope and the site ID. Never make Bulk Invite, resend or revoke with account scope: the site is dropped and Wix rejects the call with a missing-site error. If a call is still rejected (403), the cause is not always visible in the response; stop, tell the user the call was refused, and do not call the later steps of the flow.
|
|
31
|
+
|
|
32
|
+
## Steps
|
|
33
|
+
|
|
34
|
+
### 1. Establish which action the user wants and on whom
|
|
35
|
+
|
|
36
|
+
| User wants | Needs | Go to |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| Remove someone who already has access | their `accountId` | Step 2, then Step 3 |
|
|
39
|
+
| Remove themselves | their own `accountId` | Step 7 |
|
|
40
|
+
| Invite someone new | their email(s) and a role (`policyIds`) | Step 6 |
|
|
41
|
+
| Cancel an invite not yet accepted | the `inviteId` | Step 4 |
|
|
42
|
+
| Resend an invite not yet accepted | the `inviteId` | Step 5 |
|
|
43
|
+
|
|
44
|
+
Removal works only on existing collaborators; revoke and resend work only on pending invites. Do not use one for the other.
|
|
45
|
+
|
|
46
|
+
**When the user names the person only by email**, work out what that email is before acting:
|
|
47
|
+
|
|
48
|
+
1. **Invited earlier in this conversation?** If the email matches an `invites[].email` from a Bulk Invite response you received, you have its `inviteId`: treat the person as an invitee (Step 4 or 5). If the user asked to *remove* them, cancel the invite (Step 4).
|
|
49
|
+
2. **Otherwise the email cannot be classified.** The APIs cannot say whether it belongs to a collaborator, a pending invitee, or nobody, so do not claim "not a collaborator" or "has no access". Say that collaborators are identified by account ID and invites by invite ID, and ask for the one that fits the request (for removal, the account ID). Do not guess from the contributors list.
|
|
50
|
+
3. **Wrong-mode guards.** Do not revoke or resend for someone the user says already has access, and do not remove someone the user says is only invited. In those cases tell the user which action applies instead (for example: "they have only been invited, so I can cancel the invite rather than remove them").
|
|
51
|
+
|
|
52
|
+
### 2. List the site's collaborators
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
GET https://www.wixapis.com/roles-management/v2/contributors/query
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
No filter is needed to list everyone. To narrow by role, pass `filter.policyIds` (up to 20 role IDs) as repeated query parameters. Response:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{ "contributors": [ { "accountId": "<account GUID>", "accountOwnerId": "<owner user GUID>" } ] }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Always run this read-only query before removing anyone. Use it to confirm the `accountId` the user gave is a current collaborator. If it is not in the list, stop and tell the user that account is not a collaborator on the site, so there is nothing to remove. If it is the site owner's account (it matches `accountOwnerId`), do not remove it: an owner can leave only after transferring ownership to another user. Tell the user that.
|
|
65
|
+
|
|
66
|
+
### 3. Remove a collaborator
|
|
67
|
+
|
|
68
|
+
Removal clears all of the collaborator's role assignments on the site, so they lose access. When the user gave the exact `accountId` and Step 2 shows it is a current collaborator (and not the owner), call it directly — do not ask for confirmation:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
POST https://www.wixapis.com/roles-management/contributor/remove
|
|
72
|
+
```
|
|
73
|
+
```json
|
|
74
|
+
{ "accountId": "<accountId from step 2>" }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The response is `{}` on success.
|
|
78
|
+
|
|
79
|
+
### 4. Revoke a pending invite
|
|
80
|
+
|
|
81
|
+
When the user named the invite (or you created it earlier in this conversation and hold its `inviteId`), call it directly with an empty JSON body `{}`. Ask only if you cannot tell which invite is meant:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
POST https://www.wixapis.com/invites/site-invite/{inviteId}/revoke
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The response is `{}`. Revoke applies to pending invites only; if the person has since accepted and appears in the Step 2 list, use Step 3 instead.
|
|
88
|
+
|
|
89
|
+
### 5. Resend a pending invite
|
|
90
|
+
|
|
91
|
+
When the user named the invite (or you created it earlier in this conversation and hold its `inviteId`), call it directly with an empty JSON body `{}`. Ask only if you cannot tell which invite is meant:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
POST https://www.wixapis.com/invites/site-invite/{inviteId}/resend
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The response contains the invite: `invite.id`, `invite.email`, `invite.status` (Pending, Used, Deleted, Declined, Expired) and `invite.expirationDate`. Report the status back to the user.
|
|
98
|
+
|
|
99
|
+
### 6. Send an invite
|
|
100
|
+
|
|
101
|
+
Ask the user for the email address(es) (1–10) and which role to grant; `policyIds` are role IDs, not names. Look them up with `GET https://www.wixapis.com/roles-management/roles` ([Get Roles Info](https://dev.wix.com/docs/api-reference/account-level/user-management/accounts/users/get-roles-info)), which returns `predefinedRoles` and `customRoles`. Add `?filter.role_level=SITE_LEVEL` to list only site roles. Each entry is `{ "id": "<role id>", "title": "...", "description": "..." }`; use the ID of the role the user chose, and do not guess an ID. If the user said "any" or "a standard role", pick from `predefinedRoles` the role whose `description` grants the least access (view or content editing, not managing, billing or ownership) and name its `title` in your final message; if they gave no role at all, ask which one. Once you have the emails and a role, send the invite without asking for confirmation:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
POST https://www.wixapis.com/invites/site-invite/bulk
|
|
105
|
+
```
|
|
106
|
+
```json
|
|
107
|
+
{ "policyIds": ["<role id>"], "emails": ["person@example.com"] }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The response has `invites[]` (each with `id`, `email`, `status`, `expirationDate`) and `failedEmails` / `failedInvites`. Report any that failed. Keep each `invites[].id`: it is the `inviteId` for Steps 4 and 5.
|
|
111
|
+
|
|
112
|
+
### 7. Remove the current user from the site ("remove me")
|
|
113
|
+
|
|
114
|
+
The APIs cannot tell who is talking to you, so you need the user's own `accountId` from them. Then:
|
|
115
|
+
|
|
116
|
+
1. Run Step 2. If their account is not in the contributors list, stop: the site owner is not listed as a collaborator, and an owner can leave only after transferring ownership to another user. Tell them that and do not call Remove Contributor.
|
|
117
|
+
2. Call Remove Contributor (Step 3) with their `accountId`. The user asked for this, so do not ask for confirmation, but do not soften it afterwards: removal cannot be undone.
|
|
118
|
+
3. On success, state clearly and in bold that they can no longer use this site's dashboard, and should close the tab or click the Wix logo at the top left to go to All Sites. For example: **You have been removed from this site. The dashboard will no longer work for you — close this tab or click the Wix logo at the top left to go to All Sites.**
|
|
119
|
+
|
|
120
|
+
## Reporting back
|
|
121
|
+
|
|
122
|
+
State what was done, to which account or email, and the outcome. Do not show raw IDs unless the user asks. Always say which of these happened:
|
|
123
|
+
|
|
124
|
+
- **Succeeded**, e.g. "The invite for james@bond.com has been canceled."
|
|
125
|
+
- **Failed**, e.g. "I couldn't resend the invite for james@bond.com. Please try again." If the call returns 403, say so; do not guess a cause.
|
|
126
|
+
- **Not done**, with the reason, e.g. "That account is not a collaborator on this site, so there was nothing to remove." or "That is the site owner's account, which cannot be removed without transferring ownership."
|
|
127
|
+
|
|
128
|
+
For resend, read `invite.status` in the response: if it is `Used`, the person already accepted and is now a collaborator, so say they already have access rather than that the invite was resent; `Declined`, `Expired` or `Deleted` mean the invite is no longer pending.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Forms Dashboard Navigation"
|
|
3
|
-
description: "Builds direct links to Wix Forms dashboard pages on manage.wix.com. The paths are not guessable and appear in no API reference, so take them from here: under `https://manage.wix.com/dashboard/{metaSiteId}/`, the forms list is `wix-forms`, a form's builder is `wix-forms/form/{formId}`, and that form's submissions are `wix-forms/form/{formId}/submissions` — there is no site-wide submissions page, and nothing lives under `contacts/forms`, `forms`, `form-builder` or `wix-forms-and-payments` (the legacy app). Also standalone forms, and
|
|
3
|
+
description: "Builds direct links to Wix Forms dashboard pages on manage.wix.com. The paths are not guessable and appear in no API reference, so take them from here: under `https://manage.wix.com/dashboard/{metaSiteId}/`, the forms list is `wix-forms`, a form's builder is `wix-forms/form/{formId}`, and that form's submissions are `wix-forms/form/{formId}/submissions` — there is no site-wide submissions page, and nothing lives under `contacts/forms`, `forms`, `form-builder` or `wix-forms-and-payments` (the legacy app). Also standalone forms, and the dashboard link for each Forms entity; reading forms and submissions is Read Forms and Submissions."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Forms Dashboard Navigation
|
|
@@ -33,6 +33,8 @@ Fetch the entity via REST, then link the matching dashboard page. All calls use
|
|
|
33
33
|
| Form | `GET /form-schema-service/v4/forms` · `POST /form-schema-service/v4/forms/query` · `GET /form-schema-service/v4/forms/{formId}` | `wix-forms/form/{formId}` (edit) or `wix-forms` (list) |
|
|
34
34
|
| Submission | `POST /form-submission-service/v4/submissions/namespace/query` (the filter must carry `"namespace": "wix.form_app.form"`) · `GET /form-submission-service/v4/submissions/{submissionId}` | `wix-forms/form/{formId}/submissions` — the `formId` comes off the submission |
|
|
35
35
|
|
|
36
|
+
For complete read requests — the namespace on each call, the submission fields you can filter and sort by, paging — see [Read Forms and Submissions](./read-forms-and-submissions.md).
|
|
37
|
+
|
|
36
38
|
Example — after creating a form, hand back its links:
|
|
37
39
|
|
|
38
40
|
```
|