Developer APIv1

Build with BookOrielle

Integrate bookings, services, staff management, and availability directly into your applications. RESTful JSON API with simple bearer token authentication.

Getting Started

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.

  1. Generate an API key from your Partner Portal. Keys start with bo_live_ for production or bo_test_ for sandbox.
  2. Send it in the Authorization header of every request.
  3. All responses return JSON with a data field (single object or array) and a meta field for paginated lists.

Authentication

Every API request must include your API key in the Authorization header as a Bearer token.

Example request
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.

Base URL

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.

Rate Limits

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:

HeaderDescription
X-RateLimit-LimitYour monthly call quota
X-RateLimit-UsedCalls used so far this month
X-RateLimit-RemainingCalls 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.

429 response body
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Monthly API call limit exceeded. Resets on the 1st of the month."
  }
}

Pagination

All list endpoints accept page and limit query parameters. The default page is 1, default limit is 25, and maximum limit is 100.

Paginated request and response
GET /api/v1/bookings?page=2&limit=10

{
  "data": [ ... ],
  "meta": {
    "page": 2,
    "limit": 10,
    "total": 42
  }
}

Errors

All errors return a consistent JSON envelope with an error object containing code and message fields.

Error response shape
{
  "error": {
    "code": "validation_error",
    "message": "service_id, start_at, customer_name, and customer_email are required"
  }
}
StatusCodeWhat it means
400validation_errorA required field is missing or a value is invalid. Check the message for details.
401unauthorizedYour API key is missing, invalid, or has been revoked.
404not_foundThe resource you requested does not exist or does not belong to your business.
429rate_limit_exceededYou have exceeded your monthly API call quota. Wait for the next billing cycle or contact support.
500internal_errorSomething went wrong on our side. If this persists, contact support.

Bookings

Create, list, retrieve, and manage the lifecycle of customer appointments.

POST/api/v1/bookings

Create a new booking for a customer. The booking is immediately confirmed. The end time is calculated automatically from the service duration.

Request body

ParameterTypeDescription
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*stringFull name of the customer
customer_email*stringCustomer email address
staff_idstring (uuid)Assign a specific staff member. Omit for any available.
customer_phonestringCustomer phone number, e.g. +15551234567
notesstringSpecial requests or internal notes
promo_codestringA 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
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)

JSON
{
  "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"
  }
}
GET/api/v1/bookings

List all bookings for your business, sorted by start time (most recent first). Filter by status and date range.

Query parameters

ParameterTypeDescription
statusstringFilter by status: pending, confirmed, in_progress, completed, cancelled, no_show
fromstring (ISO 8601)Only bookings starting on or after this date
tostring (ISO 8601)Only bookings starting on or before this date
pageintegerPage number (default 1)
limitintegerResults per page (default 25, max 100)

Example request

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

JSON
{
  "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
  }
}
GET/api/v1/bookings/:id

Retrieve full details for a single booking, including deposit, cancellation info, and timestamps.

Example request

cURL
curl https://bookorielle.com/api/v1/bookings/f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1 \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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"
  }
}
PATCH/api/v1/bookings/:id

Update 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

ParameterTypeDescription
status*stringNew status: confirmed, in_progress, completed, cancelled, or no_show
cancellation_reasonstringOptional reason (only applies when status is cancelled)

Confirm a pending booking

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

JSON
{
  "data": {
    "id": "f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1",
    "booking_number": "BO-A1B2C3D4",
    "status": "cancelled",
    "updated_at": "2026-04-03T12:00:00.000Z"
  }
}

Booking Status Transitions

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 statusCan transition to
pendingconfirmed, cancelled, no_show
confirmedin_progress, cancelled, no_show
in_progresscompleted, cancelled
completedTerminal. No further transitions.
cancelledTerminal. No further transitions.
no_showTerminal. No further transitions.
Invalid transition error
{
  "error": {
    "code": "validation_error",
    "message": "Cannot transition from \"completed\" to \"cancelled\". Valid transitions: none (terminal status)"
  }
}

Services

Manage the services your business offers. Each service has a name, duration, price, and optional category.

GET/api/v1/services

List all services for your business, sorted by display order.

Query parameters

ParameterTypeDescription
pageintegerPage number (default 1)
limitintegerResults per page (default 25, max 100)

Example request

cURL
curl "https://bookorielle.com/api/v1/services?page=1&limit=10" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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
  }
}
GET/api/v1/services/:id

Get the full details of a single service.

