Scheduling API
Manage provider availability, working hours, blockouts, rooms, and equipment.
Overview
The Scheduling API enables complete control over when and where services can be performed. It includes:
- Provider Schedules — Weekly working hours
- Blockouts — Time off, meetings, breaks
- Holidays — Center-wide closures
- Rooms — Treatment room management
- Equipment — Device/equipment scheduling
Provider Schedules
Data Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
provider_id | UUID | Provider this schedule belongs to |
day_of_week | Integer | 0 (Sunday) to 6 (Saturday) |
start_time | Time | Shift start (HH:MM:SS) |
end_time | Time | Shift end (HH:MM:SS) |
is_active | Boolean | Whether schedule is active |
effective_from | Date | When schedule takes effect |
effective_to | Date | When schedule ends (null = ongoing) |
Get Provider Schedule
import { getProviderSchedule } from '@/lib/actions/scheduling'
const result = await getProviderSchedule('provider-uuid')
// Returns array of schedule entries
[
{ day_of_week: 1, start_time: '09:00:00', end_time: '17:00:00' }, // Monday
{ day_of_week: 2, start_time: '09:00:00', end_time: '17:00:00' }, // Tuesday
// ...
]Update Provider Schedule
Set a provider's weekly schedule (replaces existing).
import { bulkUpdateProviderSchedule } from '@/lib/actions/scheduling'
const result = await bulkUpdateProviderSchedule('provider-uuid', [
{ day_of_week: 1, start_time: '09:00', end_time: '17:00', is_active: true },
{ day_of_week: 2, start_time: '09:00', end_time: '17:00', is_active: true },
{ day_of_week: 3, start_time: '09:00', end_time: '17:00', is_active: true },
{ day_of_week: 4, start_time: '09:00', end_time: '17:00', is_active: true },
{ day_of_week: 5, start_time: '09:00', end_time: '15:00', is_active: true },
{ day_of_week: 6, start_time: '00:00', end_time: '00:00', is_active: false }, // Off
{ day_of_week: 0, start_time: '00:00', end_time: '00:00', is_active: false }, // Off
])Provider Blockouts
Data Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
provider_id | UUID | Provider this blockout belongs to |
start_time | DateTime | Block start |
end_time | DateTime | Block end |
reason | String | Optional description |
blockout_type | Enum | Type of blockout |
is_recurring | Boolean | Whether this repeats |
recurrence_pattern | JSON | Recurrence rules |
Blockout Types
| Type | Description |
|---|---|
personal | Personal time off |
vacation | Vacation/PTO |
sick | Sick leave |
meeting | Team/staff meeting |
lunch | Lunch break |
training | Training session |
other | Other reason |
Get Blockouts
import { getProviderBlockouts } from '@/lib/actions/scheduling'
const result = await getProviderBlockouts(
'provider-uuid',
'2026-02-01', // start date
'2026-02-28' // end date
)Create Blockout
import { createBlockout } from '@/lib/actions/scheduling'
// Single blockout
const result = await createBlockout({
provider_id: 'provider-uuid',
start_time: '2026-02-15T12:00:00Z',
end_time: '2026-02-15T13:00:00Z',
reason: 'Lunch',
blockout_type: 'lunch'
})
// Recurring blockout (e.g., daily lunch)
const recurring = await createBlockout({
provider_id: 'provider-uuid',
start_time: '2026-02-01T12:00:00Z',
end_time: '2026-02-01T13:00:00Z',
reason: 'Daily lunch break',
blockout_type: 'lunch',
is_recurring: true,
recurrence_pattern: {
frequency: 'weekly',
interval: 1,
days: [1, 2, 3, 4, 5], // Mon-Fri
until: '2026-12-31'
}
})Delete Blockout
import { deleteBlockout } from '@/lib/actions/scheduling'
const result = await deleteBlockout('blockout-uuid')Availability Checking
Check Provider Availability
import { checkProviderAvailability } from '@/lib/actions/scheduling'
const result = await checkProviderAvailability(
'provider-uuid',
'2026-02-15T10:00:00Z',
'2026-02-15T11:00:00Z',
'exclude-appointment-uuid' // optional: exclude when editing
)
// result.isAvailable: booleanChecks:
- Provider has a schedule for this day
- Time is within working hours
- No conflicting blockouts
- No conflicting appointments
- Center is not closed (holiday)
Get Available Slots
Get all bookable time slots for a provider.
import { getAvailableSlots } from '@/lib/actions/scheduling'
const result = await getAvailableSlots(
'provider-uuid',
'2026-02-15', // date
60, // duration (minutes)
15 // slot interval (optional)
)
// Returns
[
{ slot_start: '2026-02-15T09:00:00Z', slot_end: '2026-02-15T10:00:00Z' },
{ slot_start: '2026-02-15T09:15:00Z', slot_end: '2026-02-15T10:15:00Z' },
// ... all available slots
]MedSpa Holidays
Get Holidays
import { getHolidays } from '@/lib/actions/scheduling'
const result = await getHolidays(2026) // yearCreate Holiday
import { createHoliday } from '@/lib/actions/scheduling'
// Full day closure
const result = await createHoliday({
date: '2026-12-25',
name: 'Christmas Day',
is_full_day: true
})
// Partial day closure
const partial = await createHoliday({
date: '2026-12-24',
name: 'Christmas Eve (Early Close)',
is_full_day: false,
start_time: '14:00',
end_time: '23:59'
})Delete Holiday
import { deleteHoliday } from '@/lib/actions/scheduling'
const result = await deleteHoliday('holiday-uuid')Rooms
Data Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
name | String | Room name |
description | String | Optional description |
capacity | Integer | Max occupancy |
is_active | Boolean | Available for booking |
sort_order | Integer | Display order |
Get Rooms
import { getRooms } from '@/lib/actions/scheduling'
const result = await getRooms()Create Room
import { createRoom } from '@/lib/actions/scheduling'
const result = await createRoom({
name: 'Treatment Room A',
description: 'Main injectable room',
capacity: 1
})Check Room Availability
import { checkRoomAvailability } from '@/lib/actions/scheduling'
const result = await checkRoomAvailability(
'room-uuid',
'2026-02-15T10:00:00Z',
'2026-02-15T11:00:00Z'
)Equipment
Data Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
name | String | Equipment name |
description | String | Optional description |
serial_number | String | Serial number |
model | String | Model number |
manufacturer | String | Manufacturer |
purchase_date | Date | When purchased |
warranty_expires | Date | Warranty expiration |
is_active | Boolean | Available for use |
Get Equipment
import { getEquipment } from '@/lib/actions/scheduling'
const result = await getEquipment()Create Equipment
import { createEquipment } from '@/lib/actions/scheduling'
const result = await createEquipment({
name: 'CoolSculpting Elite',
description: 'Body contouring device',
serial_number: 'CSE-2026-001',
model: 'Elite 2.0',
manufacturer: 'Allergan',
purchase_date: '2026-01-15',
warranty_expires: '2028-01-15'
})Check Equipment Availability
import { checkEquipmentAvailability } from '@/lib/actions/scheduling'
const result = await checkEquipmentAvailability(
'equipment-uuid',
'2026-02-15T10:00:00Z',
'2026-02-15T12:00:00Z'
)Service Resources
Link services to required rooms or equipment.
// When a service requires specific resources, appointments will
// automatically check for resource availability.
// Example: Laser treatment requires the laser room and laser device
// This is configured in service_resources tableBest Practices
- Set schedules before accepting bookings — Providers without schedules show as unavailable
- Use blockouts for recurring events — Lunch breaks, meetings, etc.
- Plan holidays in advance — Add them at the start of the year
- Track equipment warranties — Set up reminders before expiration
- Consider buffer time — Account for room turnover between appointments