Booking Flow

Appointments

An Appointment represents a booking of an AppointmentType.

The Appointment object

Attributes

  • idobject-idrequired

    The ID of the appointment.

  • appointment_type_idobject-idrequired

    The ID of the appointment type.

  • appointment_type_namestringrequired

    The name of the appointment type.

  • currencyoptional
  • customer_idobject-idrequired

    The ID of the customer this appointment is for.

  • durationintegerrequired

    The duration of the appointment in minutes.

  • emailstringrequired

    The email address of the customer.

  • end_bufferintegerrequired

    The number of minutes blocked out at the end of the appointment for cleaning or changeover.

  • end_timedate-timerequired

    The end time this appointment is for.

  • first_namestringrequired

    The first name of the customer.

  • full_namestringoptional

    The full name of the customer.

  • guestsobject[]required
  • has_notesbooleanrequired

    Whether the appointment belongs to an order that has notes.

  • Whether the appointment belongs to an order that has an outstanding balance.

  • has_special_requestsbooleanrequired

    Whether the appointment belongs to an order that has special requests.

  • is_group_bookingbooleanrequired

    Whether the appointment belongs to an order that has multiple guests.

  • is_hotel_room_bookingbooleanoptional

    Whether the appointment belongs to an order that is associated with a hotel room.

  • is_lockedbooleanoptional

    Whether the appointment is locked and should not be moved.

  • is_part_of_packagebooleanrequired

    Whether the appointment was sold as part of a package

  • last_namestringrequired

    The last name of the customer.

  • net_totalintegerrequired

    The net total of the appointment.

  • order_idobject-idrequired

    The ID of the order associated with this appointment.

  • order_is_lockedbooleanrequired

    Whether the order is locked

  • order_item_idobject-idrequired

    The ID of the order item associated with this appointment.

  • order_labelsobject[]required
  • order_locked_atdate-timeoptional

    The date the order was locked at

  • order_refstringrequired

    The order reference associated with this appointment.

  • organisation_iduuidrequired

    The ID of the organisation the appointment belongs to.

  • package_product_codestringoptional

    The product code for the package.

  • phonestringrequired

    The customer's phone number.

  • practitioner_idsstring[]required

    The IDs of the practitioners this appointment assigned to.

  • practitionersobject[]required
  • product_codestringrequirednullable

    A custom product code for the product.

  • roomobjectrequired

    The summary of a Room object

  • room_idobject-idrequired

    The ID of the room this appointment assigned to.

  • site_iduuidrequired

    The ID of the site the appointment belongs to.

  • stagestringrequired

    The current stage of the order the appointment belongs to.

    Possible values:arrivedchecked_outin_treatmentnot_arrived
  • start_timedate-timerequired

    The start time this appointment is for.

  • statusstringrequired

    The status of the appointment.

    Possible values:confirmedin_progressnew
  • submitted_atdate-timerequired

    The date and time the appointment was submitted.

  • total_costintegerrequired

    The total cost of the appointment.

  • created_atdate-timerequired

    When then resource was created.

  • updated_atrequired
{
  "id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "appointment_type_id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "appointment_type_name": "60 minute massage",
  "currency": "GBP",
  "customer_id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "duration": 60,
  "email": "janedoe@example.com",
  "end_buffer": 15,
  "end_time": "2019-01-15T13:00:00+01:00",
  "first_name": "Jane",
  "full_name": "Jane Doe",
  "guests": [
    {
      "id": "5dcb47800000000000000000",
      "checked_in_at": "2025-10-01T12:00:00+00:00",
      "checked_out_at": "2025-10-01T16:30:00+00:00",
      "customer_id": "5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d",
      "email": "jane.doe@example.com",
      "first_name": "Jane",
      "intake_form_submission_id": "5dcb47800000000000000010",
      "intake_form_complete": false,
      "is_lead_booker": true,
      "last_name": "Doe",
      "name": "Jane Doe"
    }
  ],
  "has_notes": true,
  "has_outstanding_balance": true,
  "has_special_requests": true,
  "is_group_booking": true,
  "is_hotel_room_booking": true,
  "is_locked": true,
  "is_part_of_package": true,
  "last_name": "Doe",
  "net_total": 4950,
  "order_id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "order_is_locked": false,
  "order_item_id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "order_labels": [
    "string"
  ],
  "order_locked_at": "2019-01-15T12:00:00+01:00",
  "order_ref": "TRY00",
  "organisation_id": "00000000-0000-0000-0000-000000000000",
  "package_product_code": "MAS123",
  "phone": "+447727123456",
  "practitioner_ids": [
    "64a9f3b2c3d8e1f4a5b6c7d8"
  ],
  "practitioners": [
    {
      "id": "5dcb47800000000000000000",
      "name": "Jane Doe"
    }
  ],
  "product_code": "MAS123",
  "room": {
    "id": "5dcb47800000000000000000",
    "capacity": 1,
    "name": "Alex Morgan"
  },
  "room_id": "64a9f3b2c3d8e1f4a5b6c7d8",
  "site_id": "00000000-0000-0000-0000-000000000000",
  "stage": "arrived",
  "start_time": "2019-01-15T12:00:00+01:00",
  "status": "confirmed",
  "submitted_at": "2019-01-15T12:00:00+01:00",
  "total_cost": 5000,
  "created_at": "2025-02-04T12:00:00+01:00",
  "updated_at": "string"
}
get/shop/appointments-v2

