← Files WixARCHIVED FILE
skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md
4.23 KB · Oct 8, 2026 · 12:02 UTC
# Bookings Staff Sorting Provider Service Plugin Reference
## Overview
The Staff Sorting Provider SPI lets you implement custom staff assignment algorithms for Wix Bookings. When a booking slot has multiple available staff members, Wix calls your plugin to determine the priority order. Implement the `sortStaffMembers` handler — it returns the available staff members reordered by priority.
**FQDN**: `wix.interfaces.resources.sorting.v1.staff_sorting_provider`
## Request and Response Schema
Before implementing, call `ReadFullDocsMethodSchema` on the docs URL to get the full request/response types.
| Handler | Docs URL |
| --- | --- |
| `sortStaffMembers` | https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-sorting-service-plugin/sort-staff-members?apiView=SDK |
**Important constraints:**
- You must return the **exact same IDs** from `availableResourceIds`, reordered by priority
- Do not add or remove any IDs
- If your response is invalid, Wix falls back to random assignment
## Performance Requirements
- **Hard limit**: Response must be returned within **5 seconds**
- **Recommended**: Keep response time under **500ms** for optimal user experience
## Example: Workload Balancing
This example sorts staff members to balance workload by prioritizing those with fewer recent bookings.
```typescript
import { staffSorting } from "@wix/bookings/service-plugins";
import { auth } from "@wix/essentials";
import { extendedBookings } from "@wix/bookings";
staffSorting.provideHandlers({
sortStaffMembers: async (payload) => {
const { request } = payload;
// availableResourceIds is optional on the request type — default it, or
// spreading/iterating it below fails `tsc` with "possibly undefined."
const { availableResourceIds = [], slot } = request;
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
const elevatedQuery = auth.elevate(extendedBookings.queryExtendedBookings);
const result = await elevatedQuery({
filter: {
"bookedEntity.item.slot.resource.id": { "$in": availableResourceIds },
"startDate": { "$gte": sevenDaysAgo },
},
cursorPaging: { limit: 100 },
});
const recentBookings = result.extendedBookings ?? [];
// Count bookings per staff member
const bookingCounts = new Map<string, number>();
for (const id of availableResourceIds) {
bookingCounts.set(id, 0);
}
for (const booking of recentBookings) {
const resourceId = booking.booking?.bookedEntity?.slot?.resource?._id;
if (resourceId && bookingCounts.has(resourceId)) {
bookingCounts.set(resourceId, (bookingCounts.get(resourceId) ?? 0) + 1);
}
}
// Sort by fewest bookings first (balance workload)
const sorted = [...availableResourceIds].sort(
(a, b) => (bookingCounts.get(a) ?? 0) - (bookingCounts.get(b) ?? 0)
);
return {
staff: sorted.map((resourceId) => ({ resourceId })),
};
},
});
```
## Manual Setup Required
None. Confirmed live with a service that has 2 assigned staff — the dashboard's "Add booking" flow resolved a specific staff member from the plugin's sorted order, and the booking created successfully with no errors. No dashboard configuration is needed beyond having the app installed and released, and the service having 2+ staff assigned to genuinely exercise the sort.
## Key Implementation Notes
1. **Return all IDs** - You must return every ID from `availableResourceIds`, just reordered
2. **Performance matters** - Keep logic fast; the booking flow waits for your response
3. **Elevate permissions** - Use `auth.elevate` when querying Wix APIs from the handler
4. **Deterministic sorting** - Use a tiebreaker (e.g., resource ID) when priorities are equal
5. **Use `queryExtendedBookings`, not `query`** — `extendedBookings.query` is deprecated. `queryExtendedBookings` takes the same `filter`/`cursorPaging` shape, so it's a drop-in replacement; confirmed live after switching.
6. **`availableResourceIds` is optional on the request type** — default it to `[]` when destructuring, or spreading/iterating it fails `tsc` with "possibly undefined."
7. **Graceful degradation** - If your external data source is unavailable, return the original order rather than failing
SHA-256: 8bb1960e1bd8f71f35d62a548a4e56ded97ad509ea3f89a1aff12d59e8a1b9cd