Technical Step-by-Step Instructions: Creating Multi-Resource Bookings Services (Rooms, Equipment, Staff) - Real-World, API-First
Description
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.
Prerequisites
Required App Installations
Before creating multi-resource services, ensure the following requirements are met:
- Wix Bookings - Core app must be installed and configured
- Business Location - At least one business location must be configured
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.
App Installation Process
If you encounter resource-related errors, install the required apps using the Apps Installer API.
For detailed app installation procedures, refer to:
- Apps Installer API Documentation
- Business setup recipes for comprehensive app installation workflows
Overview
Multi-resource services allow businesses to create bookings that require multiple types of resources simultaneously. Common examples:
- Fitness Classes: Room + Equipment + Instructor
- Meeting Services: Conference Room + AV Equipment + Catering Staff
- Spa Treatments: Treatment Room + Specialized Equipment + Therapist
The system involves three independent entity types that can be connected:
- Resource Types - Category definitions (Room, Equipment, Staff) - independent entities
- Resources - Individual resource instances with their own schedules and availability - independent entities
- Services - Booking services that can optionally reference resource types - independent entities
Key Architecture Principle: Resources and Services are separate, independent entities. Resources exist independently but their availability depends on business location hours (for non-staff resources) or working hour schedules (for staff resources). Services can optionally connect to resource types (not individual resources) to require resource allocation during booking, but this connection is loose and flexible.
CRITICAL API DISCOVERY
❌ COMMON ARCHITECTURE MISTAKES (Not Clear in Individual Docs):
- Creating resources without resource types first (creation sequence matters)
- Assuming resources automatically inherit business hours (availability dependency isn't clear)
- Thinking you can connect same resource to conflicting schedules
✅ CORRECT RESOURCE ARCHITECTURE:
- Independent Creation: Resource Types → Resources (both exist independently)
- Optional Service Connection: Services can reference resource types when resource allocation is needed
- Loose Coupling: Resources maintain their own schedules and availability regardless of service connections
- Type-Based References: Services connect to
resourceType.id, not individual resource IDs - Resource Autonomy: Resources function independently - services simply request allocation from available resources of specified types
Key Discovery: Resource Schedule Behavior
Resource Availability Behavior:
- Each resource automatically gets a dedicated
eventsSchedulefor tracking bookings - Non-staff resources: Availability depends on business location hours (not 24/7)
- Staff resources: Have working hour schedules in addition to event schedules
- Working hours override: When
workingHoursSchedulesis configured, it takes precedence over location hours
Schedule Sharing Patterns:
shared: false= Dedicated schedule per resource (recommended for most cases)shared: true= Multiple resources use same working hours schedule- Business schedule is always
shared: trueamong staff
Key Discovery: Service-Resource Connection Pattern
Service Configuration Pattern:
"serviceResources": [
{"resourceType": {"id": "room-type-id"}},
{"resourceType": {"id": "equipment-type-id"}},
{"resourceType": {"id": "staff-type-id"}}
]Critical: Services specify resource types, not individual resources. This creates a loose coupling where:
- Resources exist independently but availability follows business location hours (non-staff) or working hours (staff)
- Services request allocation from available resources of specified types during booking
- No direct binding between individual resources and services
- Resource management (updates, working hours) is independent of service configuration
IMPORTANT NOTES
- Entity Independence: Resources and Services are separate entities - you can create and manage resources without any services, and vice versa
- Optional Connection: Services only need to reference resource types if they require resource allocation for bookings
- Location Complexity:
availableInAllLocations: trueis simplest; specific location configuration is complex and often unnecessary - Service Pricing: Multi-resource services often justify higher pricing due to resource coordination complexity
Steps
1. Plan Resource Type Architecture
Before creating anything, plan your resource type structure. Each type should represent a category of resources that can be substituted for each other in bookings.
Common Resource Type Patterns:
- Physical Spaces: Room, Studio, Meeting Room, Treatment Room
- Equipment Categories: AV Equipment, Medical Equipment, Sports Equipment
- Human Resources: Instructor, Therapist, Consultant, Technician
Design Principle: If resources are interchangeable for a service, they belong to the same type.
2. Create Resource Types
Create resource types using createResourceType API (POST https://www.wixapis.com/bookings/v2/resources/resource-types) (REST):
{ "resourceType": { "name": "Treatment Room" } }The response returns resourceType.id — save it for resource creation and the service's serviceResources.
Key Requirements:
namemust be unique across the site- Keep
namedescriptive but concise (appears in booking interface) - Save the returned
resourceType.idfor resource creation
Important: Cannot change name after creation if conflicts occur - plan carefully.
3. Create Individual Resources
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); for a single one, createResource (POST https://www.wixapis.com/bookings/v2/resources) takes { "resource": { "name": ..., "typeId": ... } }.
{
"resources": [
{ "name": "Room A", "typeId": "<RESOURCE_TYPE_ID>" },
{ "name": "Room B", "typeId": "<RESOURCE_TYPE_ID>" }
],
"returnEntity": true
}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.
⚠️ 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.
If you omit locationOptions, the resource defaults to availableInAllLocations: true — the simplest and usually correct configuration; specific location setup is complex and often unnecessary.
Advanced Configuration (Gap):
- Custom working hours override business location hours (this behavior isn't clearly documented)
- Specific locations: Use
specificLocationOptions(complex - avoid unless required)
Critical: Each resource automatically gets its own eventsSchedule for booking management (this is documented but the implications for multi-resource coordination aren't clear).
4. Create Multi-Resource Service (Optional Connection)
Create the service that optionally connects to multiple resource types using bulkCreateServices API (POST https://www.wixapis.com/bookings/v2/bulk/services/create) (REST). Note the endpoint path is /bulk/services/create (not /services/bulk/create, which 404s).
Pick the service type, and mind the resource-specific required fields:
- 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 400primary_resource_type is required for appointment services without staff members. APPOINTMENT also needsschedule.availabilityConstraints.sessionDurations. - A group service (fixed capacity per session) is a
CLASS(drop-in) orCOURSE(whole series); these usedefaultCapacityand do not requireprimaryResourceType.
Appointment example (one room per booking, no staff):
{
"services": [{
"name": "Massage",
"type": "APPOINTMENT",
"onlineBooking": { "enabled": true },
"serviceResources": [
{ "resourceType": { "id": "<ROOM_TYPE_ID>" } }
],
"primaryResourceType": "<ROOM_TYPE_ID>",
"schedule": { "availabilityConstraints": { "sessionDurations": [60] } },
"payment": {
"rateType": "FIXED",
"options": { "online": true, "inPerson": false },
"fixed": { "price": { "value": "80" } }
}
}],
"returnEntity": true
}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.
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.
⚠️ 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.
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.
Pricing Strategy: Multi-resource services typically command premium pricing due to coordination complexity.
5. Understand Resource Allocation Behavior (Gap in Docs)
The docs don't explain how multi-resource allocation actually works during booking. Key behaviors to understand:
- Peak time conflicts: When Room 1 is booked, Wix automatically tries Room 2 for the same resource type
- Equipment maintenance: Blocking specific resources affects all services requiring that resource type
- Cross-resource dependencies: If ANY required resource type has no availability, the entire booking fails
Architecture Implication: Plan resource quantities based on expected concurrent demand across all services.
IMPORTANT NOTES
- Resource Allocation Logic: Wix automatically handles resource selection during booking - you specify types, not individual resources
- Conflict Resolution: If any required resource type has no available resources, the entire booking fails
- Service Modification: Adding/removing resource type requirements from existing services may affect existing bookings
- Performance Consideration: Complex multi-resource services may have slower booking availability calculation
Troubleshooting Common Issues
"Resource type not found" Error:
- Verify resource type was created successfully before creating resources
- Check that
typeIdexactly matches the resource typeid - Ensure you're not using resource type
namewhenidis required
400 "Unexpected value for StringValue" on createResource or on service primaryResourceType:
- A resource-type reference was sent as a nested object where a flat GUID string is expected.
createResourceuses"typeId": "<guid>"; the service field is"primaryResourceType": "<guid>"(both flat, not{"id": ...}). Note this differs fromserviceResources[].resourceType.id, which is nested.
400 "primary_resource_type is required for appointment services without staff members":
- An
APPOINTMENTservice bound to a resource (nostaffMemberIds) needsprimaryResourceTypeset to the driving resource-type GUID. Either add it, or model the service as aCLASS/COURSEif a group service fits.
404 on bulk creation:
- 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.
Cannot read properties of undefined after a bulk create (resources or services):
- Every bulk response nests the entity directly under
results[i].item— useitem.id, neveritem.resource.idoritem.service.id. WithoutreturnEntity: truethere is noitemat all, onlyitemMetadata.id.
"Resource type name already exists" Error (409):
- Resource type names must be unique across the site
- Query existing resource types to avoid duplicates
- Consider using more specific names (e.g., "Meeting Room" vs "Room")
Service doesn't show resource requirements:
- Verify
serviceResourcesarray includes all required resource types - Check that resource type IDs are correct
- Confirm service creation was successful with proper resource configuration
Resources showing as unavailable:
- Check if
workingHoursSchedulesis too restrictive - Verify
locationOptionsmatches your business location setup - Test with
availableInAllLocations: trueto eliminate location issues
Resource updates failing:
- Handle revision conflicts with retry logic (revision requirement is documented but conflict handling strategies aren't)
Complex location availability issues:
- Start with
availableInAllLocations: truefor all resources - Only add location restrictions if absolutely necessary
- Location configuration is complex and often causes more problems than it solves
Resource deletion concerns:
- Deleting resources with active bookings may cause issues (deletion cleanup is documented but impact on existing bookings isn't clear)
- Consider disabling/hiding resources instead of deletion
Resource Architecture Best Practices
Resource Type Design:
- Keep types broad enough to allow flexibility but specific enough to be meaningful
- Plan for growth - easier to split types later than merge them
- Use clear, customer-facing names (they appear in booking interfaces)
Resource Naming:
- Include location/identifier in resource names for easy management
- Be consistent with naming patterns across resource types
- Consider how names appear in booking confirmations and staff interfaces
Availability Strategy:
- Don't add
workingHoursSchedulesto non-staff resources unless business rules require it — without them the resource simply follows business location hours, which is usually what you want - Use working hours sparingly - they add complexity without always adding value
- Test availability scenarios thoroughly before going live
Service Design:
- Start with simpler single-resource services before attempting multi-resource
- Consider premium pricing for multi-resource services due to coordination complexity
- Plan for resource substitution scenarios (what if preferred room is unavailable?)