Skip to main content

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:

TypeUse caseDurationKey fields
TableRestaurants, diningMinutestime, duration, personsNumber, floorPlanId
RoomHotels, accommodationsNightscheckIn, checkOut, nights, ratePerNight, guestId
RentalEquipment, vehicles, spacesHours / minutesstartAt, endAt, tierId, payment
The two SDKs model reservations differently

This is the one domain where the SDKs diverge significantly.

  • TypeScript exposes a dedicated client per reservation typeclient.tableReservations, client.roomReservations, client.rentalReservations — plus client.reservationResources, client.resourceCategories, client.resourceInstances, client.floorPlans, and client.reservationSettings. Table resources are created through floor plans; rooms and rentals are created as resources with embedded instances.
  • Python exposes one unified client.reservations client (discriminated by reservation_type) plus client.reservation_resources (with embedded type-specific models like RoomResource). 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.

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);

Resources

Rooms & rentals

Rooms and rentals are created as resources with embedded instances (TypeScript) or with type-specific embedded models (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 },
],
});
Tables come from floor plans

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

// 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');

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".

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');

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

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');

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's startTimeUtcSec/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 use checkIn/checkOut/nights/ratePerNight; rentals use startAt/endAt/tierId/payment.
  • Match SDK to model — in TypeScript pick the per-type client; in Python use the unified reservations client with reservation_type.

Next steps


← Back to Guides