List Appointments

listAppointments

Use this endpoint to list Appointments.

Query parameters

  • pageintegeroptional

    The page to retrieve results from

  • per_pageintegeroptional

    The number of results to return per page

  • site_idstringrequired

    Filter results by the site they belong to

  • date_fromdateoptional

    Restrict results to those on or after this date, ISO-8601 YYYY-MM-DD.

  • date_todateoptional

    Restrict results to those on or before this date, ISO-8601 YYYY-MM-DD.

  • the order submitted date to fetch appointments from

  • the order submitted date to fetch appointments to

  • practitioner_idstring[]optional

    A comma separated string of practitioner ids to fetch bookings for

  • room_idstring[]optional

    A comma separated string of room ids to fetch bookings for

  • zone_idstring[]optional

    A comma separated string of zone ids to fetch bookings for

Responses

  • 200

    Successfully retrieved Appointments.

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

get/shop/appointments

List Appointments

listShopAppointments

Returns a paginated list of Appointments, optionally filtered by the date range the appointments fall in, the date range that the underlying Orders were submitted in, and by Practitioner, Room, or Zone. Appointments are ordered by start_time ascending.

This endpoint powers the calendar list views, day-sheet exports (via the CSV variant returned when Accept: text/csv), and any third-party reporting integration that needs the same data the Trybe dashboard renders.

Query parameters

  • pageintegeroptional

    The page to retrieve results from

  • per_pageintegeroptional

    The number of results to return per page

  • site_idstringrequired

    Filter results by the site they belong to

  • date_fromdateoptional

    Restrict results to those on or after this date, ISO-8601 YYYY-MM-DD.

  • date_todateoptional

    Restrict results to those on or before this date, ISO-8601 YYYY-MM-DD.

  • the order submitted date to fetch appointments from

  • the order submitted date to fetch appointments to

  • practitioner_idstring[]optional

    A comma separated string of practitioner ids to fetch bookings for

  • room_idstring[]optional

    A comma separated string of room ids to fetch bookings for

  • zone_idstring[]optional

    A comma separated string of zone ids to fetch bookings for

Responses

  • 200

    Successfully retrieved Appointments.

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

get/shop/appointments/{appointmentId}

Retrieve an Appointment

getAppointment

Retrieves a single Appointment by ID. Use this endpoint when you have an appointment ID returned by listShopAppointments, createBasketAppointmentItem, or a webhook payload, and need the canonical record — including its current status, stage, assigned Practitioners, Room, guest associations, and order context.

Path parameters

  • appointmentIdobject-idrequired

    The unique identifier of the Appointment. An appointment is a booking of an AppointmentType against one or more Practitioners and (optionally) a Room. The ID is the MongoDB ObjectID that the appointment was assigned when it was created via the Basket.

Responses

  • 200

    The Appointment was successfully retrieved.

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

  • 404

    The resource couldn't be found

put/shop/appointments/{appointmentId}

Update an Appointment

updateAppointment

Updates an Appointment in place. Common uses are reassigning the practitioner, moving the appointment to a different Room, rescheduling the start_time, or progressing the underlying Order through stages (e.g. marking the customer as arrived, in_treatment, or checked_out).

The update is routed through the basket / availability layer, so the request is validated against the same rules a fresh booking would face — overlapping practitioner bookings, room capacity, site opening hours, and equipment availability are all enforced. Users with the reservations.override-rules permission can bypass these checks server-side; everyone else will receive a 400 Bad Request with the specific availability conflict.

The move object is a convenience for calendar drag-and-drop: pass move.resource_type of practitioner or room plus the from_id and to_id to swap the assigned resource without spelling out the full practitioner_ids list. When only stage is supplied the appointment slot is left untouched and the change is applied to the parent order, saving the availability round-trip entirely.

Path parameters

  • appointmentIdobject-idrequired

    The unique identifier of the Appointment. An appointment is a booking of an AppointmentType against one or more Practitioners and (optionally) a Room. The ID is the MongoDB ObjectID that the appointment was assigned when it was created via the Basket.

Request body

  • practitioner_idsstring[]optionalnullable

    Replace the set of practitioners assigned to this appointment. Pass an empty array to clear all assignments. Each ID must belong to a practitioner who can perform this AppointmentType at this site.

  • room_idobject-idoptionalnullable

    Replace the room assigned to this appointment. The room must be one of the rooms permitted by the AppointmentType and available for the appointment's time slot.

  • start_timedate-timeoptional

    Reschedule the appointment to start at this date and time. The end time is recalculated from the appointment's duration and end_buffer. Must be an RFC 3339 timestamp with offset.

  • timedate-timeoptionalDeprecated

    Deprecated. Legacy alias for start_time. Will be removed once all calendar drag-and-drop clients have migrated.

  • moveobjectoptional

    Convenience block for calendar drag-and-drop. Specifies which practitioner or room is being swapped without restating the whole list. When resource_type is practitioner, practitioner_ids is updated automatically; when room, the room_id is updated.

  • stagestringoptionalnullable

    Move the underlying order through its check-in flow. When stage is the only field provided the availability layer is skipped entirely. Pass null to clear the stage back to the default.

    Possible values:arrivedin_treatmentchecked_outnot_arrived

