@wix/agent-skills 1.18.2 → 1.19.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/package.json +1 -1
- package/skills/wix-app/SKILL.md +9 -9
- package/skills/wix-app/references/BACKEND_API.md +151 -152
- package/skills/wix-app/references/EXTENSION_REGISTRATION.md +12 -8
- package/skills/wix-manage/SKILL.md +1 -1
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +59 -33
- package/skills/wix-manage/references/bookings/bookings-staff-setup.md +45 -22
- package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +70 -12
- package/skills/wix-manage/references/calendar/configure-default-business-hours.md +53 -17
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +17 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +9 -8
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +9 -8
- package/skills/wix-vibe-headless/platforms/base44.md +11 -3
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +4 -0
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +5 -4
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +33 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Booking Service Policy Setup"
|
|
3
|
-
description: Sets up booking policies, cancellation rules, and waitlist configuration using the
|
|
3
|
+
description: Sets up booking policies, cancellation rules, and waitlist configuration using the Booking Policies API (query, then PATCH the bookingPolicy entity with its revision). Covers cancellationPolicy, reschedulePolicy, booking-notice limits, waitlistPolicy, and participants limits — e.g. "customers can cancel up to 24 hours before".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Technical Step-by-Step Instructions: Configuring Wix Bookings Service Policies (Real-World, API-First)
|
|
@@ -20,72 +20,98 @@ Wix Bookings policy configuration allows businesses to set rules for:
|
|
|
20
20
|
- **Waitlist policies**: When waitlists are enabled, capacity handling
|
|
21
21
|
- **Group booking policies**: Maximum participants per booking
|
|
22
22
|
|
|
23
|
-
Policies
|
|
23
|
+
Policies are **standalone entities** managed by the Booking Policies API (`/bookings/v1/booking-policies`), not fields nested on the service:
|
|
24
24
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
25
|
+
- Installing Wix Bookings creates a **"Default policy"** (`default: true`) that every new service references.
|
|
26
|
+
- Each service points at exactly one policy via its `bookingPolicy` field; many services can share a policy.
|
|
27
|
+
- To change rules site-wide, update the default policy. To give one service different rules, create a separate policy and reference it from that service.
|
|
27
28
|
|
|
28
29
|
### IMPORTANT NOTES
|
|
29
30
|
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Policy options
|
|
33
|
-
- All policy configurations support the same core features across service types
|
|
31
|
+
- A default policy exists on any site with Wix Bookings installed — **even before any service exists**. "Set a cancellation window" is always actionable by updating the default policy.
|
|
32
|
+
- Policy updates are PATCH-style: send only the sub-policies you want to change, plus the current `revision` (fetched via query/get) inside the `bookingPolicy` object.
|
|
33
|
+
- Policy options are the same across service types (APPOINTMENT, CLASS, COURSE).
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
37
|
## Steps
|
|
38
38
|
|
|
39
|
-
### 1.
|
|
39
|
+
### 1. Find the Policy to Change
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Query existing policies (`POST https://www.wixapis.com/bookings/v1/booking-policies/query`):
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
```json
|
|
44
|
+
{ "query": { "cursorPaging": { "limit": 100 } } }
|
|
45
|
+
```
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
For a site-wide change, pick the policy with `"default": true`. For a specific service, read the service first — its embedded `bookingPolicy.id` names the policy it uses. Save the policy's `id` and `revision`.
|
|
46
48
|
|
|
47
|
-
###
|
|
49
|
+
### 2. Update the Policy
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
`PATCH https://www.wixapis.com/bookings/v1/booking-policies/<POLICY_ID>` with the current `revision` inside the `bookingPolicy` object and only the sub-policies you're changing. Example — cancellations allowed up to 24 hours before the session:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"bookingPolicy": {
|
|
56
|
+
"id": "<POLICY_ID>",
|
|
57
|
+
"revision": "<CURRENT_REVISION>",
|
|
58
|
+
"cancellationPolicy": {
|
|
59
|
+
"enabled": true,
|
|
60
|
+
"limitLatestCancellation": true,
|
|
61
|
+
"latestCancellationInMinutes": 1440
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Field map (business rule → policy field):**
|
|
68
|
+
|
|
69
|
+
| Business rule | Sub-policy fields |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Cancellation deadline | `cancellationPolicy.{enabled, limitLatestCancellation, latestCancellationInMinutes}` |
|
|
72
|
+
| Reschedule deadline | `reschedulePolicy.{enabled, limitLatestReschedule, latestRescheduleInMinutes}` |
|
|
73
|
+
| How far ahead customers can book | `limitEarlyBookingPolicy.{enabled, earliestBookingInMinutes}` |
|
|
74
|
+
| Booking notice / last-minute cutoff | `limitLateBookingPolicy.{enabled, latestBookingInMinutes}` |
|
|
75
|
+
| Booking after session start (courses/classes) | `bookAfterStartPolicy.enabled` |
|
|
76
|
+
| Waitlist | `waitlistPolicy.{enabled, capacity, reservationTimeInMinutes}` |
|
|
77
|
+
| Participants per booking | `participantsPolicy.{enabled, maxParticipantsPerBooking}` |
|
|
78
|
+
|
|
79
|
+
### 3. Per-Service Policies (Optional)
|
|
80
|
+
|
|
81
|
+
To give one service different rules, create a new policy (`POST https://www.wixapis.com/bookings/v1/booking-policies`) and point the service at it by updating the service's `bookingPolicy` reference (see [Update Service](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service)).
|
|
50
82
|
|
|
51
83
|
### 4. Verify Policy Application
|
|
52
84
|
|
|
53
|
-
|
|
85
|
+
Read the service (`GET /bookings/v2/services/<SERVICE_ID>`) — the response embeds the full resolved `bookingPolicy`, so you can confirm the effective rules exactly as customers will experience them.
|
|
54
86
|
|
|
55
87
|
### IMPORTANT NOTES
|
|
56
88
|
|
|
57
|
-
- **
|
|
58
|
-
- **Partial updates**:
|
|
59
|
-
- **
|
|
60
|
-
- **
|
|
61
|
-
- **Time calculations**: Policy deadlines are calculated from booking start time in business timezone
|
|
62
|
-
- **Course flexibility**: Course services support additional policy options like `bookUntilXMinutesAfterStart`
|
|
89
|
+
- **Revision required**: Every policy update needs the current `revision` inside `bookingPolicy`; fetch it first, or the PATCH fails.
|
|
90
|
+
- **Partial updates**: Send only the sub-policies you're changing; the rest keep their values.
|
|
91
|
+
- **Enabled flags matter**: Each sub-policy has an `enabled` (and often a `limit*`) boolean — setting only the minutes value without enabling the limit has no effect.
|
|
92
|
+
- **Time calculations**: Policy deadlines are calculated from the booking's start time, in minutes (24 hours = 1440).
|
|
63
93
|
|
|
64
94
|
### Troubleshooting Common Issues
|
|
65
95
|
|
|
66
96
|
**Policies not applying:**
|
|
67
97
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
98
|
+
- Policies are separate entities — verify you PATCHed `/bookings/v1/booking-policies/<id>`, not fields on the service object (there is no `service.policy` field)
|
|
99
|
+
- Confirm the service actually references the policy you changed (`service.bookingPolicy.id`)
|
|
100
|
+
- Check the `revision` was current — a stale revision fails the update
|
|
71
101
|
|
|
72
102
|
**Waitlist not working:**
|
|
73
103
|
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
- Check that `waitingListPolicy.capacity` is set if you want limited waitlist size
|
|
104
|
+
- Verify `waitlistPolicy.enabled` is `true` and `waitlistPolicy.capacity` is set
|
|
105
|
+
- Confirm the service has capacity configured (`defaultCapacity` for CLASS/COURSE)
|
|
77
106
|
|
|
78
107
|
**Cancellation policies not enforced:**
|
|
79
108
|
|
|
80
|
-
-
|
|
81
|
-
- Verify `cancelationAllowed` is `true` if cancellations should be permitted
|
|
82
|
-
- Check that payment and booking flow supports the configured policy
|
|
109
|
+
- Set all three fields together: `cancellationPolicy.enabled: true`, `limitLatestCancellation: true`, and `latestCancellationInMinutes` — the minutes value alone has no effect without the booleans
|
|
83
110
|
|
|
84
111
|
**Group booking limits not working:**
|
|
85
112
|
|
|
86
|
-
- Confirm `
|
|
87
|
-
-
|
|
88
|
-
- Check that booking UI respects the participant limit
|
|
113
|
+
- Confirm `participantsPolicy.enabled` is `true` and `participantsPolicy.maxParticipantsPerBooking` is set
|
|
114
|
+
- Check that the booking UI respects the participant limit
|
|
89
115
|
|
|
90
116
|
## API Documentation References
|
|
91
117
|
|
|
@@ -68,7 +68,8 @@ The most common mistake is confusing which ID to use in which API call, leading
|
|
|
68
68
|
|
|
69
69
|
* **Two-Step Requirement**: Custom working hours requires both `assignWorkingHoursSchedule` AND creating `WORKING_HOURS` events. Only doing the first step results in staff with no actual working hours.
|
|
70
70
|
* **Foundation Dependencies**: Staff operations require Wix Bookings app installation and proper business schedule configuration. "Business schedule not found" errors indicate missing foundation setup.
|
|
71
|
-
* **
|
|
71
|
+
* **Bulk Request Envelope**: `bulkCreateEvents` requires each event to be wrapped in an `event` object — `{"events": [{"event": {...}}], "returnEntity": true}`. Sending a flat `{"events": [{...}]}` fails with 400 `event must not be empty`. Pass `returnEntity: true` to get the created events back; otherwise the response contains only `itemMetadata`.
|
|
72
|
+
* **Minimal Event Fields**: A `WORKING_HOURS` event needs only `type`, `scheduleId`, `start.localDate`, `end.localDate`, and (for recurring hours) `recurrenceRule`. The server derives `externalScheduleId` (set to the staff member's resource ID automatically), `adjustedStart`/`adjustedEnd`, and `appId`; `resources` may stay empty on a working-hours schedule.
|
|
72
73
|
* **Revision Numbers**: Event updates ALWAYS require the current revision number. Fetch current event details before any update operation.
|
|
73
74
|
* **Time Format Precision**: All date/time fields must use precise ISO 8601 format (`YYYY-MM-DDTHH:mm:ss`) without timezone indicators.
|
|
74
75
|
* **Separate Events for Each Day**: Each working day requires a separate event with single-day recurrence rules. You cannot specify multiple days in one event's `recurrenceRule.days` array.
|
|
@@ -113,9 +114,7 @@ Before creating staff members, ensure the foundation is properly configured:
|
|
|
113
114
|
|
|
114
115
|
**Install Wix Bookings App** (if needed): Use the App Installer API with Wix Bookings app ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`.
|
|
115
116
|
|
|
116
|
-
**Configure Business Schedule**:
|
|
117
|
-
|
|
118
|
-
**Create Calendar Schedule and Working Hours**: Create a calendar schedule for Wix Bookings integration and populate it with business `WORKING_HOURS` events.
|
|
117
|
+
**Configure Business Schedule**: Default business hours live as `WORKING_HOURS` calendar events on the business schedule — set them up per the [Configure Default Business Hours](../calendar/configure-default-business-hours.md) recipe. Do **not** use the Site Properties API for this: its business-schedule fields are separate general site info and do not drive Bookings availability.
|
|
119
118
|
|
|
120
119
|
### 2. Verify Current Business Hours (CRITICAL)
|
|
121
120
|
|
|
@@ -156,11 +155,10 @@ Create staff members using the Staff API (`POST https://www.wixapis.com/bookings
|
|
|
156
155
|
|
|
157
156
|
**⚠️ INHERITANCE MOMENT**: The moment this API call completes, the staff member inherits the current business hours. There's no "undo" for this inheritance.
|
|
158
157
|
|
|
159
|
-
**Save Critical IDs
|
|
160
|
-
- `staffMember.id` for updates and schedule assignment
|
|
161
|
-
- `staffMember.resourceId` for services and event resources
|
|
162
|
-
- `staffMember.resource.eventsSchedule.id` for working hours events
|
|
163
|
-
- `staffMember.resource.usesDefaultWorkingHours` (should be `true` initially)
|
|
158
|
+
**Save Critical IDs**:
|
|
159
|
+
- `staffMember.id` (in the create response) for updates and schedule assignment
|
|
160
|
+
- `staffMember.resourceId` (in the create response) for services and event resources
|
|
161
|
+
- `staffMember.resource.eventsSchedule.id` for working hours events — **NOT in the create response**. The create response contains only id/name/resourceId; fetch the staff member again with `?fields=RESOURCE_DETAILS` to get `resource.eventsSchedule.id` (and `resource.usesDefaultWorkingHours`, initially `true`). Reading `resource.eventsSchedule.id` off the create response yields `undefined` and downstream `scheduleId must not be empty` errors.
|
|
164
162
|
|
|
165
163
|
### 5. Set Up Custom Working Hours (Two-Step Process)
|
|
166
164
|
|
|
@@ -168,21 +166,44 @@ Create staff members using the Staff API (`POST https://www.wixapis.com/bookings
|
|
|
168
166
|
|
|
169
167
|
**Step 5A: Assign Custom Working Hours Schedule**
|
|
170
168
|
|
|
171
|
-
Get staff member details (`GET https://www.wixapis.com/bookings/v1/staff-members/<STAFF_MEMBER_ID>?fields=RESOURCE_DETAILS`) to extract the events schedule ID.
|
|
169
|
+
Get staff member details (`GET https://www.wixapis.com/bookings/v1/staff-members/<STAFF_MEMBER_ID>?fields=RESOURCE_DETAILS`) to extract the events schedule ID. Then call `assignWorkingHoursSchedule` (`POST https://www.wixapis.com/bookings/v1/staff-members/<STAFF_MEMBER_ID>/assign-working-hours-schedule`):
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{ "scheduleId": "<EVENTS_SCHEDULE_ID>" }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The request field is `scheduleId` (other names, e.g. `eventsScheduleId`, fail with 400 `scheduleId must not be empty`). This detaches the staff member from business default hours.
|
|
172
176
|
|
|
173
177
|
Verify the response shows `"usesDefaultWorkingHours": false`.
|
|
174
178
|
|
|
179
|
+
> **On failure, resume — don't restart.** If this call (or a later step) fails, the staff member from Step 4 already exists. Fix the failing call and continue with the same staff member ID; re-running the whole flow creates a duplicate staff member.
|
|
180
|
+
|
|
175
181
|
**Step 5B: Create WORKING_HOURS Events**
|
|
176
182
|
|
|
177
|
-
Use the Events API (`POST https://www.wixapis.com/calendar/v3/bulk/events/create`) to create
|
|
178
|
-
- `scheduleId`: Staff member's events schedule ID
|
|
179
|
-
- `externalScheduleId`: Staff member's resource ID
|
|
180
|
-
- `type`: `"WORKING_HOURS"`
|
|
181
|
-
- `resources` array: Staff member's resource ID
|
|
182
|
-
- `appId`: Wix Bookings app ID
|
|
183
|
-
- Proper recurrence rules with single-day specification
|
|
183
|
+
Use the Events API (`POST https://www.wixapis.com/calendar/v3/bulk/events/create`) to create one recurring event per working day. Note the request envelope: each event is wrapped in an `event` object.
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"events": [
|
|
188
|
+
{
|
|
189
|
+
"event": {
|
|
190
|
+
"type": "WORKING_HOURS",
|
|
191
|
+
"scheduleId": "<STAFF_EVENTS_SCHEDULE_ID>",
|
|
192
|
+
"start": { "localDate": "2026-09-07T09:00:00" },
|
|
193
|
+
"end": { "localDate": "2026-09-07T15:00:00" },
|
|
194
|
+
"recurrenceRule": { "frequency": "WEEKLY", "interval": 1, "days": ["MONDAY"] }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"returnEntity": true
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- `scheduleId` is the staff member's **events schedule ID** (`resource.eventsSchedule.id`).
|
|
203
|
+
- `externalScheduleId`, `adjustedStart`/`adjustedEnd`, and `appId` are derived by the server — you do not need to send them (`externalScheduleId` comes back set to the staff member's resource ID).
|
|
204
|
+
- `recurrenceRule.frequency` must be `WEEKLY` (the only supported value); `interval` is 1–4.
|
|
205
|
+
- `recurrenceRule.days` takes exactly one **full uppercase** day name from `MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY` — abbreviations like `MON` fail validation. One day per event, so create a separate event for each working day.
|
|
206
|
+
- `start`/`end` must be today or in the future for recurring events.
|
|
186
207
|
|
|
187
208
|
### 6. Verify Setup
|
|
188
209
|
|
|
@@ -193,10 +214,9 @@ Query the staff member to confirm:
|
|
|
193
214
|
|
|
194
215
|
### IMPORTANT NOTES
|
|
195
216
|
|
|
196
|
-
* **ID Relationship Critical**: Use staff member ID for assignment
|
|
217
|
+
* **ID Relationship Critical**: Use the staff member ID for assignment and the events schedule ID for event `scheduleId`; the resource ID appears in server-derived fields (`externalScheduleId`) and in `resources` arrays when attaching this staff member to CLASS/COURSE session events
|
|
197
218
|
* **Foundation First**: Complete foundation setup before staff operations to avoid "Business schedule not found" errors
|
|
198
219
|
* **Complete Two-Step Process**: Both schedule assignment AND event creation are mandatory for custom working hours
|
|
199
|
-
* **Event Field Requirements**: Include all required fields even if they appear optional in basic documentation
|
|
200
220
|
* **Revision Management**: Always fetch current revision numbers before updating events
|
|
201
221
|
* **Date Format Strict**: Use precise ISO 8601 format without timezone indicators
|
|
202
222
|
* **Inheritance is Permanent**: Once inherited, business hours changes don't affect existing staff
|
|
@@ -218,7 +238,10 @@ Completed assignment but missing event creation. Create `WORKING_HOURS` events u
|
|
|
218
238
|
- **Solution**: Standardize by configuring custom hours for all staff, or recreate staff after fixing business hours
|
|
219
239
|
|
|
220
240
|
**"Invalid scheduleId" or "Resource not found" Errors**:
|
|
221
|
-
Using wrong ID type in API calls. Verify you're using events schedule ID for `scheduleId
|
|
241
|
+
Using wrong ID type in API calls. Verify you're using the events schedule ID for `scheduleId` and the staff member ID for updates.
|
|
242
|
+
|
|
243
|
+
**400 "event must not be empty" on bulkCreateEvents**:
|
|
244
|
+
The request body is missing the per-event wrapper. Each entry in `events` must be `{"event": {...}}`, not the event fields directly.
|
|
222
245
|
|
|
223
246
|
**Event Update Fails with Revision Error**:
|
|
224
247
|
Get current event details first and include the revision number in update requests.
|
|
@@ -227,7 +250,7 @@ Get current event details first and include the revision number in update reques
|
|
|
227
250
|
Use current or future dates for recurring event start dates.
|
|
228
251
|
|
|
229
252
|
**Events Not Linked to Staff Member**:
|
|
230
|
-
|
|
253
|
+
Verify the event was created on the staff member's own events schedule (`resource.eventsSchedule.id`) — the schedule is what links working-hours events to the staff member. The returned event's `externalScheduleId` should equal the staff member's resource ID (server-derived).
|
|
231
254
|
|
|
232
255
|
### Working with Existing Staff
|
|
233
256
|
|
|
@@ -18,8 +18,9 @@ Below are the recommended steps to successfully create Wix Bookings services tha
|
|
|
18
18
|
Before creating multi-resource services, ensure the following requirements are met:
|
|
19
19
|
|
|
20
20
|
1. **Wix Bookings** - Core app must be installed and configured
|
|
21
|
-
2. **
|
|
22
|
-
|
|
21
|
+
2. **Business Location** - At least one business location must be configured
|
|
22
|
+
|
|
23
|
+
> Resource type, resource, and resource-bound service creation succeed via the API without any premium-related error. If a plan-gating error does occur, it surfaces explicitly (e.g. a 403) — don't preemptively block on plan checks.
|
|
23
24
|
|
|
24
25
|
### App Installation Process
|
|
25
26
|
|
|
@@ -112,6 +113,12 @@ Before creating anything, plan your resource type structure. Each type should re
|
|
|
112
113
|
|
|
113
114
|
Create resource types using `createResourceType` API (`POST https://www.wixapis.com/bookings/v2/resources/resource-types`) ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/resources/resource-types-v2/create-resource-type)):
|
|
114
115
|
|
|
116
|
+
```json
|
|
117
|
+
{ "resourceType": { "name": "Treatment Room" } }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The response returns `resourceType.id` — save it for resource creation and the service's `serviceResources`.
|
|
121
|
+
|
|
115
122
|
**Key Requirements:**
|
|
116
123
|
- `name` must be unique across the site
|
|
117
124
|
- Keep `name` descriptive but concise (appears in booking interface)
|
|
@@ -121,9 +128,23 @@ Create resource types using `createResourceType` API (`POST https://www.wixapis.
|
|
|
121
128
|
|
|
122
129
|
### 3. Create Individual Resources
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
Create the resource instances of each type. For more than one (the usual case — e.g. Room A and Room B), use `bulkCreateResources` (`POST https://www.wixapis.com/bookings/v2/bulk/resources/create`) ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/resources/resources-v2/bulk-create-resources)); for a single one, `createResource` (`POST https://www.wixapis.com/bookings/v2/resources`) takes `{ "resource": { "name": ..., "typeId": ... } }`.
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"resources": [
|
|
136
|
+
{ "name": "Room A", "typeId": "<RESOURCE_TYPE_ID>" },
|
|
137
|
+
{ "name": "Room B", "typeId": "<RESOURCE_TYPE_ID>" }
|
|
138
|
+
],
|
|
139
|
+
"returnEntity": true
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Read each created resource's ID from `results[i].item.id` (with `returnEntity: true`) or `results[i].itemMetadata.id` (without it). **The resource is directly under `item` — there is no `item.resource.id`** (reading it throws `Cannot read properties of undefined`). Match items to your request by `itemMetadata.originalIndex`, and check `bulkActionMetadata.totalFailures` before proceeding.
|
|
125
144
|
|
|
126
|
-
|
|
145
|
+
**⚠️ Payload shape**: the type reference is the flat `typeId` field (same on single and bulk). Sending a nested object (`"type": {"id": ...}`) fails with 400 `Unexpected value for StringValue`. A resource without `typeId` is created but is not bookable.
|
|
146
|
+
|
|
147
|
+
If you omit `locationOptions`, the resource defaults to `availableInAllLocations: true` — the simplest and usually correct configuration; specific location setup is complex and often unnecessary.
|
|
127
148
|
|
|
128
149
|
**Advanced Configuration (Gap):**
|
|
129
150
|
- Custom working hours override business location hours (this behavior isn't clearly documented)
|
|
@@ -133,17 +154,42 @@ For each resource type, create the individual resource instances using `createRe
|
|
|
133
154
|
|
|
134
155
|
### 4. Create Multi-Resource Service (Optional Connection)
|
|
135
156
|
|
|
136
|
-
Create the service that optionally connects to multiple resource types using `bulkCreateServices` API ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services))
|
|
157
|
+
Create the service that optionally connects to multiple resource types using `bulkCreateServices` API (`POST https://www.wixapis.com/bookings/v2/bulk/services/create`) ([REST](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services)). Note the endpoint path is `/bulk/services/create` (not `/services/bulk/create`, which 404s).
|
|
158
|
+
|
|
159
|
+
**Pick the service type, and mind the resource-specific required fields:**
|
|
160
|
+
|
|
161
|
+
- A **1-on-1, time-slot** service (e.g. a massage, a room rental by the hour) is an `APPOINTMENT`. When such a service is driven by a **resource instead of a staff member**, `primaryResourceType` (a flat resource-type GUID) is **required** — omitting it fails with 400 `primary_resource_type is required for appointment services without staff members`. APPOINTMENT also needs `schedule.availabilityConstraints.sessionDurations`.
|
|
162
|
+
- A **group** service (fixed capacity per session) is a `CLASS` (drop-in) or `COURSE` (whole series); these use `defaultCapacity` and do not require `primaryResourceType`.
|
|
163
|
+
|
|
164
|
+
Appointment example (one room per booking, no staff):
|
|
137
165
|
|
|
138
|
-
**Service Resource Configuration:**
|
|
139
166
|
```json
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
167
|
+
{
|
|
168
|
+
"services": [{
|
|
169
|
+
"name": "Massage",
|
|
170
|
+
"type": "APPOINTMENT",
|
|
171
|
+
"onlineBooking": { "enabled": true },
|
|
172
|
+
"serviceResources": [
|
|
173
|
+
{ "resourceType": { "id": "<ROOM_TYPE_ID>" } }
|
|
174
|
+
],
|
|
175
|
+
"primaryResourceType": "<ROOM_TYPE_ID>",
|
|
176
|
+
"schedule": { "availabilityConstraints": { "sessionDurations": [60] } },
|
|
177
|
+
"payment": {
|
|
178
|
+
"rateType": "FIXED",
|
|
179
|
+
"options": { "online": true, "inPerson": false },
|
|
180
|
+
"fixed": { "price": { "value": "80" } }
|
|
181
|
+
}
|
|
182
|
+
}],
|
|
183
|
+
"returnEntity": true
|
|
184
|
+
}
|
|
145
185
|
```
|
|
146
186
|
|
|
187
|
+
For a group service, use `"type": "CLASS"` with `"defaultCapacity": <n>` instead of `primaryResourceType`/`sessionDurations`. Both types take `payment.options` (at least one of `online`/`inPerson` true) — required even for the resource-bound case.
|
|
188
|
+
|
|
189
|
+
Save the service ID from the response: `results[0].item.id` (with `returnEntity: true`), or `results[0].itemMetadata.id` (without it). **There is no `results[0].item.service.id`** — reading that path throws `Cannot read properties of undefined`.
|
|
190
|
+
|
|
191
|
+
**⚠️ Verify from the response, not from assumptions**: without `returnEntity: true` the bulk response contains only `results[0].itemMetadata` (id + success flag) — there is no `item`. With the flag, the created service is at `results[0].item` (e.g. `item.id`, `item.serviceResources`). Check `bulkActionMetadata.totalFailures` and each `itemMetadata.success` before reporting the service as created.
|
|
192
|
+
|
|
147
193
|
**Key Principle**: This creates a **loose connection** where the service requests resource allocation during booking, but resources remain independent entities with their own lifecycle and management.
|
|
148
194
|
|
|
149
195
|
**Pricing Strategy**: Multi-resource services typically command premium pricing due to coordination complexity.
|
|
@@ -171,6 +217,18 @@ The docs don't explain how multi-resource allocation actually works during booki
|
|
|
171
217
|
- Check that `typeId` exactly matches the resource type `id`
|
|
172
218
|
- Ensure you're not using resource type `name` when `id` is required
|
|
173
219
|
|
|
220
|
+
**400 "Unexpected value for StringValue" on createResource or on service `primaryResourceType`:**
|
|
221
|
+
- A resource-type reference was sent as a nested object where a flat GUID string is expected. `createResource` uses `"typeId": "<guid>"`; the service field is `"primaryResourceType": "<guid>"` (both flat, not `{"id": ...}`). Note this differs from `serviceResources[].resourceType.id`, which *is* nested.
|
|
222
|
+
|
|
223
|
+
**400 "primary_resource_type is required for appointment services without staff members":**
|
|
224
|
+
- An `APPOINTMENT` service bound to a resource (no `staffMemberIds`) needs `primaryResourceType` set to the driving resource-type GUID. Either add it, or model the service as a `CLASS`/`COURSE` if a group service fits.
|
|
225
|
+
|
|
226
|
+
**404 on bulk creation:**
|
|
227
|
+
- The path segments are `bulk/<entity>/create`: `POST /bookings/v2/bulk/services/create`, `POST /bookings/v2/bulk/resources/create`. `/bookings/v2/services/bulk/create` (and the resources equivalent) do not exist.
|
|
228
|
+
|
|
229
|
+
**`Cannot read properties of undefined` after a bulk create (resources or services):**
|
|
230
|
+
- Every bulk response nests the entity directly under `results[i].item` — use `item.id`, never `item.resource.id` or `item.service.id`. Without `returnEntity: true` there is no `item` at all, only `itemMetadata.id`.
|
|
231
|
+
|
|
174
232
|
**"Resource type name already exists" Error (409):**
|
|
175
233
|
- Resource type names must be unique across the site
|
|
176
234
|
- Query existing resource types to avoid duplicates
|
|
@@ -211,7 +269,7 @@ The docs don't explain how multi-resource allocation actually works during booki
|
|
|
211
269
|
- Consider how names appear in booking confirmations and staff interfaces
|
|
212
270
|
|
|
213
271
|
**Availability Strategy:**
|
|
214
|
-
-
|
|
272
|
+
- Don't add `workingHoursSchedules` to non-staff resources unless business rules require it — without them the resource simply follows business location hours, which is usually what you want
|
|
215
273
|
- Use working hours sparingly - they add complexity without always adding value
|
|
216
274
|
- Test availability scenarios thoroughly before going live
|
|
217
275
|
|
|
@@ -26,7 +26,7 @@ Wix Bookings default business hours define the base availability for your bookin
|
|
|
26
26
|
|
|
27
27
|
### 🚨 CRITICAL: Default Hours Upon Installation
|
|
28
28
|
|
|
29
|
-
**IMPORTANT**: When Wix Bookings is first installed on a site, it automatically creates DEFAULT business hours
|
|
29
|
+
**IMPORTANT**: When Wix Bookings is first installed on a site, it automatically creates DEFAULT business hours — one recurring event per default working day. The exact days and times vary by site and template: a bare install creates Monday–Friday 10 AM–6 PM (per [About Business Schedules](https://dev.wix.com/docs/api-reference/business-management/calendar/about-business-schedules)), but template-created sites can differ (e.g. include Saturday). You CANNOT simply create new hours without handling these existing default hours first.
|
|
30
30
|
|
|
31
31
|
**You MUST either:**
|
|
32
32
|
1. **Update the existing default hours** to your desired schedule, OR
|
|
@@ -49,9 +49,9 @@ Wix Bookings default business hours define the base availability for your bookin
|
|
|
49
49
|
|
|
50
50
|
### Key Discovery: Universal Business Schedule External ID
|
|
51
51
|
|
|
52
|
-
**VERIFIED**: The business schedule external ID `"4e0579a5-491e-4e70-a872-d097eed6e520"` is **universal across all Wix sites
|
|
52
|
+
**VERIFIED**: The business schedule external ID `"4e0579a5-491e-4e70-a872-d097eed6e520"` is **universal across all Wix sites** — documented in [About Business Schedules](https://dev.wix.com/docs/api-reference/business-management/calendar/about-business-schedules) ("The business schedule always uses the `externalId` value `4e0579a5-491e-4e70-a872-d097eed6e520`").
|
|
53
53
|
|
|
54
|
-
This has been tested and confirmed on multiple different Wix sites:
|
|
54
|
+
This has also been tested and confirmed on multiple different Wix sites:
|
|
55
55
|
- All sites have a business schedule with this exact external ID
|
|
56
56
|
- The schedule name is consistently `"business"`
|
|
57
57
|
- While the internal schedule `id` varies per site, the `externalId` is constant
|
|
@@ -63,7 +63,8 @@ This has been tested and confirmed on multiple different Wix sites:
|
|
|
63
63
|
* **Default Hours Always Exist**: Every Wix Bookings installation creates default hours automatically
|
|
64
64
|
* **Event Scheduling Flexibility**: Businesses can create multiple time slots per day or complex schedules as needed - there are no restrictions on number of events per day
|
|
65
65
|
* **MASTER vs INSTANCE Events**: Based on observed behavior, MASTER events appear to generate INSTANCE events automatically, but always verify current event state when working with recurring events
|
|
66
|
-
* **Query Patterns**: Use `"recurrenceType": ["MASTER"]` to focus on the primary recurring event definitions
|
|
66
|
+
* **Query Patterns**: Use `"recurrenceType": ["MASTER"]` to focus on the primary recurring event definitions. ⚠️ It is a **top-level** request field, a sibling of `query` — placing it inside `query.filter` is **silently ignored** (the call succeeds and returns INSTANCE events), so a wrong placement produces confusing results rather than an error
|
|
67
|
+
* **The universal external ID is a lookup key, not a schedule ID**: use `4e0579a5-491e-4e70-a872-d097eed6e520` only in the `externalId` filter of `querySchedules`. Passing it as an event's `scheduleId` fails with 404 `Schedule with 4e0579a5-... ID not found` (and as a `resources[].id`, with a similar `Resource ... not found`) — events take the schedule's real `id` returned by that query
|
|
67
68
|
* **Revision Numbers**: Calendar events require current revision numbers for updates - always get fresh revision before bulk operations
|
|
68
69
|
|
|
69
70
|
---
|
|
@@ -104,7 +105,27 @@ Query pattern:
|
|
|
104
105
|
|
|
105
106
|
**Important**: Always query for MASTER events specifically to see actual recurring schedules.
|
|
106
107
|
|
|
107
|
-
**Expected Result**:
|
|
108
|
+
**Expected Result**: One MASTER event per default working day. Don't assume which days: a bare Bookings install has Monday–Friday, but template-created sites can carry a different set (e.g. Monday–Saturday), and times vary by site — this query is what tells you what's actually there. The response fields this flow reads (trimmed — real responses carry more):
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"events": [
|
|
113
|
+
{
|
|
114
|
+
"id": "9f1e2d3c4b5a69788766554433221100aabbccddeeff00112233445566778899",
|
|
115
|
+
"scheduleId": "f3b9c2d1-7a4e-4b8c-9d2f-6e1a5c8b0d47",
|
|
116
|
+
"type": "WORKING_HOURS",
|
|
117
|
+
"recurrenceType": "MASTER",
|
|
118
|
+
"recurrenceRule": { "frequency": "WEEKLY", "interval": 1, "days": ["MONDAY"] },
|
|
119
|
+
"start": { "localDate": "2026-08-31T10:00:00", "timeZone": "America/New_York" },
|
|
120
|
+
"end": { "localDate": "2026-08-31T18:00:00", "timeZone": "America/New_York" },
|
|
121
|
+
"revision": "1"
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- Update and cancel calls target `events[].id`; updates also need that event's current `revision`.
|
|
128
|
+
- `recurrenceRule.days` tells you which weekday each event covers; `start`/`end` `localDate` carry the current hours in the schedule's `timeZone`.
|
|
108
129
|
|
|
109
130
|
### 3. Choose Your Strategy: Update OR Replace
|
|
110
131
|
|
|
@@ -127,14 +148,14 @@ Update fields:
|
|
|
127
148
|
- `revision`: Current revision number (from Step 2 query)
|
|
128
149
|
- `fieldmask`: `"start,end"`
|
|
129
150
|
|
|
130
|
-
**Example**: Change Monday hours
|
|
151
|
+
**Example**: Change Monday hours to 8 AM-4 PM (use a Monday that is today or in the future — a past `start` is rejected for recurring events):
|
|
131
152
|
```json
|
|
132
153
|
{
|
|
133
154
|
"events": [{
|
|
134
155
|
"event": {
|
|
135
156
|
"id": "existing-monday-event-id",
|
|
136
|
-
"start": {"localDate": "
|
|
137
|
-
"end": {"localDate": "
|
|
157
|
+
"start": {"localDate": "2027-03-01T08:00:00"},
|
|
158
|
+
"end": {"localDate": "2027-03-01T16:00:00"},
|
|
138
159
|
"revision": "current-revision-number"
|
|
139
160
|
}
|
|
140
161
|
}],
|
|
@@ -145,6 +166,9 @@ Update fields:
|
|
|
145
166
|
### 4B. Replace All Business Hours (Strategy B)
|
|
146
167
|
|
|
147
168
|
#### Step 4B.1: Delete Existing Hours
|
|
169
|
+
|
|
170
|
+
Cancelling is irreversible — a cancelled event can only be replaced by creating a new one. When the user names their complete desired schedule (e.g. "Monday through Friday, 8-4"), replacing all existing hours — including days outside that set — is part of the request. If it's ambiguous whether hours on other days should be kept, ask the user instead of assuming.
|
|
171
|
+
|
|
148
172
|
Cancel existing MASTER events using `bulkCancelEvents` API (`POST https://www.wixapis.com/calendar/v3/bulk/events/cancel`) ([REST](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-cancel-event)):
|
|
149
173
|
|
|
150
174
|
```json
|
|
@@ -154,17 +178,28 @@ Cancel existing MASTER events using `bulkCancelEvents` API (`POST https://www.wi
|
|
|
154
178
|
```
|
|
155
179
|
|
|
156
180
|
#### Step 4B.2: Create New Business Hours
|
|
157
|
-
Create `WORKING_HOURS` events for each day using `bulkCreateEvents` API (`POST https://www.wixapis.com/calendar/v3/bulk/events/create`) ([REST](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event)).
|
|
181
|
+
Create `WORKING_HOURS` events for each day using `bulkCreateEvents` API (`POST https://www.wixapis.com/calendar/v3/bulk/events/create`) ([REST](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event)). Note the request envelope: each event is wrapped in an `event` object — a flat event fails with 400 `event must not be empty`.
|
|
158
182
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"events": [
|
|
186
|
+
{
|
|
187
|
+
"event": {
|
|
188
|
+
"type": "WORKING_HOURS",
|
|
189
|
+
"scheduleId": "<BUSINESS_SCHEDULE_ID_FROM_STEP_1>",
|
|
190
|
+
"start": { "localDate": "2027-03-01T08:00:00" },
|
|
191
|
+
"end": { "localDate": "2027-03-01T16:00:00" },
|
|
192
|
+
"recurrenceRule": { "frequency": "WEEKLY", "interval": 1, "days": ["MONDAY"] }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
```
|
|
166
198
|
|
|
167
|
-
|
|
199
|
+
- `scheduleId` is the business schedule's real `id` from Step 1 — **not** the universal external ID (that constant is only the `querySchedules` lookup key; used here it 404s).
|
|
200
|
+
- `scheduleOwnerId`/`externalScheduleId` are derived by the server; you do not need to send them.
|
|
201
|
+
- `recurrenceRule.days` takes exactly one full uppercase day name (`MONDAY`…`SUNDAY`); create a separate event per weekday, with `start`/`end` today or in the future.
|
|
202
|
+
- Check each `results[i].itemMetadata.success` (and `bulkActionMetadata.totalFailures`) before reporting the hours as set.
|
|
168
203
|
|
|
169
204
|
### 5. Verify Final Configuration
|
|
170
205
|
|
|
@@ -218,6 +253,7 @@ Query the business schedule events again to confirm:
|
|
|
218
253
|
|
|
219
254
|
## API Documentation References
|
|
220
255
|
|
|
256
|
+
* [About Business Schedules](https://dev.wix.com/docs/api-reference/business-management/calendar/about-business-schedules)
|
|
221
257
|
* [Query Schedules](https://dev.wix.com/docs/api-reference/business-management/calendar/schedules-v3/query-schedules)
|
|
222
258
|
* [Query Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/query-events)
|
|
223
259
|
* [Bulk Create Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event)
|
|
@@ -83,9 +83,22 @@ If any product is missing a price, **do not call the API**. Ask for the missing
|
|
|
83
83
|
|
|
84
84
|
## Build each product
|
|
85
85
|
|
|
86
|
+
> [!WARNING]
|
|
87
|
+
> **Hard requirement before every create call:** If `productType` is `"PHYSICAL"`, the request MUST include `physicalProperties` on the product and on every variant:
|
|
88
|
+
>
|
|
89
|
+
> ```json
|
|
90
|
+
> {
|
|
91
|
+
> "productType": "PHYSICAL",
|
|
92
|
+
> "physicalProperties": {},
|
|
93
|
+
> "variantsInfo": {"variants": [{"physicalProperties": {}}]}
|
|
94
|
+
> }
|
|
95
|
+
> ```
|
|
96
|
+
>
|
|
97
|
+
> Put supplied physical fields such as weight or dimensions inside those objects; use `{}` when none were supplied. Never invent them, and never execute or retry a physical-product request when either object is absent.
|
|
98
|
+
|
|
86
99
|
| Concern | Rule |
|
|
87
100
|
|---|---|
|
|
88
|
-
| Type | `PHYSICAL`
|
|
101
|
+
| Type | `PHYSICAL` requires both `productType: "PHYSICAL"` and product-level `physicalProperties`, plus both `productType: "PHYSICAL"` and variant-level `physicalProperties` on every variant. `DIGITAL` omits physical properties and carries `inventoryItem.inStock` plus `digitalProperties.digitalFile` on each variant. |
|
|
89
102
|
| Variants | Include at least one. Price, SKU, barcode, inventory, and digital file are variant-level fields. |
|
|
90
103
|
| Price | Use a string in `price.actualPrice.amount`; add `compareAtPrice` only when supplied. |
|
|
91
104
|
| SKU | Preserve supplied strings exactly, including `#`, punctuation, and leading zeroes. Keep variant SKUs unique unless explicitly requested otherwise. |
|
|
@@ -221,6 +234,8 @@ The first is for single endpoints; the second is for bulk endpoints. If the user
|
|
|
221
234
|
|
|
222
235
|
For one product when the user supplied no quantity, stock state, or inventory-tracking request, the complete direct path is `POST /stores/v3/products` with `{"product": PRODUCT}`. Do not infer `inStock: true`, add `inventoryItem`, or choose `/products-with-inventory`; physical product type does not imply inventory. If it has ready images, add `"fields": ["MEDIA_ITEMS_INFO"]` to the same no-inventory request.
|
|
223
236
|
|
|
237
|
+
For a physical product on either create endpoint, never send `productType: "PHYSICAL"` by itself. Include `physicalProperties: {}` on the product and `physicalProperties: {}` on every physical variant (or populate those objects with the supplied physical dimensions/weight). The API validates these as aligned one-of pairs and returns 400 if either corresponding field is missing.
|
|
238
|
+
|
|
224
239
|
For one physical product with inventory, the complete direct path is one `POST /stores/v3/products-with-inventory` call with `{"product": PRODUCT}`. Put `inventoryItem` on its priced variant. If it has ready images, add `"fields": ["MEDIA_ITEMS_INFO"]` to that same request. The product shape, envelope, endpoint, and validation paths are complete here: do not search another recipe or schema, probe an alternate endpoint, or make a post-create read unless the projected create response does not prove requested media.
|
|
225
240
|
|
|
226
241
|
### Request projected media when validating images
|
|
@@ -300,4 +315,5 @@ Retry only failed transient items, not successful products. If a requested field
|
|
|
300
315
|
- `variantsInfo must not be empty`: include at least one priced variant per product.
|
|
301
316
|
- Option/variant mismatch: create every requested combination and reference every option once per variant.
|
|
302
317
|
- Media not visible: use the uploaded `wixstatic.com` URL in `media.itemsInfo.items`; do not set `media.main`.
|
|
318
|
+
- `productType` alignment 400 (`product is invalid: productType and the corresponding physical_properties field must be passed together`): pair `productType: "PHYSICAL"` with `physicalProperties` on the product and on every physical variant. The API validates these as aligned one-of pairs, so do not retry with only one level populated. Pair `productType: "DIGITAL"` with the digital variant fields instead.
|
|
303
319
|
- Digital product rejected at add-to-cart: `ITEM_NOT_FOUND_IN_CATALOG` means the variant has no `digitalProperties.digitalFile`; `exceeds available inventory` means it has no `inventoryItem.inStock`. Both read back as a healthy product.
|
|
@@ -11,7 +11,8 @@ or configuration changes are needed.
|
|
|
11
11
|
**Banner disabled for this entry flow:** do not add `<WixManageBanner/>`; skip the shared
|
|
12
12
|
storefront instructions' optional banner integration.
|
|
13
13
|
|
|
14
|
-
Follow STEPs 1–4 below exactly
|
|
14
|
+
Follow STEPs 1–4 below exactly. Fire product image generations first, then build the client
|
|
15
|
+
(STEP 2), and seed (STEP 3) **after** the client is built — generation finishes while you build.
|
|
15
16
|
|
|
16
17
|
## STEP 1 — Install the Wix skills and deploy the storefront vertical to the app
|
|
17
18
|
|
|
@@ -89,13 +90,13 @@ Inline via exec_tool, `base44` is already declared — use it directly; do **not
|
|
|
89
90
|
`@base44/sdk`, re-declare it, or call `createClient()` (that's for standalone `.js` files only;
|
|
90
91
|
inline it throws *"Identifier 'base44' has already been declared."*).
|
|
91
92
|
|
|
92
|
-
**Product images.**
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
from the
|
|
97
|
-
call
|
|
98
|
-
|
|
93
|
+
**Product images.** Fire every `generate_image` **before you build the client**, and seed **after**
|
|
94
|
+
it — generation finishes while you build, so by the time you write the seed call your images are
|
|
95
|
+
ready: each finished result now reads `status: "completed"` with its final
|
|
96
|
+
`https://media.base44.com/...` url. Read every `imageUrl` from the results **as they read at that
|
|
97
|
+
moment** — not from what they said when you called the tool — and pass them in the single
|
|
98
|
+
`setupStore` call. A result without a final url by then (still running, or failed) → seed that
|
|
99
|
+
product **without** `imageUrl` and attach it afterwards with `attachProductImages`.
|
|
99
100
|
|
|
100
101
|
## STEP 4 — Wrap up
|
|
101
102
|
|