Reservation Management Guide
Manage bookable resources and reservations across three types: tables, rooms, and rentals.
WIIL supports three reservation systems, each with its own fields and flow:
| Type | Use case | Duration | Key fields |
|---|---|---|---|
| Table | Restaurants, dining | Minutes | time, duration, personsNumber, floorPlanId |
| Room | Hotels, accommodations | Nights | checkIn, checkOut, nights, ratePerNight, guestId |
| Rental | Equipment, vehicles, spaces | Hours / minutes | startAt, endAt, tierId, payment |
This is the one domain where the SDKs diverge significantly.
- TypeScript exposes a dedicated client per reservation type —
client.tableReservations,client.roomReservations,client.rentalReservations— plusclient.reservationResources,client.resourceCategories,client.resourceInstances,client.floorPlans, andclient.reservationSettings. Table resources are created through floor plans; rooms and rentals are created as resources with embedded instances. - Python exposes one unified
client.reservationsclient (discriminated byreservation_type) plusclient.reservation_resources(with embedded type-specific models likeRoomResource). The Python SDK does not expose floor plans, resource categories, instances, or settings.
Bilingual tabs are shown where both SDKs cover an operation; TypeScript-only resources (floor plans, categories, instances, settings) are labeled.
Quick start
Book a table — in TypeScript via a floor plan and the per-type client; in Python via the unified model.
- TypeScript
- Python
import { WiilClient } from 'wiil-js';
import { CanvasUnit, TableShape, ResourceType } from 'wiil-core-js';
const client = new WiilClient({ apiKey: process.env.WIIL_API_KEY! });
// 1. Create a floor plan (this creates the table resources for you)
const floorPlan = await client.floorPlans.createDefinition({
name: 'Main Dining',
description: 'Primary dining area',
capacity: 4,
canvasDimensions: { width: 800, height: 600, unit: CanvasUnit.PX },
isActive: true,
sections: [
{
name: 'Window',
capacity: 4,
color: '#2F80ED',
isActive: true,
sortOrder: 1,
tables: [
{ number: 'W1', x: 100, y: 100, width: 80, height: 80, shape: TableShape.ROUND, minParty: 2, maxParty: 4, combinableWith: [] },
],
},
],
});
// 2. Query available slots
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const slotResponse = await client.tableReservations.getAvailableSlots({
resourceType: ResourceType.TABLE,
localDate: tomorrow.toISOString().split('T')[0],
partySize: 4,
floorPlanId: floorPlan.id,
maxResults: 10,
});
// 3. Book the first slot (API expects UTC seconds)
const slot = slotResponse.slots.find(s => s.isAvailable) ?? slotResponse.slots[0];
const reservation = await client.tableReservations.create({
resourceId: floorPlan.id,
customerId: 'cust_123',
floorPlanId: floorPlan.id,
time: slot.startTimeUtcSec,
duration: 120,
personsNumber: 4,
isVip: false,
notes: 'Window table preferred',
});
console.log('Reservation Created:', reservation.id);
import os
from time import time
from wiil import WiilClient
from wiil.models.business_mgt import CreateReservation, CreateResource
client = WiilClient(api_key=os.environ["WIIL_API_KEY"])
now_ms = int(time() * 1000)
# 1. Create a bookable resource
table = client.reservation_resources.create(
CreateResource(
resource_type="table",
name="Table 5",
description="Window-side table for 4 guests",
capacity=4,
is_available=True,
location="Main dining area",
amenities=["Window view", "Booth seating"],
reservation_duration=2,
reservation_duration_unit="hours",
sync_enabled=False,
)
)
# 2. Book it through the unified reservations client
reservation = client.reservations.create(
CreateReservation(
reservation_type="table",
resource_id=table.id,
customer_id="cust_123",
start_time=now_ms + 3600000,
end_time=now_ms + 7200000,
duration=2,
persons_number=4,
total_price=0,
deposit_paid=0,
notes="Window table preferred",
is_resource_reservation=True,
)
)
print("Resource:", table.id)
print("Reservation:", reservation.id)
Resources
Rooms & rentals
Rooms and rentals are created as resources with embedded instances (TypeScript) or with type-specific embedded models (Python).
- 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', '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 },
],
});
const rentalResource = await client.reservationResources.create({
name: 'Mountain Bike - Premium',
resourceType: ResourceType.RENTAL,
capacity: 1,
isAvailable: true,
amenities: ['Helmet included', 'Lock included'],
checklistTemplate: [],
applicableTierIds: [],
instances: [
{ name: 'Bike #001', code: 'MTB-001', status: ResourceInstanceStatus.AVAILABLE, isAvailable: true },
],
});
from wiil.models.business_mgt import CreateResource, RoomResource, UpdateResource
from wiil.types import PaginationRequest
room = client.reservation_resources.create(
CreateResource(
resource_type="room",
name="Room 101",
capacity=2,
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,
),
)
)
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))
A table resource is not created directly — define a floor plan and the platform creates the table resources and instances for you.
Batch create resources
The Python SDK creates up to 50 resources per request with create_batch:
from wiil.models.business_mgt import CreateResource
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),
])
Resource categories (TypeScript)
Organize resources into categories.
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();
await client.resourceCategories.update(category.id, { id: category.id, displayOrder: 2 });
await client.resourceCategories.createBatch([
{ name: 'Executive Suites', resourceType: ResourceType.ROOM, isActive: true, displayOrder: 10 },
]);
await client.resourceCategories.delete(category.id);
Resource instances (TypeScript)
Manage the individual physical units within a resource.
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 byResource = await client.resourceInstances.getByResource(roomResource.id);
const available = await client.resourceInstances.getByStatus(ResourceInstanceStatus.AVAILABLE);
await client.resourceInstances.update(instance.id, { id: instance.id, code: 'R201-PREMIUM' });
await client.resourceInstances.delete(instance.id);
Floor plans (TypeScript)
Table resources are authored through a floor plan — a canvas of sections and table placements. Creating the definition creates the underlying table resources and instances.
import { CanvasUnit, TableShape } from 'wiil-core-js';
const floorPlan = await client.floorPlans.createDefinition({
name: 'Main Dining Room',
description: 'Primary indoor dining layout',
capacity: 12,
canvasDimensions: { width: 1200, height: 800, unit: CanvasUnit.PX },
isActive: true,
sections: [
{
name: 'Window',
capacity: 8,
color: '#2F80ED',
isActive: true,
sortOrder: 1,
tables: [
{ number: 'W1', x: 220, y: 180, width: 80, height: 80, shape: TableShape.ROUND, minParty: 2, maxParty: 4, combinableWith: ['W2'] },
{ number: 'W2', x: 320, y: 180, width: 80, height: 60, shape: TableShape.RECT, minParty: 2, maxParty: 4, combinableWith: ['W1'] },
],
},
{
name: 'Main Floor',
capacity: 4,
color: '#7B68EE',
isActive: true,
sortOrder: 2,
tables: [
{ number: 'M1', x: 200, y: 420, width: 120, height: 80, shape: TableShape.RECT, minParty: 2, maxParty: 4, combinableWith: [] },
],
},
],
});
const loaded = await client.floorPlans.get(floorPlan.id);
Section capacity must equal the sum of its tables' maxParty, and floor-plan capacity must equal the sum of section capacities.
Reservation settings (TypeScript)
Configure per-location reservation behavior and enable each mode.
const settings = await client.reservationSettings.create({
locationId: 'loc_123',
supportTableReservations: true,
supportRoomReservations: true,
supportRentalReservations: false,
table: {
defaultDurationMinutes: 90,
turnoverMinutes: 15,
slotIntervalMinutes: 30,
advanceBookingDays: 30,
maxPartySize: 12,
},
});
const byLocation = await client.reservationSettings.getByLocation('loc_123');
const all = await client.reservationSettings.list();
await client.reservationSettings.update({ id: settings.id, table: { advanceBookingDays: 60, maxPartySize: 20 } });
await client.reservationSettings.delete(settings.id);
Table reservations
Restaurant bookings against a floor plan. In TypeScript, query slots and use client.tableReservations; in Python, use the unified client with reservation_type="table".
Query available table slots (TypeScript)
import { ResourceType } from 'wiil-core-js';
const slotResponse = await client.tableReservations.getAvailableSlots({
resourceType: ResourceType.TABLE,
localDate: '2026-06-22',
partySize: 4,
floorPlanId: 'fp_123',
maxResults: 10,
});
slotResponse.slots.forEach((slot, idx) => console.log(`${idx + 1}. ${slot.startTimeOfDay}`));
Create, read, cancel
- TypeScript
- Python
// API expects UTC seconds — use slot times directly
const reservation = await client.tableReservations.create({
resourceId: 'fp_123',
customerId: 'cust_123',
floorPlanId: 'fp_123',
time: slot.startTimeUtcSec,
duration: 120,
personsNumber: 4,
isVip: false,
notes: 'Anniversary dinner',
});
const loaded = await client.tableReservations.get('reservation_123');
const all = await client.tableReservations.list();
const updated = await client.tableReservations.update(reservation.id, {
id: reservation.id,
personsNumber: 6,
notes: 'Party size increased to 6',
});
const cancelled = await client.tableReservations.cancel(reservation.id, 'Customer requested cancellation');
await client.tableReservations.delete('reservation_123');
from time import time
from wiil.models.business_mgt import CreateReservation, UpdateReservation
from wiil.types import PaginationRequest
now_ms = int(time() * 1000)
reservation = client.reservations.create(
CreateReservation(
reservation_type="table",
resource_id="resource_table5",
customer_id="cust_123",
start_time=now_ms + 3600000,
end_time=now_ms + 7200000,
duration=2,
persons_number=4,
total_price=0,
deposit_paid=0,
is_resource_reservation=True,
)
)
loaded = client.reservations.get(reservation.id)
by_customer = client.reservations.get_by_customer("cust_123", PaginationRequest(page=1, page_size=20))
updated = client.reservations.update(UpdateReservation(id=reservation.id, persons_number=6, notes="Party size increased"))
status_updated = client.reservations.update_status(reservation.id, "confirmed")
cancelled = client.reservations.update_status(reservation.id, "cancelled")
Room reservations
Hotel stays with check-in/check-out dates and nightly rates. In TypeScript, use client.roomReservations; in Python, the unified client with reservation_type="room".
- TypeScript
- Python
import { ReservationStatus, PaymentStatus } from 'wiil-core-js';
// API expects UTC seconds
const nowSec = Math.floor(Date.now() / 1000);
const checkIn = nowSec + 24 * 60 * 60;
const checkOut = checkIn + 3 * 24 * 60 * 60;
const roomReservation = await client.roomReservations.create({
resourceId: 'res_room101',
guestId: 'cust_456',
personsNumber: 2,
checkIn,
checkOut,
nights: 3,
status: ReservationStatus.PENDING,
ratePerNight: [
{ date: '2026-06-22', amount: 299.00 },
{ date: '2026-06-23', amount: 299.00 },
{ date: '2026-06-24', amount: 299.00 },
],
totalWithTax: 980.67,
deposit: 299.00,
paymentStatus: PaymentStatus.PENDING,
notes: 'Late check-in requested',
});
const byGuest = await client.roomReservations.getByGuest('cust_456');
const byResource = await client.roomReservations.getByResource('res_room101');
const all = await client.roomReservations.list();
const updated = await client.roomReservations.update(roomReservation.id, {
id: roomReservation.id,
personsNumber: 3,
deposit: 350.00,
});
const cancelled = await client.roomReservations.cancel(roomReservation.id, 'Change of travel plans');
await client.roomReservations.delete('reservation_123');
from time import time
from wiil.models.business_mgt import CreateReservation
from wiil.types import PaginationRequest
now_ms = int(time() * 1000)
reservation = client.reservations.create(
CreateReservation(
reservation_type="room",
resource_id="resource_room101",
customer_id="cust_456",
start_time=now_ms,
end_time=now_ms + 3 * 24 * 60 * 60 * 1000,
duration=3,
persons_number=2,
total_price=899.97,
deposit_paid=299.99,
is_resource_reservation=True,
)
)
by_resource = client.reservations.get_by_resource("resource_room101", PaginationRequest(page=1, page_size=20))
status_updated = client.reservations.update_status(reservation.id, "confirmed")
Rental reservations
Equipment, vehicles, and spaces with a pickup/return flow, tiers, and deposits. In TypeScript, use client.rentalReservations; in Python, the unified client with reservation_type="rental".
Query available rental slots (TypeScript)
import { ResourceType } from 'wiil-core-js';
const slotResponse = await client.rentalReservations.getAvailableSlots({
resourceType: ResourceType.RENTAL,
localDate: '2026-06-22',
resourceId: 'res_bike',
durationMinutes: 240,
maxResults: 10,
});
slotResponse.slots.forEach((slot, idx) =>
console.log(`${idx + 1}. Pickup ${slot.pickupTimeOfDay}, Return ${slot.returnTimeOfDay}`),
);
Create, read, cancel
- TypeScript
- Python
import { RentalReservationStatus, DepositStatus } from 'wiil-core-js';
const rentalReservation = await client.rentalReservations.create({
resourceId: 'res_bike',
customerId: 'cust_789',
startAt: slot.startTimeUtcSec,
endAt: slot.endTimeUtcSec,
tierId: 'tier_standard',
status: RentalReservationStatus.UPCOMING,
payment: {
rentalCharge: 75.00,
securityDeposit: 200.00,
depositStatus: DepositStatus.PENDING,
},
checklistCompletions: [],
notes: 'First-time renter',
});
const byCustomer = await client.rentalReservations.getByCustomer('cust_789');
const byResource = await client.rentalReservations.getByResource('res_bike');
const all = await client.rentalReservations.list();
const updated = await client.rentalReservations.update(rentalReservation.id, {
id: rentalReservation.id,
notes: 'Early pickup requested',
payment: { rentalCharge: 85.00, securityDeposit: 200.00, depositStatus: DepositStatus.PAID },
});
const cancelled = await client.rentalReservations.cancel(rentalReservation.id, 'Weather conditions');
await client.rentalReservations.delete('reservation_123');
from time import time
from wiil.models.business_mgt import CreateReservation
now_ms = int(time() * 1000)
reservation = client.reservations.create(
CreateReservation(
reservation_type="rental",
resource_id="resource_bike",
customer_id="cust_789",
start_time=now_ms + 3600000,
end_time=now_ms + 3600000 + 4 * 60 * 60 * 1000,
duration=240,
total_price=75.00,
deposit_paid=200.00,
is_resource_reservation=True,
)
)
rescheduled = client.reservations.reschedule(
reservation.id,
start_time=str(now_ms + 48 * 60 * 60 * 1000),
end_time=str(now_ms + 49 * 60 * 60 * 1000),
)
cancelled = client.reservations.update_status(reservation.id, "cancelled")
Status enums
import { ReservationStatus, RentalReservationStatus, ResourceInstanceStatus, ResourceType } from 'wiil-core-js';
// ResourceType: 'table' | 'room' | 'rental'
// ReservationStatus (room): pending | confirmed | checked_in | checked_out | cancelled | no_show
// RentalReservationStatus: upcoming | active | completed | cancelled
// ResourceInstanceStatus: available | occupied | maintenance | reserved
The Python unified client accepts string status values via update_status (for example "confirmed", "cancelled").
Complete example: restaurant reservations (TypeScript)
import { WiilClient } from 'wiil-js';
import { CanvasUnit, TableShape, ResourceType, PreferredContactMethod } from 'wiil-core-js';
async function setupRestaurantReservations() {
const client = new WiilClient({ apiKey: process.env.WIIL_API_KEY! });
// 1. Customer
const customer = await client.customers.create({
phone_number: '+15551234567',
firstname: 'John',
lastname: 'Smith',
preferred_language: 'en',
preferred_contact_method: PreferredContactMethod.SMS,
isValidatedNames: false,
});
// 2. Floor plan (creates the table resources)
const floorPlan = await client.floorPlans.createDefinition({
name: 'Main Dining',
description: 'Primary dining area',
capacity: 4,
canvasDimensions: { width: 800, height: 600, unit: CanvasUnit.PX },
isActive: true,
sections: [
{
name: 'Window',
capacity: 4,
color: '#2F80ED',
isActive: true,
sortOrder: 1,
tables: [
{ number: 'W1', x: 100, y: 100, width: 80, height: 80, shape: TableShape.ROUND, minParty: 2, maxParty: 4, combinableWith: [] },
],
},
],
});
// 3. Slots
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const slotResponse = await client.tableReservations.getAvailableSlots({
resourceType: ResourceType.TABLE,
localDate: tomorrow.toISOString().split('T')[0],
partySize: 4,
floorPlanId: floorPlan.id,
maxResults: 10,
});
if (slotResponse.slots.length === 0) return;
// 4. Book
const slot = slotResponse.slots.find(s => s.isAvailable) ?? slotResponse.slots[0];
const reservation = await client.tableReservations.create({
resourceId: floorPlan.id,
customerId: customer.id,
floorPlanId: floorPlan.id,
time: slot.startTimeUtcSec,
duration: 120,
personsNumber: 4,
isVip: true,
notes: 'Anniversary dinner',
});
// 5. Reschedule and inspect
const all = await client.tableReservations.list();
console.log(`Total reservations: ${all.data.length}`);
return { customer, floorPlan, reservation };
}
setupRestaurantReservations().catch(console.error);
Best practices
- Query slots before booking — use
getAvailableSlots(table, rental) and pass the slot'sstartTimeUtcSec/endTimeUtcSec(the API expects UTC seconds). - Tables come from floor plans — author the layout; the platform creates the table resources and instances.
- Use the right fields per type — tables use
time/personsNumber; rooms usecheckIn/checkOut/nights/ratePerNight; rentals usestartAt/endAt/tierId/payment. - Match SDK to model — in TypeScript pick the per-type client; in Python use the unified
reservationsclient withreservation_type.
Next steps
- Catalog reference: Resources & Instances, Floor Plans, Table · Room · Rental reservations, Settings
- Notifications: booking confirmations via outbound communications