Example request

cURL
curl https://bookorielle.com/api/v1/services/d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8 \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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"
  }
}
POST/api/v1/services

Add a new service to your business.

Request body

ParameterTypeDescription
name*stringService name
duration_minutes*integerHow long the service takes
price_cents*integerPrice in cents (e.g. 4500 for $45.00)
descriptionstringPublic description for customers
deposit_centsintegerDeposit amount in cents (default 0)
buffer_minutesintegerCleanup/transition time after the service (default 0)
category_idstring (uuid)Category to file this service under

Example request

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

JSON
{
  "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"
  }
}
PATCH/api/v1/services/:id

Update any field on an existing service. Only include the fields you want to change.

Request body (all optional)

ParameterTypeDescription
namestringNew name
descriptionstringNew description
duration_minutesintegerNew duration
price_centsintegerNew price in cents
deposit_centsintegerNew deposit amount
buffer_minutesintegerNew buffer time
is_activebooleanSet to false to hide the service from booking

Example: update price

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

JSON
{
  "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"
  }
}
DELETE/api/v1/services/:id

Deactivate 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
curl -X DELETE https://bookorielle.com/api/v1/services/d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8 \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "data": {
    "id": "d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8",
    "deleted": true
  }
}

Staff

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.

GET/api/v1/staff

List all active staff members for your business.

Query parameters

ParameterTypeDescription
pageintegerPage number (default 1)
limitintegerResults per page (default 25, max 100)

Example request

cURL
curl "https://bookorielle.com/api/v1/staff" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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
  }
}
GET/api/v1/staff/:id

Get a staff member's full profile, including the list of services they can perform.

Example request

cURL
curl https://bookorielle.com/api/v1/staff/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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"
  }
}
PATCH/api/v1/staff/:id

Update a staff member's profile or reassign their services. Only include the fields you want to change.

Request body (all optional)

ParameterTypeDescription
namestringDisplay name
emailstringEmail address
phonestringPhone number
rolestringOne of: owner, manager, staff, front_desk
biostringStaff bio shown to customers
service_idsstring[]Array of service UUIDs this staff member can perform. Replaces all current assignments.

Example: update bio and reassign services

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

JSON
{
  "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"
  }
}
DELETE/api/v1/staff/:id

Deactivate 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
curl -X DELETE https://bookorielle.com/api/v1/staff/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "data": {
    "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "deleted": true
  }
}

Availability

Check which time slots are open for a given date. The API considers your business hours, existing bookings, blocked time, and the service duration.

GET/api/v1/availability

Get available appointment slots for a specific date. Each slot includes a start and end time in ISO 8601 format.

Query parameters

ParameterTypeDescription
date*string (YYYY-MM-DD)The date to check availability for
service_idstring (uuid)Slot duration is based on this service. If omitted, defaults to 30 minute slots.
staff_idstring (uuid)Only show slots for a specific staff member

Example request

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

JSON
{
  "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

JSON
{
  "data": {
    "date": "2026-04-13",
    "slots": [],
    "message": "No availability for this day"
  }
}

Clients

View aggregated customer data derived from your bookings. Customers are identified by email, so repeat visitors are grouped together automatically.

GET/api/v1/clients

List all unique customers who have booked with your business, sorted by most recent visit.

Query parameters

ParameterTypeDescription
pageintegerPage number (default 1)
limitintegerResults per page (default 25, max 100)

Example request

cURL
curl "https://bookorielle.com/api/v1/clients?page=1&limit=10" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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
  }
}

Reviews

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.

GET/api/v1/reviews

List reviews for your business. Filter by star rating or whether you have replied.

Query parameters

ParameterTypeDescription
ratinginteger (1 to 5)Only show reviews with this exact star rating
has_replystring (true or false)Filter to reviews with or without a business reply
sortstringSort order: newest (default), oldest, highest, lowest
pageintegerPage number (default 1)
limitintegerResults per page (default 25, max 100)

Example: get unanswered reviews, lowest first

cURL
curl "https://bookorielle.com/api/v1/reviews?has_reply=false&sort=lowest&limit=10" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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
  }
}

Business Profile

Read and update your business information, including name, contact details, address, hours, and booking settings.

GET/api/v1/business

Retrieve your full business profile, including operating hours and booking configuration.

Example request

cURL
curl https://bookorielle.com/api/v1/business \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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"
  }
}
PATCH/api/v1/business

Update your business profile. Only include the fields you want to change.

Request body (all optional)

