Reservation
Services, providers, bookings, and availability management
The Reservation module provides complete booking functionality including services, providers, availability, and checkout.
Services
Services represent bookable offerings (haircuts, consultations, classes, etc.).
Create Service
/v1/businesses/{businessId}/services sdk.reservation.createService() Create a new bookable service.
const result = await sdk.reservation.createService({
key: 'haircut',
nodeIds: ['node_services', 'node_hair'],
blocks: [
{
key: 'description',
type: 'TEXT',
content: {
body: { en: 'Professional haircut service' }
}
}
],
prices: [
{ market: 'USD', amount: 3500 },
{ market: 'EUR', amount: 3200 }
],
durations: [
{ duration: 30, isPause: false },
{ duration: 45, isPause: false }
],
isApprovalRequired: false,
status: 'ACTIVE',
providers: [
{
providerId: 'prv_sarah',
workingTime: {
workingDays: [
{ day: 'MONDAY', workingHours: [{ from: 540, to: 1020 }] },
{ day: 'TUESDAY', workingHours: [{ from: 540, to: 1020 }] }
],
outcastDates: [],
specificDates: []
}
}
]
});Parameters
| Name | Type | Description |
|---|---|---|
key required | string | Unique service key identifier |
slug optional | Record<string, string> | Locale-keyed URL slugs |
access optional | PUBLIC | AUTHENTICATED | PRIVATE | Access level |
nodeIds optional | string[] | Category node IDs |
networkIds optional | string[] | Network IDs |
blocks optional | Block[] | Content blocks for service details |
prices optional | Price[] | Pricing per market (array of { market, amount }) |
durations optional | ServiceDuration[] | Duration segments (array of { duration: number, isPause: boolean }) |
isApprovalRequired optional | boolean | Whether bookings need approval |
location optional | Location | Service location (for mobile services) |
status optional | DRAFT | ACTIVE | ARCHIVED | Service status |
providers optional | ServiceProviderInput[] | Provider assignments with working time |
Get Service
/v1/businesses/{businessId}/services/{id} sdk.reservation.getService() Retrieve a service by ID or slug.
// By ID
const result = await sdk.reservation.getService({
id: 'svc_xyz789'
});
// By slug (locale-aware)
const result = await sdk.reservation.getService({
slug: 'haircut'
});
Parameters
| Name | Type | Description |
|---|---|---|
id optional | string | Service ID (use this OR slug) |
slug optional | string | Service slug (locale-aware lookup) |
List Services
/v1/businesses/{businessId}/services sdk.reservation.getServices() List all services with filtering.
const result = await sdk.reservation.getServices({
providerId: 'prv_sarah',
ids: ['svc_1', 'svc_2'],
query: 'haircut',
statuses: ['ACTIVE'],
nodeId: 'node_services',
blocks: ['description', 'gallery'],
sortField: 'createdAt',
sortDirection: 'desc',
priceFrom: 2000,
priceTo: 5000,
cursor: null,
limit: 20
});
result.items.forEach(service => {
console.log(service.key, service.prices);
});Parameters
| Name | Type | Description |
|---|---|---|
providerId optional | string | Filter by provider |
ids optional | string[] | Filter by specific service IDs |
query optional | string | Search query |
statuses optional | string[] | Filter by statuses |
nodeId optional | string | Filter by category node |
blocks optional | Block[] | Filter by blocks content |
matchAll optional | boolean | If true, match all filters (AND); if false, match any (OR) |
sortField optional | string | Sort field |
sortDirection optional | asc | desc | Sort direction |
priceFrom optional | number | Minimum price filter |
priceTo optional | number | Maximum price filter |
from optional | number | Filter by availability from (Unix timestamp) |
to optional | number | Filter by availability to (Unix timestamp) |
createdAtFrom optional | number | Filter by creation date (Unix timestamp) |
createdAtTo optional | number | Filter by creation date (Unix timestamp) |
cursor optional | string | Pagination cursor |
limit optional | number | Items per page |
Update Service
/v1/businesses/{businessId}/services/{id} sdk.reservation.updateService() await sdk.reservation.updateService({
id: 'svc_xyz789',
key: 'premium-haircut',
prices: [{ market: 'USD', amount: 4000 }],
status: 'ACTIVE'
});
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Service ID to update |
key required | string | Service key identifier |
slug optional | Record<string, string> | Locale-keyed URL slugs |
access optional | PUBLIC | AUTHENTICATED | PRIVATE | Access level |
nodeIds optional | string[] | Category node IDs |
networkIds optional | string[] | Network IDs |
blocks optional | Block[] | Content blocks |
prices optional | Price[] | Pricing per market |
durations optional | ServiceDuration[] | Duration segments ({ duration, isPause }) |
isApprovalRequired optional | boolean | Whether bookings need approval |
location optional | Location | Service location |
status optional | DRAFT | ACTIVE | ARCHIVED | Service status |
providers optional | ServiceProviderInput[] | Provider assignments with working time |
Delete Service
/v1/businesses/{businessId}/services/{id} sdk.reservation.deleteService() await sdk.reservation.deleteService({
id: 'svc_xyz789'
});
Bulk Schedule
/v1/businesses/{businessId}/services/bulk-schedule sdk.reservation.bulkSchedule() Apply working time to multiple services and providers at once.
await sdk.reservation.bulkSchedule({
serviceIds: ['svc_haircut', 'svc_coloring'],
providerIds: ['prv_sarah', 'prv_mike'],
workingTime: {
workingDays: [
{ day: 'MONDAY', workingHours: [{ from: 540, to: 1020 }] },
{ day: 'TUESDAY', workingHours: [{ from: 540, to: 1020 }] },
{ day: 'WEDNESDAY', workingHours: [{ from: 540, to: 1020 }] },
{ day: 'THURSDAY', workingHours: [{ from: 540, to: 1020 }] },
{ day: 'FRIDAY', workingHours: [{ from: 540, to: 1020 }] }
],
outcastDates: [],
specificDates: []
}
});
Parameters
| Name | Type | Description |
|---|---|---|
serviceIds required | string[] | Services to apply schedule to |
providerIds required | string[] | Providers to apply schedule to |
workingTime required | WorkingTime | Working time configuration |
Providers
Providers are staff members who perform services.
Create Provider
/v1/businesses/{businessId}/providers sdk.reservation.createProvider() const result = await sdk.reservation.createProvider({
key: 'sarah-johnson',
nodeIds: ['node_stylists'],
blocks: [
{
key: 'bio',
type: 'TEXT',
content: {
body: { en: 'Senior stylist with 10 years experience' }
}
},
{
key: 'image',
type: 'IMAGE',
content: {
mediaId: 'media_sarah123'
}
}
],
concurrentLimit: 1, // Can handle 1 client at a time
status: 'ACTIVE'
});Parameters
| Name | Type | Description |
|---|---|---|
key required | string | Unique provider key identifier |
slug optional | Record<string, string> | Locale-keyed URL slugs |
access optional | PUBLIC | AUTHENTICATED | PRIVATE | Access level |
nodeIds optional | string[] | Category node IDs |
networkIds optional | string[] | Network IDs |
blocks optional | Block[] | Content blocks (bio, image, etc.) |
concurrentLimit optional | number | Max concurrent bookings (default 1) |
status optional | DRAFT | ACTIVE | ARCHIVED | Provider status |
Get Provider
/v1/businesses/{businessId}/providers/{id} sdk.reservation.getProvider() // By ID
const result = await sdk.reservation.getProvider({
id: 'prv_abc123'
});
// By slug
const result = await sdk.reservation.getProvider({
slug: 'sarah-johnson'
});
List Providers
/v1/businesses/{businessId}/providers sdk.reservation.getProviders() const result = await sdk.reservation.getProviders({
serviceId: 'svc_haircut',
ids: ['prv_1', 'prv_2'],
query: 'sarah',
statuses: ['ACTIVE'],
nodeId: 'node_stylists',
blocks: 'bio,image',
sortField: 'createdAt',
sortDirection: 'desc',
cursor: null,
limit: 20,
createdAtFrom: '2024-01-01',
createdAtTo: '2024-12-31'
});
result.items.forEach(provider => {
console.log(provider.key, provider.concurrentLimit);
});Parameters
| Name | Type | Description |
|---|---|---|
serviceId optional | string | Filter by service |
ids optional | string[] | Filter by specific provider IDs |
query optional | string | Search query |
statuses optional | string[] | Filter by statuses |
nodeId optional | string | Filter by category node |
blocks optional | Block[] | Filter by blocks content |
matchAll optional | boolean | If true, match all filters (AND); if false, match any (OR) |
sortField optional | string | Sort field |
sortDirection optional | asc | desc | Sort direction |
from optional | number | Filter by availability from (Unix timestamp) |
to optional | number | Filter by availability to (Unix timestamp) |
createdAtFrom optional | number | Filter by creation date (Unix timestamp) |
createdAtTo optional | number | Filter by creation date (Unix timestamp) |
cursor optional | string | Pagination cursor |
limit optional | number | Items per page |
Get Provider Working Time
/v1/businesses/{businessId}/providers/{providerId}/working-time sdk.reservation.getProviderWorkingTime() Get a provider’s availability schedule.
const result = await sdk.reservation.getProviderWorkingTime({
providerId: 'prv_abc123',
serviceId: 'svc_haircut' // Optional: filter by service
});
// Returns working time configuration
console.log(result.workingDays);
console.log(result.outcastDates);
console.log(result.specificDates);
Parameters
| Name | Type | Description |
|---|---|---|
providerId required | string | Provider ID |
serviceId optional | string | Filter working time by specific service |
Update Provider
/v1/businesses/{businessId}/providers/{id} sdk.reservation.updateProvider() await sdk.reservation.updateProvider({
id: 'prv_abc123',
key: 'sarah-johnson-senior',
concurrentLimit: 2,
status: 'ACTIVE'
});
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Provider ID to update |
key required | string | Provider key identifier |
slug optional | Record<string, string> | Locale-keyed URL slugs |
access optional | PUBLIC | AUTHENTICATED | PRIVATE | Access level |
nodeIds optional | string[] | Category node IDs |
networkIds optional | string[] | Network IDs |
blocks optional | Block[] | Content blocks |
concurrentLimit optional | number | Max concurrent bookings |
status optional | DRAFT | ACTIVE | ARCHIVED | Provider status |
Delete Provider
/v1/businesses/{businessId}/providers/{id} sdk.reservation.deleteProvider() await sdk.reservation.deleteProvider({
id: 'prv_abc123'
});
Cart (Client-Side)
The SDK provides local cart management for building booking flows.
Add to Cart
sdk.reservation.addToCart({
id: 'slot_123',
serviceId: 'svc_haircut',
providerId: 'prv_sarah',
from: 1704110400, // Unix timestamp
to: 1704112200,
timeText: '10:00 AM',
dateText: 'Jan 15, 2024'
});
Get Cart
const cart = sdk.reservation.getCart();
// Returns array of Slot objects
console.log(cart);
Remove from Cart
sdk.reservation.removeFromCart('slot_123');
Clear Cart
sdk.reservation.clearCart();
Reservations
Create Reservation
/v1/businesses/{businessId}/reservations sdk.reservation.createReservation() Create a reservation from selected slots.
const result = await sdk.reservation.createReservation({
// Any additional params
});
Get Reservation
/v1/businesses/{businessId}/reservations/{id} sdk.reservation.getReservation() const result = await sdk.reservation.getReservation({
id: 'res_xyz789'
});
console.log(result.status, result.parts, result.payment);
Search Reservations
/v1/businesses/{businessId}/reservations sdk.reservation.searchReservations() const result = await sdk.reservation.searchReservations({
query: '[email protected]',
serviceIds: ['svc_haircut'],
providerIds: ['prv_sarah'],
accountId: 'acc_customer123',
from: 1704067200, // Unix timestamp
to: 1704672000,
status: 'CONFIRMED',
sortField: 'createdAt',
sortOrder: 'desc',
cursor: null,
limit: 50
});
result.items.forEach(reservation => {
console.log(reservation.id, reservation.status);
});Parameters
| Name | Type | Description |
|---|---|---|
query optional | string | Search query |
serviceIds optional | string[] | Filter by services |
providerIds optional | string[] | Filter by providers |
accountId optional | string | Filter by customer account |
from optional | number | Start date (Unix timestamp) |
to optional | number | End date (Unix timestamp) |
status optional | string | Filter by status: CREATED, PENDING, AUTHORIZED, CONFIRMED, COMPLETED, CANCELLED, FAILED |
sortField optional | string | Sort field |
sortOrder optional | asc | desc | Sort order |
cursor optional | string | Pagination cursor |
limit optional | number | Items per page |
Update Reservation
/v1/businesses/{businessId}/reservations/{id} sdk.reservation.updateReservation() await sdk.reservation.updateReservation({
id: 'res_xyz789',
status: 'CANCELLED',
blocks: [
{
key: 'cancellation-reason',
type: 'TEXT',
content: { body: 'Customer request' }
}
],
items: [/* updated items */],
payment: null
});
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Reservation ID to update |
status required | string | Status: CREATED, PENDING, AUTHORIZED, CONFIRMED, COMPLETED, CANCELLED, FAILED |
blocks required | Block[] | Reservation content blocks |
items optional | ReservationItemPayload[] | Updated reservation items |
payment optional | Payment | null | Updated payment information |
Checkout
Get Quote
/v1/businesses/{businessId}/reservations/quote sdk.reservation.getQuote() Calculate pricing before checkout.
const quote = await sdk.reservation.getQuote({
items: [
{
serviceId: 'svc_haircut',
providerId: 'prv_sarah',
from: 1704110400,
to: 1704112200
}
],
paymentMethodId: 'pm_card_visa',
promoCode: 'FIRSTVISIT',
location: {
lat: 40.7128,
lng: -74.0060
}
});
console.log('Subtotal:', quote.subtotal);
console.log('Discount:', quote.discount);
console.log('Total:', quote.total);Parameters
| Name | Type | Description |
|---|---|---|
items required | ReservationQuoteItem[] | Items with serviceId, providerId, from, to timestamps |
paymentMethodId optional | string | Payment method for fee calculation |
promoCode optional | string | Promo code for discount |
location optional | Location | Customer location (for mobile services) |
Checkout Reservation
/v1/businesses/{businessId}/reservations/checkout sdk.reservation.checkout() Process payment for a reservation. Can use cart items or provide items directly.
// Using cart items (if cart has items)
const result = await sdk.reservation.checkout({
paymentMethodId: 'pm_card_visa',
blocks: [
{
key: 'customer-info',
type: 'FORM',
content: {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
phone: '+1234567890'
}
},
{
key: 'notes',
type: 'TEXT',
content: { body: 'First time customer' }
}
],
promoCodeId: 'promo_firstvisit',
location: {
lat: 40.7128,
lng: -74.0060
}
});
// Or provide items directly
const result = await sdk.reservation.checkout({
items: [
{
serviceId: 'svc_haircut',
providerId: 'prv_sarah',
from: 1704110400,
to: 1704112200
}
],
paymentMethodId: 'pm_card_visa',
blocks: [/* customer info blocks */]
});Parameters
| Name | Type | Description |
|---|---|---|
items optional | any[] | Reservation items (uses cart if not provided) |
paymentMethodId optional | string | Payment method from Stripe |
blocks optional | Block[] | Customer info and notes as content blocks |
promoCodeId optional | string | Applied promo code ID |
location optional | Location | Customer location |
Complete Booking Flow
async function bookAppointment() {
// 1. Get available services
const services = await sdk.reservation.getServices({
statuses: ['ACTIVE']
});
// 2. Get providers for a service
const providers = await sdk.reservation.getProviders({
serviceId: 'svc_haircut',
statuses: ['ACTIVE']
});
// 3. Get provider working time
const workingTime = await sdk.reservation.getProviderWorkingTime({
providerId: 'prv_sarah',
serviceId: 'svc_haircut'
});
// 4. User selects a slot - add to cart
sdk.reservation.addToCart({
id: 'slot_unique_id',
serviceId: 'svc_haircut',
providerId: 'prv_sarah',
from: 1704110400,
to: 1704112200,
timeText: '10:00 AM',
dateText: 'Jan 15, 2024'
});
// 5. Get quote
const quote = await sdk.reservation.getQuote({
items: sdk.reservation.getCart().map(s => ({
serviceId: s.serviceId,
providerId: s.providerId,
from: s.from,
to: s.to
})),
promoCode: 'FIRSTVISIT'
});
console.log('Total:', quote.total);
// 6. Checkout
const result = await sdk.reservation.checkout({
paymentMethodId: 'pm_card_visa',
blocks: [
{
key: 'customer',
type: 'FORM',
content: {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe'
}
}
]
});
// 7. Clear cart after successful booking
sdk.reservation.clearCart();
return result;
}
Use concurrentLimit on providers to control how many appointments they can handle simultaneously (e.g., set to 2 for group classes).