Appointments

Update an Appointment

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.

put/shop/appointments/{appointmentId}

Request body

practitioner_idsstring[] nullable

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_idstring object-id nullable

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_timestring date-time

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.

timestring date-time

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

stage'arrived' | 'in_treatment' | 'checked_out' | 'not_arrived' nullable

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.

Example request

{
  "practitioner_ids": [
    "5e932c0901d210625e3a8766"
  ],
  "room_id": "5e932c0901d210625e3a8767",
  "start_time": "2026-06-01T10:00:00+01:00",
  "time": "2026-06-01T10:00:00+01:00",
  "move": {
    "from_id": "5e932c0901d210625e3a8766",
    "to_id": "5e932c0901d210625e3a8767"
  }
}

Response

The Appointment was successfully updated.

Example response

{
  "data": {
    "appointment_type_name": "60 minute massage",
    "currency": "gbp",
    "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",
        "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_labels": [
      {
        "color": "#FF0000",
        "name": "VIP"
      }
    ],
    "order_locked_at": "2019-01-15T12:00:00+01:00",
    "order_ref": "TRY00",
    "package_product_code": "MAS123",
    "phone": "+447727123456",
    "practitioners": [
      {
        "id": "5dcb47800000000000000000",
        "name": "Jane Doe"
      }
    ],
    "product_code": "MAS123",
    "room": {
      "id": "5dcb47800000000000000000"
    },
    "start_time": "2019-01-15T12:00:00+01:00",
    "submitted_at": "2019-01-15T12:00:00+01:00",
    "total_cost": 5000,
    "created_at": "2025-02-04T12:00:00+01:00",
    "updated_at": "2025-02-04T12:00:00+01:00"
  }
}

Changes

No recorded changes to this endpoint across all 1 revision of this API.