API reference
Appointments
Bookings at a venue. 4 operations under /public/v1, with parameters, request bodies and example responses.
Paths are relative to the API host: https://sandbox-api.clivehealth.app for the sandbox, https://api.clivehealth.app for production. Send Authorization: Bearer <token> on every request (Getting started).
Operations
- GET
/public/v1/appointmentsList appointments - POST
/public/v1/appointmentsBook an appointment - GET
/public/v1/appointments/{id}Get an appointment - POST
/public/v1/appointments/{id}/cancelCancel an appointment
List appointments
/public/v1/appointmentsScope appointments:readOperation listAppointments
Ordered by updated_at then id. from and to filter on start_time.
Requires scope appointments:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
limit | query | integer | Page size, 1 to 200. Default 50. |
cursor | query | string | Opaque cursor from the previous page's next_cursor. |
updated_since | query | string (date-time) | ISO 8601 timestamp: only records updated at or after it. Lists are ordered by updated_at then id, so this plus cursor is a change feed. |
member_id | query | string (uuid) | |
venue_id | query | string (uuid) | |
from | query | string (date-time) | Appointments starting at or after this time. |
to | query | string (date-time) | Appointments starting before this time. |
status | query | "scheduled" | "confirmed" | "checked_in" | "in_progress" | "completed" | "cancelled" | "no_show" |
Responses
200A page of appointments.Returns AppointmentPage.
| Field | Type | Description |
|---|---|---|
datarequired | array of Appointment | |
idrequired | string (uuid) | |
member_idrequired | string (uuid) | |
venue_idrequired | string (uuid) | |
practitioner_idrequired | string (uuid) | |
start_timerequired | string (date-time) | |
end_timerequired | string (date-time) | |
duration_minutesrequired | integer | |
typerequired | string | Service or treatment type. |
statusrequired | "scheduled" | "confirmed" | "checked_in" | "in_progress" | "completed" | "cancelled" | "no_show" | |
cancel_reasonrequired | string or null | |
sourcerequired | string or null | How it was booked: partner_api, online_booking, manual, ... |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
next_cursorrequired | string or null | Pass as cursor to fetch the next page; null on the last page. |
has_morerequired | boolean |
{
"data": [
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"member_id": "0b8e3c6a-2d4f-4e1b-9a7c-5d3e1f2a4b6c",
"venue_id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"practitioner_id": "3f6b8d0a-2c4e-4f1a-9b3d-5e7f9a1c3e5b",
"start_time": "2026-10-24T01:30:00.000Z",
"end_time": "2026-10-24T02:00:00.000Z",
"duration_minutes": 30,
"type": "consultation",
"status": "scheduled",
"cancel_reason": null,
"source": "partner",
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}
],
"next_cursor": null,
"has_more": false
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 422 | Validation failed (VALIDATION_ERROR). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Book an appointment
/public/v1/appointmentsScope appointments:writeOperation createAppointment
Books the member at the venue. 409 SLOT_TAKEN when the practitioner (or every practitioner at the venue) is busy.
Requires scope appointments:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Keyrequired | header | string | Unique key for this operation (a UUID is a good choice). Retrying with the same key and request replays the first response for 24 hours. |
Request body AppointmentCreate
| Field | Type | Description |
|---|---|---|
member_idrequired | string (uuid) | |
venue_idrequired | string (uuid) | |
start_timerequired | string (date-time) | ISO 8601 with offset; must be in the future. |
duration_minutes | integer | Defaults to the clinic's slot length. |
typerequired | string | |
practitioner_id | string (uuid) | A specific practitioner; otherwise the first free practitioner at the venue is assigned. |
{
"member_id": "0b8e3c6a-2d4f-4e1b-9a7c-5d3e1f2a4b6c",
"venue_id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"start_time": "2026-10-24T01:30:00.000Z",
"duration_minutes": 30,
"type": "consultation",
"practitioner_id": "3f6b8d0a-2c4e-4f1a-9b3d-5e7f9a1c3e5b"
}Responses
201The new appointment.Returns Appointment.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
member_idrequired | string (uuid) | |
venue_idrequired | string (uuid) | |
practitioner_idrequired | string (uuid) | |
start_timerequired | string (date-time) | |
end_timerequired | string (date-time) | |
duration_minutesrequired | integer | |
typerequired | string | Service or treatment type. |
statusrequired | "scheduled" | "confirmed" | "checked_in" | "in_progress" | "completed" | "cancelled" | "no_show" | |
cancel_reasonrequired | string or null | |
sourcerequired | string or null | How it was booked: partner_api, online_booking, manual, ... |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"member_id": "0b8e3c6a-2d4f-4e1b-9a7c-5d3e1f2a4b6c",
"venue_id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"practitioner_id": "3f6b8d0a-2c4e-4f1a-9b3d-5e7f9a1c3e5b",
"start_time": "2026-10-24T01:30:00.000Z",
"end_time": "2026-10-24T02:00:00.000Z",
"duration_minutes": 30,
"type": "consultation",
"status": "scheduled",
"cancel_reason": null,
"source": "partner",
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request, invalid cursor, or missing Idempotency-Key (IDEMPOTENCY_KEY_REQUIRED). |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 409 | Conflict, or a request with the same Idempotency-Key is still in flight (IDEMPOTENCY_IN_PROGRESS). |
| 422 | Validation failed (VALIDATION_ERROR), or the Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Get an appointment
/public/v1/appointments/{id}Scope appointments:readOperation getAppointment
Requires scope appointments:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string (uuid) |
Responses
200The appointment.Returns Appointment.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
member_idrequired | string (uuid) | |
venue_idrequired | string (uuid) | |
practitioner_idrequired | string (uuid) | |
start_timerequired | string (date-time) | |
end_timerequired | string (date-time) | |
duration_minutesrequired | integer | |
typerequired | string | Service or treatment type. |
statusrequired | "scheduled" | "confirmed" | "checked_in" | "in_progress" | "completed" | "cancelled" | "no_show" | |
cancel_reasonrequired | string or null | |
sourcerequired | string or null | How it was booked: partner_api, online_booking, manual, ... |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"member_id": "0b8e3c6a-2d4f-4e1b-9a7c-5d3e1f2a4b6c",
"venue_id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"practitioner_id": "3f6b8d0a-2c4e-4f1a-9b3d-5e7f9a1c3e5b",
"start_time": "2026-10-24T01:30:00.000Z",
"end_time": "2026-10-24T02:00:00.000Z",
"duration_minutes": 30,
"type": "consultation",
"status": "scheduled",
"cancel_reason": null,
"source": "partner",
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 404 | No such record in this clinic (NOT_FOUND). |
| 422 | Validation failed (VALIDATION_ERROR). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Cancel an appointment
/public/v1/appointments/{id}/cancelScope appointments:writeOperation cancelAppointment
Cancelling an already-cancelled appointment returns it unchanged. Appointments in progress or completed can't be cancelled (409).
Requires scope appointments:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string (uuid) | |
Idempotency-Keyrequired | header | string | Unique key for this operation (a UUID is a good choice). Retrying with the same key and request replays the first response for 24 hours. |
Request body AppointmentCancel
| Field | Type | Description |
|---|---|---|
reason | string |
{
"reason": "Member requested"
}Responses
200The cancelled appointment.Returns Appointment.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
member_idrequired | string (uuid) | |
venue_idrequired | string (uuid) | |
practitioner_idrequired | string (uuid) | |
start_timerequired | string (date-time) | |
end_timerequired | string (date-time) | |
duration_minutesrequired | integer | |
typerequired | string | Service or treatment type. |
statusrequired | "scheduled" | "confirmed" | "checked_in" | "in_progress" | "completed" | "cancelled" | "no_show" | |
cancel_reasonrequired | string or null | |
sourcerequired | string or null | How it was booked: partner_api, online_booking, manual, ... |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"member_id": "0b8e3c6a-2d4f-4e1b-9a7c-5d3e1f2a4b6c",
"venue_id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"practitioner_id": "3f6b8d0a-2c4e-4f1a-9b3d-5e7f9a1c3e5b",
"start_time": "2026-10-24T01:30:00.000Z",
"end_time": "2026-10-24T02:00:00.000Z",
"duration_minutes": 30,
"type": "consultation",
"status": "scheduled",
"cancel_reason": null,
"source": "partner",
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request, invalid cursor, or missing Idempotency-Key (IDEMPOTENCY_KEY_REQUIRED). |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 404 | No such record in this clinic (NOT_FOUND). |
| 409 | Conflict, or a request with the same Idempotency-Key is still in flight (IDEMPOTENCY_IN_PROGRESS). |
| 422 | Validation failed (VALIDATION_ERROR), or the Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.