REST API Reference
Reservly exposes 7 public endpoints under /api/public/{slug}/. All GET endpoints are publicly accessible without authentication. The POST /book endpoint accepts an optional API key for higher rate limits.
Business Info
GET/api/public/{slug}/info
Returns public business profile information including name, logo, currency, timezone, enabled modules, social links, action buttons, payment providers, and cancellation policy.
Example Request
curl https://reservly.io/api/public/luxe-salon/infobash
Example Response
{
"name": "Luxe Salon",
"slug": "luxe-salon",
"logo_url": "https://cdn.reservly.io/logos/luxe-salon.png",
"currency": "USD",
"timezone": "America/New_York",
"default_language": "en",
"languages": ["en", "es"],
"modules_enabled": {
"services": true,
"events": false,
"rentals": false
},
"social_links": {
"instagram": "https://instagram.com/luxesalon"
},
"action_buttons": [
{
"type": "link",
"label": "Visit Website",
"icon": "globe",
"content": "https://luxesalon.com",
"order": 0
}
],
"has_payment_providers": true,
"payment_providers": ["stripe"],
"cancellation_policy": [
{ "hours_before": 24, "refund_percent": 100 },
{ "hours_before": 2, "refund_percent": 50 }
]
}jsonList Services
GET/api/public/{slug}/services
Returns all active services for the business, sorted by display order. Includes pricing, duration, delivery mode, and translation data.
Example Request
curl https://reservly.io/api/public/luxe-salon/servicesbash
Example Response
{
"services": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Haircut & Style",
"short_description": "Full haircut with wash and blow-dry",
"duration_minutes": 60,
"price": 75,
"currency": "USD",
"image_url": "https://cdn.reservly.io/services/haircut.jpg",
"allow_multiple": false,
"has_class_schedule": false,
"name_translations": { "es": "Corte y Peinado" },
"short_description_translations": null,
"payment_requirement": "full",
"deposit_value": null
}
],
"currency": "USD"
}jsonList Staff
GET/api/public/{slug}/staff
Returns active staff members. Optionally filter by service to get only staff qualified for a specific service.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| service_id | uuid | Optional | Filter staff to only those assigned to this service |
Example Request
curl "https://reservly.io/api/public/luxe-salon/staff?service_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890"bash
Example Response
{
"staff": [
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"name": "Maria Garcia",
"description": "Senior stylist with 10 years experience",
"category": "Stylists",
"image_url": "https://cdn.reservly.io/staff/maria.jpg",
"bio_translations": { "es": "Estilista senior con 10 anos de experiencia" }
}
]
}jsonAvailable Slots
GET/api/public/{slug}/slots
Calculates and returns available booking time slots for a given date and service. Accounts for business hours, staff schedules, existing bookings, blocked time, calendar sync events, and schedule overrides.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| date | string | Required | Date in YYYY-MM-DD format |
| service_id | uuid | Required | Service UUID. Supports comma-separated IDs for multi-service bookings. |
| staff_id | uuid | Optional | Filter slots to a specific staff member |
| is_package | string | Optional | Set to "true" when booking a package (uses any-staff matching) |
Example Request
curl "https://reservly.io/api/public/luxe-salon/slots?date=2026-04-15&service_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890"bash
Example Response
{
"slots": [
{
"time": "09:00",
"endTime": "10:00",
"staffId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"staffName": "Maria Garcia"
},
{
"time": "10:00",
"endTime": "11:00",
"staffId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"staffName": "Maria Garcia"
},
{
"time": "10:00",
"endTime": "11:00",
"staffId": "b2c3d4e5-a6b7-8901-cdef-234567890abc",
"staffName": "Alex Kim"
}
],
"timezone": "America/New_York"
}jsonRate limit: 60 requests / minute per IP
Upcoming Events
GET/api/public/{slug}/events
Returns upcoming active public events with capacity information and ticket inventory. Only events on or after today (in the business timezone) are included.
Example Request
curl https://reservly.io/api/public/luxe-salon/eventsbash
Example Response
{
"events": [
{
"id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
"name": "Summer Hair Workshop",
"short_description": "Learn the latest styling techniques",
"date": "2026-05-20",
"start_time": "14:00",
"end_time": "17:00",
"image_url": "https://cdn.reservly.io/events/workshop.jpg",
"total_capacity": 30,
"spots_remaining": 18,
"inventory": [
{
"id": "d4e5f6a7-b8c9-0123-def4-567890123456",
"name": "General Admission",
"price": 45,
"total_capacity": 20,
"spots_remaining": 12,
"name_translations": null
},
{
"id": "e5f6a7b8-c9d0-1234-ef56-789012345678",
"name": "VIP Front Row",
"price": 85,
"total_capacity": 10,
"spots_remaining": 6,
"name_translations": null
}
],
"name_translations": null,
"short_description_translations": null,
"payment_requirement": "full",
"deposit_value": null
}
],
"currency": "USD"
}jsonList Rentals
GET/api/public/{slug}/rentals
Returns active rental items with pricing, availability constraints, and upsell relationships. Supports hourly and daily rentals.
Example Request
curl https://reservly.io/api/public/luxe-salon/rentalsbash
Example Response
{
"rentals": [
{
"id": "a7b8c9d0-e1f2-3456-abcd-789012345678",
"name": "Private Styling Suite",
"short_description": "Fully equipped private suite for events",
"category": "Spaces",
"price": 150,
"price_type": "hourly",
"quantity": 2,
"image_url": "https://cdn.reservly.io/rentals/suite.jpg",
"min_rental_days": null,
"max_rental_days": null,
"min_rental_hours": 2,
"max_rental_hours": 8,
"name_translations": null,
"short_description_translations": null,
"payment_requirement": "deposit_percent",
"deposit_value": 25
}
],
"rental_upsells": [
{
"rental_id": "a7b8c9d0-e1f2-3456-abcd-789012345678",
"upsell_rental_id": "b8c9d0e1-f2a3-4567-bcde-890123456789",
"is_required": false,
"sort_order": 0
}
],
"currency": "USD"
}jsonCreate a Booking
POST/api/public/{slug}/book
Creates a new booking. The end time is calculated automatically from the combined duration of the selected services. If the business has payment providers connected and the service requires payment, the response includes payment details.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| service_ids | uuid[] | Required | Array of service UUIDs to book |
| date | string | Required | Booking date in YYYY-MM-DD format |
| time | string | Required | Start time in HH:MM format (24-hour) |
| customer_name | string | Required | Full name of the customer |
| customer_email | string | Required | Customer email address |
| staff_id | uuid | Optional | Preferred staff member UUID |
| customer_phone | string | Optional | Customer phone number |
| form_data | object | Optional | Custom form field responses |
| party_size | number | Optional | Number of guests (defaults to 1) |
| source | string | Optional | Attribution source (e.g. "vapi", "n8n", "make"). Auto-tagged as "api" if omitted and request lacks browser headers. |
| preferred_provider | string | Optional | Preferred payment provider: "stripe" or "paypal" |
Request Body
{
"service_ids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
"date": "2026-04-15",
"time": "10:00",
"customer_name": "Jane Smith",
"customer_email": "jane@example.com",
"customer_phone": "+1-555-0123",
"staff_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"source": "n8n",
"party_size": 1
}jsonExample Request
curl -X POST https://reservly.io/api/public/luxe-salon/book \
-H "Content-Type: application/json" \
-H "Authorization: Bearer rsvly_YOUR_API_KEY" \
-d '{
"service_ids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
"date": "2026-04-15",
"time": "10:00",
"customer_name": "Jane Smith",
"customer_email": "jane@example.com"
}'bashExample Response
{
"success": true,
"booking": {
"id": "e5f6a7b8-c9d0-1234-abcd-567890123456",
"date": "2026-04-15",
"start_time": "10:00",
"end_time": "11:00",
"status": "pending",
"source": "n8n",
"services": [
{
"name": "Haircut & Style",
"duration_minutes": 60,
"price": 75
}
]
}
}jsonRate limit: 10 req/min (unauthenticated) | 100 req/min (authenticated)
Common Error Codes
| Status | Meaning | Example |
|---|---|---|
| 400 | Invalid parameters | Missing required field, bad date format, invalid UUID |
| 403 | Business pending deletion | The business account is scheduled for removal and no longer accepts bookings |
| 404 | Not found | Invalid slug, service ID does not exist, or resource is inactive |
| 409 | Booking conflict | The requested time slot is already booked or no longer available |
| 429 | Rate limited | Too many requests. Retry after the period indicated in the Retry-After header. |
| 500 | Server error | An unexpected error occurred. Contact support if it persists. |