ParameterTypeDescription
namestringBusiness name
descriptionstringPublic description
phonestringBusiness phone number
websitestringBusiness website URL
addressobjectAddress object with street, city, state, zip, country

Example: update description and phone

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

JSON
{
  "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"
  }
}

Products

Manage retail products that can be added to appointments during checkout. Products are available on all plans.

GET/api/v1/products

List all products for your business, with optional filtering and pagination.

Query parameters

ParameterTypeDescription
pageintegerPage number (default 1)
limitintegerItems per page, 1 to 100 (default 25)
categorystringFilter by category name (case insensitive)
activebooleanFilter by active status. Defaults to true.

Example request

cURL
curl "https://bookorielle.com/api/v1/products?category=hair+care&limit=10" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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
  }
}
POST/api/v1/products

Add a new product to your catalog.

Request body

ParameterTypeDescription
name*stringProduct name
price_cents*integerPrice in cents (e.g. 2400 = $24.00)
descriptionstringShort product description
categorystringFree text category (e.g. Hair Care, Skincare)
skustringStock keeping unit identifier
inventory_countinteger | nullQuantity in stock. Null means unlimited (no tracking).
image_urlstringURL to a product image
sort_orderintegerDisplay order in the catalog (lower is first)

Example request

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

JSON
{
  "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"
  }
}
GET/api/v1/products/:id

Retrieve a single product by ID.

Path parameters

ParameterTypeDescription
id*string (uuid)Product ID

Response (200 OK)

JSON
{
  "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

ParameterTypeDescription
404not_foundProduct does not exist or does not belong to your business
PATCH/api/v1/products/:id

Update one or more fields on an existing product. Only include the fields you want to change.

Path parameters

ParameterTypeDescription
id*string (uuid)Product ID

Request body (all fields optional)

ParameterTypeDescription
namestringUpdated product name
price_centsintegerUpdated price in cents
descriptionstringUpdated description
categorystringUpdated category
skustringUpdated SKU
inventory_countinteger | nullUpdated stock count. Set to null to disable tracking.
is_activebooleanSet to false to hide the product from the catalog

Example request

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

JSON
{
  "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

ParameterTypeDescription
400validation_errorInvalid field value (e.g. negative price)
404not_foundProduct does not exist or does not belong to your business
DELETE/api/v1/products/:id

Deactivate a product. The product is not permanently deleted. It is hidden from the catalog and can be reactivated later via PATCH.

Path parameters

ParameterTypeDescription
id*string (uuid)Product ID

Example request

cURL
curl -X DELETE https://bookorielle.com/api/v1/products/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "data": {
    "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "is_active": false,
    "deactivated_at": "2026-04-03T17:00:00.000Z"
  }
}

Error codes

ParameterTypeDescription
404not_foundProduct does not exist or does not belong to your business

Checkout

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.

GET/api/v1/bookings/:id

After checkout, the booking response includes a line_items array with every charge for that appointment.

Line item fields

ParameterTypeDescription
typestringOne of: service, product, addon_service, tip, discount
namestringDisplay name for the charge
price_centsintegerUnit price in cents
quantityintegerNumber of units
product_idstring | nullIf the line item is a product, the product ID

Example response (completed booking with products)

JSON
{
  "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
      }
    ]
  }
}

Analytics

Get a snapshot of your business performance including booking counts, revenue, average rating, top services, and busiest days.

GET/api/v1/analytics

Retrieve analytics data for your business over a selected time period.

Query parameters

ParameterTypeDescription
periodstringTime window: 7d, 30d (default), 90d, or all

Example request

cURL
curl "https://bookorielle.com/api/v1/analytics?period=30d" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"

Response (200 OK)

JSON
{
  "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 }
    ]
  }
}

Code Examples

Complete working examples for the most common API actions in cURL, JavaScript, and Python.

Create a booking

cURL
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"
  }'
JavaScript (fetch)
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}`);
Python (requests)
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']}")

List bookings with filters

cURL
curl "https://bookorielle.com/api/v1/bookings?status=confirmed&from=2026-04-01&limit=10" \
  -H "Authorization: Bearer bo_live_abc123def456ghi789jkl012"
JavaScript (fetch)
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}`);
}
Python (requests)
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']}")

Cancel a booking

cURL
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"
  }'
JavaScript (fetch)
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`);
Python (requests)
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")

Full workflow: check availability, then book

JavaScript (fetch)
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}`);
}
Python (requests)
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']}")