Integrate bookings, services, staff management, and availability directly into your applications. RESTful JSON API with simple bearer token authentication.
The BookOrielle API lets you programmatically manage bookings, services, staff, availability, reviews, and analytics for your business. Every request uses JSON and standard HTTP methods.
bo_live_ for production or bo_test_ for sandbox.Authorization header of every request.data field (single object or array) and a meta field for paginated lists.Every API request must include your API key in the Authorization header as a Bearer token.
curl https://bookorielle.com/api/v1/bookings \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Keep your keys secret. Never expose API keys in client side code, public repositories, or browser requests. Make all API calls from your server.
https://bookorielle.com/api/v1
All endpoints are versioned. The current (and only) version is v1. We will never introduce breaking changes within a version.
Each API key has a monthly call quota. The default is 10,000 calls per month. Every response includes headers so you can track your usage:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Your monthly call quota |
| X-RateLimit-Used | Calls used so far this month |
| X-RateLimit-Remaining | Calls remaining this month |
When the limit is exceeded, you will receive a 429 Too Many Requests response. Overage charges may apply at $5.00 per 1,000 additional calls. Contact support to increase your quota.
{
"error": {
"code": "rate_limit_exceeded",
"message": "Monthly API call limit exceeded. Resets on the 1st of the month."
}
}All list endpoints accept page and limit query parameters. The default page is 1, default limit is 25, and maximum limit is 100.
GET /api/v1/bookings?page=2&limit=10
{
"data": [ ... ],
"meta": {
"page": 2,
"limit": 10,
"total": 42
}
}All errors return a consistent JSON envelope with an error object containing code and message fields.
{
"error": {
"code": "validation_error",
"message": "service_id, start_at, customer_name, and customer_email are required"
}
}| Status | Code | What it means |
|---|---|---|
| 400 | validation_error | A required field is missing or a value is invalid. Check the message for details. |
| 401 | unauthorized | Your API key is missing, invalid, or has been revoked. |
| 404 | not_found | The resource you requested does not exist or does not belong to your business. |
| 429 | rate_limit_exceeded | You have exceeded your monthly API call quota. Wait for the next billing cycle or contact support. |
| 500 | internal_error | Something went wrong on our side. If this persists, contact support. |
Create, list, retrieve, and manage the lifecycle of customer appointments.
/api/v1/bookingsCreate a new booking for a customer. The booking is immediately confirmed. The end time is calculated automatically from the service duration.
Request body
| Parameter | Type | Description |
|---|---|---|
| service_id* | string (uuid) | The service being booked |
| start_at* | string (ISO 8601) | Appointment start time, e.g. 2026-04-10T14:00:00Z |
| customer_name* | string | Full name of the customer |
| customer_email* | string | Customer email address |
| staff_id | string (uuid) | Assign a specific staff member. Omit for any available. |
| customer_phone | string | Customer phone number, e.g. +15551234567 |
| notes | string | Special requests or internal notes |
| promo_code | string | A valid promotion code to apply a discount. The code is validated at creation time and the discount is reflected in the payment amount. Promo management is portal only and not exposed via the API. |
Example request
curl -X POST https://bookorielle.com/api/v1/bookings \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"service_id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"staff_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"start_at": "2026-04-10T14:00:00Z",
"customer_name": "Olivia Thompson",
"customer_email": "olivia.thompson@gmail.com",
"customer_phone": "+15551234567",
"notes": "First time client, prefers a natural look",
"promo_code": "SUMMER20"
}'Response (201 Created)
{
"data": {
"id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
"booking_number": "BO-X1Y2Z3W4",
"status": "confirmed",
"start_at": "2026-04-10T14:00:00.000Z",
"end_at": "2026-04-10T14:30:00.000Z",
"price_cents": 4500,
"created_at": "2026-04-03T10:15:00.000Z"
}
}/api/v1/bookingsList all bookings for your business, sorted by start time (most recent first). Filter by status and date range.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: pending, confirmed, in_progress, completed, cancelled, no_show |
| from | string (ISO 8601) | Only bookings starting on or after this date |
| to | string (ISO 8601) | Only bookings starting on or before this date |
| page | integer | Page number (default 1) |
| limit | integer | Results per page (default 25, max 100) |
Example request
curl "https://bookorielle.com/api/v1/bookings?status=confirmed&from=2026-04-01&to=2026-04-30&page=1&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
"booking_number": "BO-A1B2C3D4",
"status": "confirmed",
"source": "portal_link",
"customer": {
"name": "Olivia Thompson",
"email": "olivia.thompson@gmail.com",
"phone": "+15551234567"
},
"service": {
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure"
},
"staff": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Sarah Johnson"
},
"start_at": "2026-04-10T14:00:00.000Z",
"end_at": "2026-04-10T14:30:00.000Z",
"price_cents": 4500,
"notes": "First time client, prefers a natural look",
"created_at": "2026-04-03T10:15:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 42
}
}/api/v1/bookings/:idRetrieve full details for a single booking, including deposit, cancellation info, and timestamps.
Example request
curl https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
"booking_number": "BO-A1B2C3D4",
"status": "confirmed",
"source": "portal_link",
"customer": {
"name": "Olivia Thompson",
"email": "olivia.thompson@gmail.com",
"phone": "+15551234567"
},
"service": {
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure"
},
"staff": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Sarah Johnson"
},
"start_at": "2026-04-10T14:00:00.000Z",
"end_at": "2026-04-10T14:30:00.000Z",
"price_cents": 4500,
"deposit_cents": 0,
"notes": "First time client, prefers a natural look",
"cancelled_at": null,
"cancellation_reason": null,
"created_at": "2026-04-03T10:15:00.000Z",
"updated_at": "2026-04-03T10:15:00.000Z"
}
}/api/v1/bookings/:idUpdate a booking's status. Use this to confirm, start, complete, cancel, or mark a booking as a no show. See the status transitions table below for valid changes.
Request body
| Parameter | Type | Description |
|---|---|---|
| status* | string | New status: confirmed, in_progress, completed, cancelled, or no_show |
| cancellation_reason | string | Optional reason (only applies when status is cancelled) |
Confirm a pending booking
curl -X PATCH https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{ "status": "confirmed" }'Cancel a booking
curl -X PATCH https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"status": "cancelled",
"cancellation_reason": "Customer requested reschedule"
}'Mark as completed
curl -X PATCH https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{ "status": "completed" }'Mark as no show
curl -X PATCH https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{ "status": "no_show" }'Response (200 OK)
{
"data": {
"id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
"booking_number": "BO-A1B2C3D4",
"status": "cancelled",
"updated_at": "2026-04-03T12:00:00.000Z"
}
}Bookings follow a strict lifecycle. You can only move a booking to certain statuses depending on its current state. Attempting an invalid transition returns a 400 error.
| Current status | Can transition to |
|---|---|
| pending | confirmed, cancelled, no_show |
| confirmed | in_progress, cancelled, no_show |
| in_progress | completed, cancelled |
| completed | Terminal. No further transitions. |
| cancelled | Terminal. No further transitions. |
| no_show | Terminal. No further transitions. |
{
"error": {
"code": "validation_error",
"message": "Cannot transition from \"completed\" to \"cancelled\". Valid transitions: none (terminal status)"
}
}Manage the services your business offers. Each service has a name, duration, price, and optional category.
/api/v1/servicesList all services for your business, sorted by display order.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default 1) |
| limit | integer | Results per page (default 25, max 100) |
Example request
curl "https://bookorielle.com/api/v1/services?page=1&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure",
"description": "Nail shaping, cuticle care, and polish application",
"duration_minutes": 30,
"buffer_minutes": 10,
"price_cents": 4500,
"deposit_cents": 1000,
"category": {
"id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"name": "Nails"
},
"is_active": true,
"sort_order": 1,
"created_at": "2026-03-15T08:00:00.000Z"
},
{
"id": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9",
"name": "Gel Full Set",
"description": "Full set of gel nail extensions with your choice of color",
"duration_minutes": 75,
"buffer_minutes": 15,
"price_cents": 8500,
"deposit_cents": 2000,
"category": {
"id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"name": "Nails"
},
"is_active": true,
"sort_order": 2,
"created_at": "2026-03-15T08:05:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 8
}
}/api/v1/services/:idGet the full details of a single service.
Example request
curl https://bookorielle.com/api/v1/services/d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8 \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure",
"description": "Nail shaping, cuticle care, and polish application",
"duration_minutes": 30,
"buffer_minutes": 10,
"price_cents": 4500,
"deposit_cents": 1000,
"is_active": true,
"sort_order": 1,
"created_at": "2026-03-15T08:00:00.000Z",
"updated_at": "2026-03-20T12:00:00.000Z"
}
}/api/v1/servicesAdd a new service to your business.
Request body
| Parameter | Type | Description |
|---|---|---|
| name* | string | Service name |
| duration_minutes* | integer | How long the service takes |
| price_cents* | integer | Price in cents (e.g. 4500 for $45.00) |
| description | string | Public description for customers |
| deposit_cents | integer | Deposit amount in cents (default 0) |
| buffer_minutes | integer | Cleanup/transition time after the service (default 0) |
| category_id | string (uuid) | Category to file this service under |
Example request
curl -X POST https://bookorielle.com/api/v1/services \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"name": "Deep Conditioning Treatment",
"description": "Intensive moisture treatment for dry or damaged hair",
"duration_minutes": 45,
"price_cents": 6500,
"buffer_minutes": 10,
"category_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
}'Response (201 Created)
{
"data": {
"id": "b3c4d5e6-f7a8-4b9c-0d1e-2f3a4b5c6d7e",
"name": "Deep Conditioning Treatment",
"description": "Intensive moisture treatment for dry or damaged hair",
"duration_minutes": 45,
"buffer_minutes": 10,
"price_cents": 6500,
"deposit_cents": 0,
"category_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"is_active": true,
"sort_order": 0,
"created_at": "2026-04-03T10:30:00.000Z"
}
}/api/v1/services/:idUpdate any field on an existing service. Only include the fields you want to change.
Request body (all optional)
| Parameter | Type | Description |
|---|---|---|
| name | string | New name |
| description | string | New description |
| duration_minutes | integer | New duration |
| price_cents | integer | New price in cents |
| deposit_cents | integer | New deposit amount |
| buffer_minutes | integer | New buffer time |
| is_active | boolean | Set to false to hide the service from booking |
Example: update price
curl -X PATCH https://bookorielle.com/api/v1/services/d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{ "price_cents": 5000 }'Response (200 OK)
{
"data": {
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure",
"description": "Nail shaping, cuticle care, and polish application",
"duration_minutes": 30,
"price_cents": 5000,
"is_active": true,
"updated_at": "2026-04-03T11:00:00.000Z"
}
}/api/v1/services/:idDeactivate a service. This is a soft delete. The service will no longer appear in booking flows, but existing bookings referencing it are preserved.
Example request
curl -X DELETE https://bookorielle.com/api/v1/services/d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8 \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"deleted": true
}
}View and manage your team members. Each staff member has a role (owner, manager, staff, or front_desk) and can be assigned to specific services.
/api/v1/staffList all active staff members for your business.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default 1) |
| limit | integer | Results per page (default 25, max 100) |
Example request
curl "https://bookorielle.com/api/v1/staff" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Sarah Johnson",
"email": "sarah@marees-nails.com",
"phone": "+15559876543",
"role": "staff",
"bio": "Senior nail technician with 8 years of experience",
"avatar_url": null,
"created_at": "2026-03-15T08:00:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 5
}
}/api/v1/staff/:idGet a staff member's full profile, including the list of services they can perform.
Example request
curl https://bookorielle.com/api/v1/staff/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Sarah Johnson",
"email": "sarah@marees-nails.com",
"phone": "+15559876543",
"role": "staff",
"bio": "Senior nail technician with 8 years of experience",
"avatar_url": null,
"is_active": true,
"services": [
{
"id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"name": "Classic Manicure"
},
{
"id": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9",
"name": "Gel Full Set"
}
],
"created_at": "2026-03-15T08:00:00.000Z",
"updated_at": "2026-03-20T12:00:00.000Z"
}
}/api/v1/staff/:idUpdate a staff member's profile or reassign their services. Only include the fields you want to change.
Request body (all optional)
| Parameter | Type | Description |
|---|---|---|
| name | string | Display name |
| string | Email address | |
| phone | string | Phone number |
| role | string | One of: owner, manager, staff, front_desk |
| bio | string | Staff bio shown to customers |
| service_ids | string[] | Array of service UUIDs this staff member can perform. Replaces all current assignments. |
Example: update bio and reassign services
curl -X PATCH https://bookorielle.com/api/v1/staff/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"bio": "Lead technician specializing in gel and acrylic nails",
"service_ids": [
"d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9"
]
}'Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Sarah Johnson",
"email": "sarah@marees-nails.com",
"phone": "+15559876543",
"role": "staff",
"bio": "Lead technician specializing in gel and acrylic nails",
"avatar_url": null,
"is_active": true,
"updated_at": "2026-04-03T11:30:00.000Z"
}
}/api/v1/staff/:idDeactivate a staff member. This is a soft delete. They will no longer appear in booking flows, but their existing bookings are preserved.
Example request
curl -X DELETE https://bookorielle.com/api/v1/staff/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"deleted": true
}
}Check which time slots are open for a given date. The API considers your business hours, existing bookings, blocked time, and the service duration.
/api/v1/availabilityGet available appointment slots for a specific date. Each slot includes a start and end time in ISO 8601 format.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| date* | string (YYYY-MM-DD) | The date to check availability for |
| service_id | string (uuid) | Slot duration is based on this service. If omitted, defaults to 30 minute slots. |
| staff_id | string (uuid) | Only show slots for a specific staff member |
Example request
curl "https://bookorielle.com/api/v1/availability?date=2026-04-10&service_id=d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"date": "2026-04-10",
"service_id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"slot_duration_minutes": 30,
"slots": [
{ "start": "2026-04-10T09:00:00.000Z", "end": "2026-04-10T09:30:00.000Z" },
{ "start": "2026-04-10T09:30:00.000Z", "end": "2026-04-10T10:00:00.000Z" },
{ "start": "2026-04-10T10:00:00.000Z", "end": "2026-04-10T10:30:00.000Z" },
{ "start": "2026-04-10T11:00:00.000Z", "end": "2026-04-10T11:30:00.000Z" },
{ "start": "2026-04-10T14:00:00.000Z", "end": "2026-04-10T14:30:00.000Z" },
{ "start": "2026-04-10T14:30:00.000Z", "end": "2026-04-10T15:00:00.000Z" },
{ "start": "2026-04-10T15:00:00.000Z", "end": "2026-04-10T15:30:00.000Z" }
]
}
}Tip. To build a booking flow, first call this endpoint to show the customer available times, then use the selected slot as the start_at when creating the booking.
Response when no slots available
{
"data": {
"date": "2026-04-13",
"slots": [],
"message": "No availability for this day"
}
}View aggregated customer data derived from your bookings. Customers are identified by email, so repeat visitors are grouped together automatically.
/api/v1/clientsList all unique customers who have booked with your business, sorted by most recent visit.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default 1) |
| limit | integer | Results per page (default 25, max 100) |
Example request
curl "https://bookorielle.com/api/v1/clients?page=1&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"email": "olivia.thompson@gmail.com",
"name": "Olivia Thompson",
"phone": "+15551234567",
"total_bookings": 12,
"total_spent_cents": 54000,
"last_booking_at": "2026-04-01T14:00:00.000Z",
"first_booking_at": "2025-11-10T09:00:00.000Z"
},
{
"email": "maya.chen@outlook.com",
"name": "Maya Chen",
"phone": null,
"total_bookings": 3,
"total_spent_cents": 19500,
"last_booking_at": "2026-03-28T11:00:00.000Z",
"first_booking_at": "2026-02-14T10:00:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 150
}
}Read customer reviews left on your business. Reviews include a 1 to 5 star rating, an optional comment, and your business reply if one exists.
/api/v1/reviewsList reviews for your business. Filter by star rating or whether you have replied.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| rating | integer (1 to 5) | Only show reviews with this exact star rating |
| has_reply | string (true or false) | Filter to reviews with or without a business reply |
| sort | string | Sort order: newest (default), oldest, highest, lowest |
| page | integer | Page number (default 1) |
| limit | integer | Results per page (default 25, max 100) |
Example: get unanswered reviews, lowest first
curl "https://bookorielle.com/api/v1/reviews?has_reply=false&sort=lowest&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"id": "r1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c",
"rating": 5,
"comment": "Sarah did an amazing job on my gel nails. Will definitely be back!",
"would_recommend": true,
"customer_name": "Olivia T.",
"business_reply": null,
"business_reply_at": null,
"created_at": "2026-04-02T16:30:00.000Z"
},
{
"id": "r2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
"rating": 4,
"comment": "Great service, though I had to wait about 10 minutes past my appointment time.",
"would_recommend": true,
"customer_name": "Maya C.",
"business_reply": null,
"business_reply_at": null,
"created_at": "2026-03-30T12:00:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 24
}
}Read and update your business information, including name, contact details, address, hours, and booking settings.
/api/v1/businessRetrieve your full business profile, including operating hours and booking configuration.
Example request
curl https://bookorielle.com/api/v1/business \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
"name": "Maree's Nails",
"slug": "marees-nails",
"description": "Premium nail care in downtown Austin",
"logo_url": "https://bookorielle.com/uploads/logo-marees.png",
"cover_photo_url": null,
"address": {
"street": "742 Congress Ave",
"city": "Austin",
"state": "TX",
"zip": "78701",
"country": "US"
},
"phone": "+15125551234",
"email": "hello@marees-nails.com",
"website": "https://marees-nails.com",
"timezone": "America/Chicago",
"rating": 4.8,
"review_count": 47,
"plan": "gold",
"is_active": true,
"hours": {
"sunday": null,
"monday": { "open": "09:00", "close": "18:00" },
"tuesday": { "open": "09:00", "close": "18:00" },
"wednesday": { "open": "09:00", "close": "18:00" },
"thursday": { "open": "09:00", "close": "20:00" },
"friday": { "open": "09:00", "close": "20:00" },
"saturday": { "open": "10:00", "close": "16:00" }
},
"booking_settings": {
"min_advance_hours": 2,
"max_advance_days": 60,
"slot_interval_minutes": 15,
"auto_confirm": true
},
"created_at": "2026-03-01T08:00:00.000Z",
"updated_at": "2026-04-01T12:00:00.000Z"
}
}/api/v1/businessUpdate your business profile. Only include the fields you want to change.
Request body (all optional)
| Parameter | Type | Description |
|---|---|---|
| name | string | Business name |
| description | string | Public description |
| phone | string | Business phone number |
| website | string | Business website URL |
| address | object | Address object with street, city, state, zip, country |
Example: update description and phone
curl -X PATCH https://bookorielle.com/api/v1/business \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"description": "Award winning nail salon in the heart of downtown Austin",
"phone": "+15125559876"
}'Response (200 OK)
{
"data": {
"id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
"name": "Maree's Nails",
"description": "Award winning nail salon in the heart of downtown Austin",
"phone": "+15125559876",
"website": "https://marees-nails.com",
"address": {
"street": "742 Congress Ave",
"city": "Austin",
"state": "TX",
"zip": "78701",
"country": "US"
},
"updated_at": "2026-04-03T12:30:00.000Z"
}
}Manage retail products that can be added to appointments during checkout. Products are available on all plans.
/api/v1/productsList all products for your business, with optional filtering and pagination.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default 1) |
| limit | integer | Items per page, 1 to 100 (default 25) |
| category | string | Filter by category name (case insensitive) |
| active | boolean | Filter by active status. Defaults to true. |
Example request
curl "https://bookorielle.com/api/v1/products?category=hair+care&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": [
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Hydrating Leave In Conditioner",
"description": "Lightweight formula for all hair types",
"price_cents": 2400,
"category": "Hair Care",
"sku": "HC-LIC-001",
"inventory_count": 42,
"is_active": true,
"sort_order": 1,
"image_url": "https://example.com/product.jpg",
"created_at": "2026-04-01T10:00:00.000Z",
"updated_at": "2026-04-01T10:00:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 1
}
}/api/v1/productsAdd a new product to your catalog.
Request body
| Parameter | Type | Description |
|---|---|---|
| name* | string | Product name |
| price_cents* | integer | Price in cents (e.g. 2400 = $24.00) |
| description | string | Short product description |
| category | string | Free text category (e.g. Hair Care, Skincare) |
| sku | string | Stock keeping unit identifier |
| inventory_count | integer | null | Quantity in stock. Null means unlimited (no tracking). |
| image_url | string | URL to a product image |
| sort_order | integer | Display order in the catalog (lower is first) |
Example request
curl -X POST https://bookorielle.com/api/v1/products \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"name": "Hydrating Leave In Conditioner",
"price_cents": 2400,
"category": "Hair Care",
"sku": "HC-LIC-001",
"inventory_count": 50
}'Response (201 Created)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Hydrating Leave In Conditioner",
"description": null,
"price_cents": 2400,
"category": "Hair Care",
"sku": "HC-LIC-001",
"inventory_count": 50,
"is_active": true,
"sort_order": 0,
"image_url": null,
"created_at": "2026-04-03T15:00:00.000Z",
"updated_at": "2026-04-03T15:00:00.000Z"
}
}/api/v1/products/:idRetrieve a single product by ID.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string (uuid) | Product ID |
Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Hydrating Leave In Conditioner",
"description": "Lightweight formula for all hair types",
"price_cents": 2400,
"category": "Hair Care",
"sku": "HC-LIC-001",
"inventory_count": 42,
"is_active": true,
"sort_order": 1,
"image_url": "https://example.com/product.jpg",
"created_at": "2026-04-01T10:00:00.000Z",
"updated_at": "2026-04-01T10:00:00.000Z"
}
}Error codes
| Parameter | Type | Description |
|---|---|---|
| 404 | not_found | Product does not exist or does not belong to your business |
/api/v1/products/:idUpdate one or more fields on an existing product. Only include the fields you want to change.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string (uuid) | Product ID |
Request body (all fields optional)
| Parameter | Type | Description |
|---|---|---|
| name | string | Updated product name |
| price_cents | integer | Updated price in cents |
| description | string | Updated description |
| category | string | Updated category |
| sku | string | Updated SKU |
| inventory_count | integer | null | Updated stock count. Set to null to disable tracking. |
| is_active | boolean | Set to false to hide the product from the catalog |
Example request
curl -X PATCH https://bookorielle.com/api/v1/products/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"price_cents": 2200,
"inventory_count": 35
}'Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Hydrating Leave In Conditioner",
"description": "Lightweight formula for all hair types",
"price_cents": 2200,
"category": "Hair Care",
"sku": "HC-LIC-001",
"inventory_count": 35,
"is_active": true,
"sort_order": 1,
"image_url": "https://example.com/product.jpg",
"created_at": "2026-04-01T10:00:00.000Z",
"updated_at": "2026-04-03T16:00:00.000Z"
}
}Error codes
| Parameter | Type | Description |
|---|---|---|
| 400 | validation_error | Invalid field value (e.g. negative price) |
| 404 | not_found | Product does not exist or does not belong to your business |
/api/v1/products/:idDeactivate a product. The product is not permanently deleted. It is hidden from the catalog and can be reactivated later via PATCH.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string (uuid) | Product ID |
Example request
curl -X DELETE https://bookorielle.com/api/v1/products/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"is_active": false,
"deactivated_at": "2026-04-03T17:00:00.000Z"
}
}Error codes
| Parameter | Type | Description |
|---|---|---|
| 404 | not_found | Product does not exist or does not belong to your business |
Checkout and close out are handled through the portal UI. When a business completes an appointment, they can add products, tips, and discounts before charging the balance. Line items for completed bookings are readable via the Bookings API.
/api/v1/bookings/:idAfter checkout, the booking response includes a line_items array with every charge for that appointment.
Line item fields
| Parameter | Type | Description |
|---|---|---|
| type | string | One of: service, product, addon_service, tip, discount |
| name | string | Display name for the charge |
| price_cents | integer | Unit price in cents |
| quantity | integer | Number of units |
| product_id | string | null | If the line item is a product, the product ID |
Example response (completed booking with products)
{
"data": {
"id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
"booking_number": "BO-X1Y2Z3W4",
"status": "completed",
"total_charged_cents": 7900,
"tip_cents": 1000,
"line_items": [
{
"type": "service",
"name": "Classic Manicure",
"price_cents": 4500,
"quantity": 1,
"product_id": null
},
{
"type": "product",
"name": "Hydrating Leave In Conditioner",
"price_cents": 2400,
"quantity": 1,
"product_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
},
{
"type": "tip",
"name": "Tip",
"price_cents": 1000,
"quantity": 1,
"product_id": null
}
]
}
}Get a snapshot of your business performance including booking counts, revenue, average rating, top services, and busiest days.
/api/v1/analyticsRetrieve analytics data for your business over a selected time period.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| period | string | Time window: 7d, 30d (default), 90d, or all |
Example request
curl "https://bookorielle.com/api/v1/analytics?period=30d" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
Response (200 OK)
{
"data": {
"period": "30d",
"total_bookings": 127,
"total_revenue_cents": 571500,
"bookings_this_month": 42,
"revenue_this_month_cents": 189000,
"avg_rating": 4.8,
"total_reviews": 47,
"top_services": [
{
"service_id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"service_name": "Classic Manicure",
"booking_count": 38,
"revenue_cents": 171000
},
{
"service_id": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9",
"service_name": "Gel Full Set",
"booking_count": 25,
"revenue_cents": 212500
}
],
"busy_days": [
{ "day": "Saturday", "booking_count": 32 },
{ "day": "Friday", "booking_count": 28 },
{ "day": "Thursday", "booking_count": 24 }
]
}
}Complete working examples for the most common API actions in cURL, JavaScript, and Python.
curl -X POST https://bookorielle.com/api/v1/bookings \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"service_id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"start_at": "2026-04-10T14:00:00Z",
"customer_name": "Olivia Thompson",
"customer_email": "olivia.thompson@gmail.com",
"customer_phone": "+15551234567"
}'const API_KEY = process.env.BOOKORIELLE_API_KEY;
const BASE = "https://bookorielle.com/api/v1";
const response = await fetch(`${BASE}/bookings`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
service_id: "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
start_at: "2026-04-10T14:00:00Z",
customer_name: "Olivia Thompson",
customer_email: "olivia.thompson@gmail.com",
customer_phone: "+15551234567",
}),
});
const { data } = await response.json();
console.log(`Booking created: ${data.booking_number}`);import os
import requests
API_KEY = os.environ["BOOKORIELLE_API_KEY"]
BASE = "https://bookorielle.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.post(
f"{BASE}/bookings",
json={
"service_id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
"start_at": "2026-04-10T14:00:00Z",
"customer_name": "Olivia Thompson",
"customer_email": "olivia.thompson@gmail.com",
"customer_phone": "+15551234567",
},
headers=headers,
)
data = response.json()["data"]
print(f"Booking created: {data['booking_number']}")curl "https://bookorielle.com/api/v1/bookings?status=confirmed&from=2026-04-01&limit=10" \ -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
const API_KEY = process.env.BOOKORIELLE_API_KEY;
const BASE = "https://bookorielle.com/api/v1";
const params = new URLSearchParams({
status: "confirmed",
from: "2026-04-01",
limit: "10",
});
const response = await fetch(`${BASE}/bookings?${params}`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const { data, meta } = await response.json();
console.log(`Found ${meta.total} confirmed bookings`);
for (const booking of data) {
console.log(` ${booking.booking_number} - ${booking.customer.name} at ${booking.start_at}`);
}import os
import requests
API_KEY = os.environ["BOOKORIELLE_API_KEY"]
BASE = "https://bookorielle.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.get(
f"{BASE}/bookings",
params={"status": "confirmed", "from": "2026-04-01", "limit": 10},
headers=headers,
)
result = response.json()
print(f"Found {result['meta']['total']} confirmed bookings")
for booking in result["data"]:
print(f" {booking['booking_number']} - {booking['customer']['name']} at {booking['start_at']}")curl -X PATCH https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
-H "Authorization: Bearer bo_live_abc123def456ghi789jkl012" \
-H "Content-Type: application/json" \
-d '{
"status": "cancelled",
"cancellation_reason": "Customer requested reschedule"
}'const API_KEY = process.env.BOOKORIELLE_API_KEY;
const BASE = "https://bookorielle.com/api/v1";
const bookingId = "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1";
const response = await fetch(`${BASE}/bookings/${bookingId}`, {
method: "PATCH",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "cancelled",
cancellation_reason: "Customer requested reschedule",
}),
});
const { data } = await response.json();
console.log(`Booking ${data.booking_number} cancelled`);import os
import requests
API_KEY = os.environ["BOOKORIELLE_API_KEY"]
BASE = "https://bookorielle.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
booking_id = "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1"
response = requests.patch(
f"{BASE}/bookings/{booking_id}",
json={
"status": "cancelled",
"cancellation_reason": "Customer requested reschedule",
},
headers=headers,
)
data = response.json()["data"]
print(f"Booking {data['booking_number']} cancelled")const API_KEY = process.env.BOOKORIELLE_API_KEY;
const BASE = "https://bookorielle.com/api/v1";
const headers = {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
};
// Step 1: List services to find the one we want
const servicesRes = await fetch(`${BASE}/services`, { headers });
const { data: services } = await servicesRes.json();
const manicure = services.find((s) => s.name === "Classic Manicure");
// Step 2: Check availability for next Thursday
const availRes = await fetch(
`${BASE}/availability?date=2026-04-10&service_id=${manicure.id}`,
{ headers }
);
const { data: avail } = await availRes.json();
if (avail.slots.length === 0) {
console.log("No slots available for that day.");
} else {
// Step 3: Book the first available slot
const slot = avail.slots[0];
const bookRes = await fetch(`${BASE}/bookings`, {
method: "POST",
headers,
body: JSON.stringify({
service_id: manicure.id,
start_at: slot.start,
customer_name: "Olivia Thompson",
customer_email: "olivia.thompson@gmail.com",
}),
});
const { data: booking } = await bookRes.json();
console.log(`Booked ${manicure.name} at ${slot.start}`);
console.log(`Confirmation: ${booking.booking_number}`);
}import os
import requests
API_KEY = os.environ["BOOKORIELLE_API_KEY"]
BASE = "https://bookorielle.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Step 1: List services
services = requests.get(f"{BASE}/services", headers=headers).json()["data"]
manicure = next(s for s in services if s["name"] == "Classic Manicure")
# Step 2: Check availability
avail = requests.get(
f"{BASE}/availability",
params={"date": "2026-04-10", "service_id": manicure["id"]},
headers=headers,
).json()["data"]
if not avail["slots"]:
print("No slots available for that day.")
else:
# Step 3: Book the first available slot
slot = avail["slots"][0]
booking = requests.post(
f"{BASE}/bookings",
json={
"service_id": manicure["id"],
"start_at": slot["start"],
"customer_name": "Olivia Thompson",
"customer_email": "olivia.thompson@gmail.com",
},
headers=headers,
).json()["data"]
print(f"Booked {manicure['name']} at {slot['start']}")
print(f"Confirmation: {booking['booking_number']}")