Responses

  • 200

    The Appointment was successfully updated.

  • 400

    The request failed.

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

  • 404

    The resource couldn't be found

  • 422

    The request didn't pass validation

get/shop/appointments-v2/queue

Queue an export of the appointments-v2 list

queueAppointmentsV2

Queues a background job that exports the same appointment list returned by GET /shop/appointments-v2 as a CSV download. The -v2 endpoint sources its data from the order-item store rather than the legacy appointments collection, which means it can apply a richer set of filters (sales channel, order label, brand, etc.) and reflects the same totals shown in revenue reports.

The response returns a QueuedJob resource that you can poll via GET /shop/queued-jobs/{queuedJobId} to check progress and fetch the download_url once ready.

All filters supported by the list endpoint are accepted here and are applied to the export.

Query parameters

  • site_idstringrequired

    Filter results by the site they belong to

  • date_fromdateoptional

    Restrict results to those on or after this date, ISO-8601 YYYY-MM-DD.

  • date_todateoptional

    Restrict results to those on or before this date, ISO-8601 YYYY-MM-DD.

  • the order submitted date to fetch appointments from

  • the order submitted date to fetch appointments to

  • practitioner_idstring[]optional

    A comma separated string of practitioner ids to fetch bookings for

  • room_idstring[]optional

    A comma separated string of room ids to fetch bookings for

  • zone_idstring[]optional

    A comma separated string of zone ids to fetch bookings for

Responses

  • 200

    The job was successfully queued

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

get/shop/appointments/queue

Queue an export of the appointments list

queueAppointments

Queues a background job that exports the same Appointment list returned by GET /shop/appointments as a CSV download. Use this when the result set is too large to retrieve synchronously, or when you want the export delivered to the calling user as a downloadable file.

The response returns a QueuedJob resource you can poll via GET /shop/queued-jobs/{queuedJobId}. Once the job has finished, its download_url becomes available and the CSV can be streamed.

All filters supported by the list endpoint (date range, order submitted range, practitioner, room, zone) are accepted here and are applied to the export.

Query parameters

  • site_idstringrequired

    Filter results by the site they belong to

  • date_fromdateoptional

    Restrict results to those on or after this date, ISO-8601 YYYY-MM-DD.

  • date_todateoptional

    Restrict results to those on or before this date, ISO-8601 YYYY-MM-DD.

  • the order submitted date to fetch appointments from

  • the order submitted date to fetch appointments to

  • practitioner_idstring[]optional

    A comma separated string of practitioner ids to fetch bookings for

  • room_idstring[]optional

    A comma separated string of room ids to fetch bookings for

  • zone_idstring[]optional

    A comma separated string of zone ids to fetch bookings for

Responses

  • 200

    The job was successfully queued

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

put/shop/appointments/{appointmentId}/check

Check whether an Appointment update would be allowed

updateAppointmentCheck

Dry-runs an Appointment update without persisting the change. Reports whether the proposed assignment of practitioners, room and time-of-day slot would succeed.

Note: this endpoint validates against time-of-day only — it is NOT a full reschedule dry-run. The body is a strict subset of UpdateAppointment (practitioner_ids, room_id and a HH:mm start_time); other writable appointment fields (move, stage, item_configuration, etc.) are not consulted here. Use PUT /shop/appointments/{appointmentId} to actually persist a reschedule.

Use this to surface conflicts (overlapping bookings, room capacity, equipment availability, opening hours) to the operator before they commit a drag-and-drop move on the calendar. The response indicates whether the update is allowed, lists the specific availability errors that would block it, and reports whether the current user has the reservations.override-rules permission to bypass them.

Path parameters

  • appointmentIdobject-idrequired

    The unique identifier of the Appointment. An appointment is a booking of an AppointmentType against one or more Practitioners and (optionally) a Room. The ID is the MongoDB ObjectID that the appointment was assigned when it was created via the Basket.

Request body

  • practitioner_idsstring[]optional

    The practitioners that would be assigned to the appointment. Each entry must be a valid Practitioner ID; the check fails if any of the practitioners is unavailable or unqualified for the appointment type.

  • room_idstringoptionalnullable

    The room the appointment would take place in. Pass null to check availability without a room constraint.

  • start_timetimeoptional

    Time-of-day the appointment would start, in HH:mm (24-hour) format. The check endpoint validates only the time-of-day slot — it does NOT accept a full RFC 3339 datetime; pass the date via the path/appointment context and the clock time here.

Responses

  • 200

    The check was successfully carried out.

  • 401

    The user is unauthenticated

  • 403

    The authenticated user does not have permission.

  • 404

    The resource couldn't be found

  • 422

    The request didn't pass validation