Resources & Instances
Reservations draw a deliberate line between what can be booked and the physical thing that gets used. A "Deluxe King Suite" is a type with a nightly rate and an occupancy rule; "Room 204" and "Room 205" are the units that actually get assigned, checked in, and cleaned. Keeping these separate lets one resource definition back many interchangeable units, and lets you take a single unit out of service without touching the catalog.
The catalog has three layers:
- ResourceCategory groups resources for browsing, display order, channel mapping, and resource-type filtering.
- Resource defines a bookable type — a dining table type, a room type, or a rental product — with its capacity, pricing, booking behavior, and checklist templates.
- ResourceInstance is a physical unit under a resource that can be assigned, reserved, occupied, blocked for maintenance, cleaned, or retired.
Why it matters
- One type, many units — define a room or table type once, then add as many interchangeable instances as you own. Bookings match the type; the platform assigns a free unit.
- Operational truth — take a single instance into
maintenanceorcleaningwithout making the whole resource unbookable. - Right model per business — capacity and pricing strategies adapt the same structure to tables (party-size ranges), rooms (occupancy + nightly rates), and rentals (single-unit limits + tiered pricing).
ResourceCategory
Groups resources by business use, location scope, resource type, and external channel mapping.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique category identifier |
name | string | Yes | Category display name |
description | string | null | No | Public or administrative description |
locationId | string | null | No | Location scope; null applies across locations |
resourceType | enum | null | No | table, room, rental, or resource scope |
displayOrder | number | null | No | Stable ordering for catalog displays |
channelMappings | array | null | No | External channel category IDs (channelId, externalCategoryId) |
isActive | boolean | Yes | Whether the category is usable (default: true) |
metadata | object | null | No | Integration-specific or rendering metadata |
resourceRevisionId | string | null | No | Version revision this category belongs to |
Resource
Defines a reservable type, including capacity, pricing, booking behavior, checklist templates, and display metadata.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier |
resourceType | enum | Yes | table, room, rental, or resource |
name | string | Yes | Resource name |
categoryId | string | null | No | Category this resource belongs to |
locationId | string | null | No | Location scope |
description | string | null | No | Description |
imageUrls | string[] | null | No | Image URLs |
capacity | integer | null | No | Simple capacity |
capacityConfig | object | null | No | Strategy-based capacity (see below) |
isAvailable | boolean | Yes | Catalog availability (default: true) |
amenities | string[] | No | Amenity labels (default: []) |
pricing | object | null | No | Pricing strategy (see below) |
turnoverMinutes | integer | null | No | Reset time between bookings |
reservationDuration | integer | null | No | Default duration |
reservationDurationUnit | enum | null | No | minutes, hours, or nights |
checklistTemplate | array | No | Pickup/return checklist items (default: []) |
applicableTierIds | string[] | No | Pricing tier IDs (default: []) |
attributes | array | null | No | Structured key/value attributes |
instances | array | null | Conditional | Instance IDs (read) / embedded definitions (create) |
Capacity strategies
capacityConfig is discriminated by kind and pairs with a resource type.
Strategy (kind) | Resource type | Fields | Purpose |
|---|---|---|---|
range | table | min, max | Party-size matching |
occupancy | room | standard, max, extraFee | Lodging occupancy pricing |
single | rental | value, weightLimit, skillLevel | Single-unit rental constraints |
Pricing strategies
pricing is discriminated by kind.
Strategy (kind) | Resource type | Fields | Purpose |
|---|---|---|---|
none | table | holdPolicy | No price quote needed for a slot |
dayOfWeek | room | rates.mon … rates.sun | Nightly rate generation |
tiered | rental | tiers[] (from, to, price) | Duration- or quantity-based pricing |
Checklist templates
For rentals especially, a resource can carry a checklist that staff complete at handover. Each item has an id, a label, a required flag (default true), and a phase — pickup, return, or both (default both).
Capacity & pricing in context
The configuration is identical across SDKs and channels — here is a room type with occupancy capacity, day-of-week rates, and two embedded instances:
{
"resourceType": "room",
"name": "King Suite",
"capacityConfig": { "kind": "occupancy", "standard": 2, "max": 4, "extraFee": 25 },
"pricing": {
"kind": "dayOfWeek",
"rates": { "mon": 220, "tue": 220, "wed": 240, "thu": 260, "fri": 320, "sat": 340, "sun": 250 }
},
"amenities": ["wifi", "kitchenette", "city-view"],
"instances": [
{ "name": "Room 204", "code": "204", "status": "available" },
{ "name": "Room 205", "code": "205", "status": "available" }
],
"isAvailable": true
}
When you create a room or rental resource here, it must include at least one instance. On create, the embedded instance definitions omit resourceId; the server assigns it once the parent resource exists. (table resources are exempt because you don't create them here at all — see below.)
table resources are not created directly. The platform creates a table Resource and its ResourceInstance automatically when you author a Floor Plan — that is why tables are exempt from the instance-requirement rule above. Create rooms and rentals here; create tables by defining a floor plan.
ResourceInstance
A physical table, room, rental unit, or other concrete unit under a resource.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier |
resourceId | string | Yes | Parent resource |
name | string | null | No | Instance name (e.g. "Room 204") |
code | string | null | No | Short code (e.g. "204") |
status | enum | Yes | Lifecycle status (default: available) |
isAvailable | boolean | Yes | Physical availability (default: true) |
attributes | array | null | No | Structured key/value attributes (floor, view, …) |
locationId | string | null | No | Location scope |
Status lifecycle
| Value | Meaning |
|---|---|
available | Can be assigned |
reserved | Reserved for a future booking |
occupied | Currently in use |
maintenance | Temporarily blocked for maintenance |
cleaning | Temporarily blocked for reset or cleaning |
out_of_service | Not usable until restored |
Keep physical availability on the ResourceInstance (status, isAvailable) and catalog availability on the Resource (isAvailable).
Resource versioning
Versioning separates a stable catalog definition from its mutable revisions, so you can edit a catalog without disturbing existing reservations. A ResourceDefinition (id, name, description, isActive) owns one or more ResourceRevision records, each with a status of draft, active, or archived, an optional derivedFromRevisionId, and a publishedAt timestamp. Draft a revision for editing, publish it before exposing it to booking channels, and keep historical reservations tied to the resource and instance IDs that existed when they were booked. Catalog records can carry a resourceRevisionId when a revision-specific view is needed.
Query options
Each resource supports paginated filtering and sorting:
| Resource | Filters | Sort fields |
|---|---|---|
ResourceCategory | search, locationId, resourceType[], isActive | name, displayOrder, createdAt |
Resource | search, locationId, resourceType[], categoryId, isAvailable, capacityRange, location, amenities[], priceRange | name, capacity, createdAt |
ResourceInstance | resourceId, locationId, status[], isAvailable | name, status, createdAt |
All sorts take a direction of asc or desc.
Create a resource
A resource is created with its type, configuration, and (for non-table types) its instances.
- TypeScript
- Python
import { ResourceType, ResourceInstanceStatus } from 'wiil-core-js';
const roomResource = await client.reservationResources.create({
name: 'Deluxe Ocean Suite',
resourceType: ResourceType.ROOM,
capacity: 4,
isAvailable: true,
amenities: ['WiFi', 'Air Conditioning', 'Mini Bar', 'Ocean View'],
checklistTemplate: [],
applicableTierIds: [],
instances: [
{ name: 'Room 101', code: 'R101', status: ResourceInstanceStatus.AVAILABLE, isAvailable: true },
{ name: 'Room 102', code: 'R102', status: ResourceInstanceStatus.AVAILABLE, isAvailable: true },
],
});
console.log(`Room Resource Created: ${roomResource.id}`);
from wiil.models.business_mgt import CreateResource, RoomResource
room = client.reservation_resources.create(
CreateResource(
resource_type="room",
name="Room 101",
capacity=2,
is_available=True,
amenities=["WiFi", "Air Conditioning"],
reservation_duration=1,
reservation_duration_unit="nights",
room_resource=RoomResource(
room_number="101",
room_type="Deluxe King",
price_per_night=299.99,
bed_type="King",
is_smoking=False,
),
)
)
print("Resource:", room.id)
Read, update, and batch
- TypeScript
- Python
import { ResourceType } from 'wiil-core-js';
const loaded = await client.resourceCategories.get('category_123');
const roomCategories = await client.resourceCategories.getByResourceType(ResourceType.ROOM);
const allInstances = await client.resourceInstances.getByResource(roomResource.id);
from wiil.models.business_mgt import CreateResource, UpdateResource
from wiil.types import PaginationRequest
loaded = client.reservation_resources.get(room.id)
rooms = client.reservation_resources.get_by_type("room", PaginationRequest(page=1, page_size=20))
updated = client.reservation_resources.update(
UpdateResource(id=room.id, is_available=False)
)
resources = client.reservation_resources.create_batch([
CreateResource(resource_type="table", name="Table 1", description="Corner table for 4", capacity=4, is_available=True),
CreateResource(resource_type="table", name="Table 2", description="Center table for 4", capacity=4, is_available=True),
])
The TypeScript SDK manages categories and instances as dedicated resources (client.resourceCategories, client.resourceInstances), shown below. The Python SDK manages physical inventory through the unified client.reservation_resources model — creating resources (optionally with embedded instances), filtering by type, updating availability, and batch-creating — rather than as separate category/instance clients.
Resource categories
Organize resources into categories. (TypeScript SDK)
import { ResourceType } from 'wiil-core-js';
const category = await client.resourceCategories.create({
name: 'Conference Rooms',
description: 'Meeting and conference spaces',
resourceType: ResourceType.ROOM,
isActive: true,
displayOrder: 1,
});
const roomCategories = await client.resourceCategories.getByResourceType(ResourceType.ROOM);
const activeCategories = await client.resourceCategories.getActive();
const allCategories = await client.resourceCategories.list();
const updated = await client.resourceCategories.update(category.id, {
id: category.id,
description: 'Premium meeting spaces',
displayOrder: 2,
});
const batch = await client.resourceCategories.createBatch([
{ name: 'Executive Suites', resourceType: ResourceType.ROOM, isActive: true, displayOrder: 10 },
{ name: 'Equipment Rentals', resourceType: ResourceType.RENTAL, isActive: true, displayOrder: 11 },
]);
await client.resourceCategories.delete(category.id);
Resource instances
Manage individual bookable units within a resource. (TypeScript SDK)
import { ResourceInstanceStatus } from 'wiil-core-js';
const instance = await client.resourceInstances.create({
resourceId: roomResource.id,
name: 'Room 201',
code: 'R201',
status: ResourceInstanceStatus.AVAILABLE,
isAvailable: true,
attributes: [
{ key: 'floor', value: '2' },
{ key: 'view', value: 'garden' },
],
});
const resourceInstances = await client.resourceInstances.getByResource(roomResource.id);
const availableInstances = await client.resourceInstances.getByStatus(ResourceInstanceStatus.AVAILABLE);
const updatedInstance = await client.resourceInstances.update(instance.id, {
id: instance.id,
code: 'R201-PREMIUM',
attributes: [
{ key: 'floor', value: '2' },
{ key: 'view', value: 'ocean' },
],
});
await client.resourceInstances.delete(instance.id);