{
  "openapi": "3.0.0",
  "info": {
    "title": "Dentally NexGen API",
    "version": "2026-01-01",
    "description": "The **Dentally NexGen API** exposes HTTP resources for partner integrations\nwith Dentally. This page is the machine-readable contract; the developer\nportal sidebar carries the rest of the documentation:\n\n- **Getting started** — make your first call.\n- **Authentication** — bearer tokens issued via Auth0.\n- **Versioning** — date-based revisions selected with the\n  `Dentally-API-Version` header.\n- **Pagination** — cursor-based paging using `cursor` + `limit`.\n- **Errors** — Problem Details (RFC 7807) for every error response.\n- **Conventions** — naming, types, dates, nullability.\n",
    "license": {
      "name": "Proprietary",
      "url": "https://dentally.com"
    },
    "contact": {
      "name": "Dentally Partnerships",
      "url": "https://www.dentally.com/en-gb/integrations/become-a-partner",
      "email": "dentallypartnerships@henryscheinone.com"
    }
  },
  "servers": [
    {
      "url": "https://api.dentally.co",
      "description": "Production - UK"
    },
    {
      "url": "https://api.apac.dentally.com",
      "description": "Production - APAC"
    }
  ],
  "tags": [
    {
      "name": "Appointments",
      "description": "Book, reschedule, and cancel patient appointments. List and retrieve appointment details, including patient, practitioner, site, and reason information."
    },
    {
      "name": "Appointment Reasons",
      "description": "Reasons that describe the purpose of a patient visit (for example an examination or a scale and polish). List and retrieve the catalogue of reasons configured for a practice."
    },
    {
      "name": "Calendar Zones",
      "description": "Scheduled, recurring blocks of diary time reserved for a specific purpose, for a practitioner or a room. List and retrieve calendar zone occurrences, including their practitioner, room, and zone group."
    },
    {
      "name": "Patients",
      "description": "Core patient demographic operations."
    },
    {
      "name": "Practitioners",
      "description": "Practice clinicians and dental care professionals (DCPs). List and retrieve identifiers, linked user, site, role, and NHS number fields for integrations."
    },
    {
      "name": "Sites",
      "description": "Physical locations for a practice (clinics, surgeries, branches). List and retrieve addresses, contact details, and opening hours for partner-facing experiences such as booking and location finders."
    },
    {
      "name": "Communications",
      "description": "Send communications to patients on behalf of a practice using a variety of channels."
    },
    {
      "name": "Invoices",
      "description": "Billing invoices for dental services provided to patients. List and retrieve invoice details, including amounts, payments, insurance, and outstanding balances."
    },
    {
      "name": "Fee Schedules",
      "description": "Practice-defined pricing and care categories assigned to patients. List and retrieve fee schedule details, including funding, default appointment lengths, new-patient recall defaults, and optional membership pricing. Dentally's user interface in the United Kingdom sometimes calls these payment plans."
    },
    {
      "name": "NHS Contracts",
      "description": "NHS dental service contracts configured for a practice, including NHS-issued identifiers."
    },
    {
      "name": "Identifier Mappings",
      "description": "Map legacy integer sequential ids to NexGen UUIDs for supported resource types (`patient`, `practitioner`, `appointment`, `invoice`), up to 100 ids per request."
    },
    {
      "name": "SystemUsers",
      "description": "Internal system user."
    },
    {
      "name": "Fees",
      "description": "List and retrieve fees for a practice."
    },
    {
      "name": "Treatment Categories",
      "description": "Folders a practice uses to group its treatment catalogue. List and retrieve treatment categories. Treatment categories are practice-wide and are not scoped to a site."
    },
    {
      "name": "Treatment Plans",
      "description": "Planned course of dental treatment for a patient at a practice."
    },
    {
      "name": "Treatment Plan Items",
      "description": "A treatment charted on a patient’s treatment plan."
    },
    {
      "name": "Treatments",
      "description": "Practice-level catalogue of procedures that can be assigned to a patient treatment plan. List and retrieve treatments. Treatments are practice-wide and are not scoped to a site."
    },
    {
      "name": "Subscriptions",
      "description": "Marketplace endpoints to manage a customer's subscriptions to partner products."
    }
  ],
  "paths": {
    "/appointments": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List appointments",
        "description": "Returns a **paginated** list of appointments for the practice identified by\n`X-Practice-Id`. Results are ordered by **creation time**, latest first\n(`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameters allow filtering results by patient, practitioner,\nsite, room, and state, as well as create and update date ranges.\n\n**Date range.** Optional query parameters `created_date_from` and `created_date_to` filter by creation date,\nwhile `updated_date_from` and `updated_date_to` filter by update date. Both ends are inclusive.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-appointments",
        "tags": [
          "Appointments"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          },
          {
            "name": "patient_id",
            "in": "query",
            "required": false,
            "description": "Filter appointments to those associated with the specified patient. The value should be a UUID corresponding to a patient within the practice.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "practitioner_id",
            "in": "query",
            "required": false,
            "description": "Filter appointments to those associated with the specified practitioner. The value should be a UUID corresponding to a practitioner within the practice.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "room_id",
            "in": "query",
            "required": false,
            "description": "Filter appointments to those occurring in the specified room. The value should be a UUID corresponding to a room within the practice.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Filter appointments to those in the specified state.",
            "schema": {
              "$ref": "#/components/schemas/appointment-state"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-appointments-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      },
      "post": {
        "summary": "Create an appointment",
        "description": "Creates a new appointment for the practice identified by `X-Practice-Id`.\nThe appointment location (`site_id`) is determined by the site of the practitioner\nspecified in `practitioner_id`. On success, the newly created appointment is returned\nin the `data` envelope with a state of `Pending`.\n\nSupplied IDs must exist within the practice and be usable for booking.\nAn inactive patient or practitioner, a patient blocked from booking, an inactive\nappointment reason, or an unavailable room results in **422**.\n\nAppointments must also fall within the practitioner's working hours; times that conflict\nwith their schedule, breaks, or blocked periods result in **422**.\n",
        "operationId": "create-appointment",
        "tags": [
          "Appointments"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/create-appointment-request"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/create-appointment-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/appointments/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get appointment by ID",
        "description": "Returns the **single appointment** matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing appointments.\n\nIf no appointment exists for that practice and `id`, the API responds with **404**.\n",
        "operationId": "get-appointment",
        "tags": [
          "Appointments"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-appointment-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      },
      "patch": {
        "summary": "Update an appointment",
        "description": "Updates the appointment matching `id` for the practice identified by `X-Practice-Id`. Only the fields provided in the request body will be modified; omitted fields remain unchanged.\nIf no appointment exists for that practice and `id`, the API responds with **404**.\nWhen `reason_id` is provided, it must refer to an active appointment reason; otherwise the API responds with **422**.\nWhen `start_time` or `duration_minutes` is provided, the resulting appointment must fall within the practitioner's working hours and must not conflict with any blocked or unavailable periods; otherwise the API responds with **422**.",
        "operationId": "update-appointment",
        "tags": [
          "Appointments"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/update-appointment-request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/update-appointment-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/appointments/{id}/cancel": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "post": {
        "summary": "Cancel an appointment",
        "description": "Cancels the appointment matching `id` for the practice identified by\n`X-Practice-Id`. The appointment `state` is set to `Cancelled` and\n`cancelled_at` is recorded.\n\nCancellation is only permitted when the appointment is not in a final\nstate. The following states are final and cannot be cancelled:\n`Completed`, `Cancelled`, `Did not attend`, `Arrived`, and `In surgery`.\nOnly Appointments in `Pending` and `Confirmed` may be cancelled.\n\nIf the appointment is already `Cancelled`, the API responds with **422**.\nIf no appointment exists for that practice and `id`, the API responds\nwith **404**. An unknown or inactive `cancellation_reason_id` results in\n**422**.\n",
        "operationId": "cancel-appointment",
        "tags": [
          "Appointments"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/cancel-appointment-request"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Appointment successfully cancelled."
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/appointment_reasons": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List appointment reasons",
        "description": "Returns a **paginated** list of appointment reasons for the practice identified by\n`X-Practice-Id`. Results are ordered by **creation time**, latest first\n(`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameter `is_active`, when `true`, restricts results to\nappointment reasons that are currently active. When `false`, restricts results to\nappointment reasons that are currently inactive. When omitted, all appointment\nreasons are returned.\n",
        "operationId": "list-appointment-reasons",
        "tags": [
          "Appointment Reasons"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-appointment-reasons-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/appointment_cancellation_reasons": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List appointment cancellation reasons",
        "description": "Returns a **paginated** list of appointment cancellation reasons for the practice\nidentified by `X-Practice-Id`. Results are ordered by **creation time**, latest\nfirst (`created_at` descending), then by `id` descending for a stable sort.\n",
        "operationId": "list-appointment-cancellation-reasons",
        "tags": [
          "Appointment Reasons"
        ],
        "security": [
          {
            "oauth2": [
              "appointment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-appointment-cancellation-reasons-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/patients": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List patients",
        "description": "Returns a paginated list of patients for a practice.\n\nOptional query parameters allow filtering results by site, as well as create\nand update date ranges.\n",
        "operationId": "list-patients",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "patient:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-patients-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      },
      "post": {
        "summary": "Create a new patient",
        "description": "Creates a new patient record for a practice. Writable fields mirror the patient\nresource returned by list and get where applicable.\n",
        "operationId": "create-patient",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "patient:write"
            ]
          }
        ],
        "requestBody": {
          "description": "Patient object that needs to be added to the practice.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/create-patient-request"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/create-patient-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/patients/search": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Search patients",
        "description": "Returns a paginated list of patients for a practice, with optional filters.\n\nWhen **no** query filters are provided, all patients for the practice are returned (subject to\npagination), ordered for keyset paging.\n\nWhen **one or more** filters are provided, patients matching **any** of those filters are included\n(logical **OR**). Filters combine only with each other under this OR rule.\n\nWhen `family_id` is provided, only patients in that family are considered. Any other filters\nare OR-combined within that family. Behaviour without `family_id` is unchanged.\n\n**Filter semantics:**\n\n- `family_id` — exact UUID match limiting results to patients in that family.\n- `id` — primary key equality.\n- `first_name` — case-insensitive **prefix** match on first name.\n- `last_name` — case-insensitive **prefix** match on last name.\n- `date_of_birth` — exact calendar date match (`YYYY-MM-DD`).\n- `email_address` — case-insensitive **prefix** match on stored email.\n- `mobile_phone` — match against mobile number (substring match, case-insensitive).\n\nResponse body matches `GET /patients` (same `data` items and `meta.cursor` pagination). Visibility of\nemail, address, and phone fields still depends on the token scopes, as for the patient list endpoint.\n",
        "operationId": "search-patients",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "patient:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "family_id",
            "in": "query",
            "required": false,
            "description": "Exact family UUID. Other filters are OR-combined within the matching family.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Filter by patient id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "first_name",
            "in": "query",
            "required": false,
            "description": "Case-insensitive prefix filter on first name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "last_name",
            "in": "query",
            "required": false,
            "description": "Case-insensitive prefix filter on last name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_of_birth",
            "in": "query",
            "required": false,
            "description": "Exact date of birth (`YYYY-MM-DD`).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "email_address",
            "in": "query",
            "required": false,
            "description": "Case-insensitive prefix filter on email address.",
            "schema": {
              "type": "string",
              "format": "email"
            }
          },
          {
            "name": "mobile_phone",
            "in": "query",
            "required": false,
            "description": "Filter using mobile number (substring match).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-patients-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/patients/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get an existing patient",
        "description": "Gets an existing patient record for a practice.",
        "operationId": "get-patient",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "patient:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-patient-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      },
      "patch": {
        "summary": "Update an existing patient",
        "description": "Updates an existing patient record for a practice.",
        "operationId": "update-patient",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "patient:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "requestBody": {
          "description": "Fields to update on the patient. Omitted members are left unchanged.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/update-patient-request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/update-patient-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/patients/{id}/account": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get patient account balance",
        "description": "Returns the account balance for the patient matching `id`, for the practice identified by `X-Practice-Id`. The balance is the account the patient's invoices and payments are posted to. The `id` is the same patient `id` returned when listing patients.\nMonetary amounts are signed. A negative amount means money is owed to the practice. A positive amount means the account is in credit.\nSome patients share an account, so `owning_patient_id` in the response is the patient who owns the account. When it differs from the `id` in the request path, the patient you asked for shares the account of the returned `owning_patient_id`, and the balances are those of that shared account.\nIf the patient does not exist, has been deleted, or has no account, the API responds with 404. The three cases cannot be told apart. A token without the `account:read` scope receives 403.",
        "operationId": "get-patient-account",
        "tags": [
          "Patients"
        ],
        "security": [
          {
            "oauth2": [
              "account:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-patient-account-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/practitioners": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List practitioners",
        "description": "Returns a **paginated** list of practitioners for the practice identified by\n`X-Practice-Id`. Results are ordered by **creation time**, newest first\n(`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameter `is_active`, when `true`, restricts results to\npractitioners who are currently active. When `false`, restricts results to\npractitioners who are currently inactive. When omitted, all practitioners are returned.\n\nOptional query parameter `site_id` restricts results to practitioners assigned to\nthe specified site.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-practitioners",
        "tags": [
          "Practitioners"
        ],
        "security": [
          {
            "oauth2": [
              "practitioner:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-practitioners-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/practitioners/availabilities": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List practitioner availabilities",
        "description": "Returns a **paginated** list of **availability slots** for one or more practitioners.\n\n**Required query parameters:** `date_from`, `date_to`, and\n`practitioner_ids[]` (at least one practitioner UUID).\n\n**Date range.** Both `date_from` and `date_to` are inclusive (`YYYY-MM-DD`).\nBoth must be today or in the future, and `date_from` must be on or before\n`date_to`. The span between them must not exceed **one week**; otherwise\nthe API responds with **422**.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-practitioner-availabilities",
        "tags": [
          "Practitioners"
        ],
        "security": [
          {
            "oauth2": [
              "practitioner:availability:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/date-from"
          },
          {
            "$ref": "#/components/parameters/date-to"
          },
          {
            "name": "practitioner_ids[]",
            "in": "query",
            "required": true,
            "description": "One or more practitioner UUIDs to search for availability. At least one\nvalue is required. Repeat the parameter for multiple practitioners\n(e.g. `practitioner_ids[]=3fa85f64-5717-4562-b3fc-2c963f66afa6`).\n",
            "schema": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "string",
                "format": "uuid"
              }
            },
            "style": "form",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-practitioner-availabilities-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/practitioners/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get practitioner by ID",
        "description": "Returns the **single practitioner** matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing practitioners.\n\nIf no practitioner exists for that practice and `id`, the API responds with **404**.\n",
        "operationId": "get-practitioner",
        "tags": [
          "Practitioners"
        ],
        "security": [
          {
            "oauth2": [
              "practitioner:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-practitioner-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/practitioners/{id}/rota_schedule_histories": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List rota schedule histories",
        "description": "Returns a **paginated** list of **snapshot rota days** for the practitioner\nidentified by `id` in the path. Each row describes the effective scheduled\nworking hours and breaks for a single calendar date, as captured from the\npractice rota (including overrides that were active when the snapshot was taken).\n\nResults are ordered by **calendar date**, most recent first (`date` descending).\n\n**Date range.** `date_from` and `date_to` are **required** query parameters.\nBoth ends are inclusive. The span between them must not exceed **three months**;\notherwise the API responds with **422**.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-practitioner-rota-schedule-histories",
        "tags": [
          "Practitioners"
        ],
        "security": [
          {
            "oauth2": [
              "practitioner:rota_schedule:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "date_from",
            "in": "query",
            "required": true,
            "description": "Inclusive start of the date range (`YYYY-MM-DD`). Must be supplied together with `date_to`. The span between `date_from` and `date_to` must not exceed three months.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-01-01"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "required": true,
            "description": "Inclusive end of the date range (`YYYY-MM-DD`). Must be supplied together with `date_from`. Must be on or after `date_from`, and the span between the two dates must not exceed three months.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-03-31"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-rota-schedule-histories-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/sites": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List sites",
        "description": "Returns a **paginated** list of all sites for the practice identified by\n`X-Practice-Id`. Use this to discover locations where the practice operates,\nincluding addresses, contact details, and opening hours.\n\nResults are ordered by **creation time**, newest first (`created_at`\ndescending). Use `limit` and the `meta.cursor` value from the response to\nretrieve further pages.\n",
        "operationId": "list-sites",
        "tags": [
          "Sites"
        ],
        "security": [
          {
            "oauth2": [
              "site:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-sites-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/sites/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get site by ID",
        "description": "Returns the **single site** matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing sites.\n\nIf no site exists for that practice and `id`, the API responds with **404**.\n",
        "operationId": "get-site",
        "tags": [
          "Sites"
        ],
        "security": [
          {
            "oauth2": [
              "site:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-site-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/communications": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "post": {
        "summary": "Send a message to a patient",
        "description": "Send a SMS or eMail to a patient on behalf of a practice.  \nNo other messaging channels are currently supported for sending communications via the API.  \nPlease note, access to this API is provisioned by a Dentally admin.\n",
        "operationId": "send-communication",
        "tags": [
          "Communications"
        ],
        "security": [
          {
            "oauth2": [
              "communication:write"
            ]
          }
        ],
        "requestBody": {
          "description": "Details of the communication to send to a patient.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/send-communication-request"
              },
              "examples": {
                "send_sms": {
                  "summary": "Send an SMS communication",
                  "value": {
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "sms",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "send_email": {
                  "summary": "Send an Email communication",
                  "value": {
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "email",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "html_body": "<p>Your appointment is scheduled for tomorrow at 3 PM.</p>",
                    "subject": "Appointment Reminder",
                    "message_type": "appointment_confirmation",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/send-communication-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/communications/{id}/reply": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get response details",
        "description": "Returns the details of a **single response communication** to a communication matching `id` for the practice\nidentified by `X-Practice-Id`. The identifier is the same `id` returned when \n[creating an SMS communication](#operation/send-communication).\n",
        "operationId": "get-communication-response-details",
        "tags": [
          "Communications"
        ],
        "security": [
          {
            "oauth2": [
              "communication:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          },
          {
            "in": "query",
            "name": "communication_channel",
            "schema": {
              "$ref": "#/components/schemas/communication-channel"
            },
            "description": "The communication channel to filter by. If not provided, the response will include communications for the SMS channel ONLY.  \nCurrently **ONLY** sms is supported. All other channels will return a not supported response.\n"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-communication-details-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/external_communications": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "post": {
        "summary": "Create an external communication",
        "description": "Capture an external communication which has occurred with a patient, outside of the Dentally eco-system.  \nThis is used to capture messages sent via channels that Dentally does not support.  \nPlease note, the Dentally portal has not yet been updated to display this information.  \nLogging an SMS requires the `communication:external:sms:write` scope instead of `communication:external:write`.  \nPlease note, access to the `communication:external:sms:write` scope is provisioned by a Dentally admin.\n",
        "operationId": "external-create-communication",
        "tags": [
          "Communications"
        ],
        "security": [
          {
            "oauth2": [
              "communication:external:write"
            ]
          },
          {
            "oauth2": [
              "communication:external:sms:write"
            ]
          }
        ],
        "requestBody": {
          "description": "Details of the communication that was sent to a patient.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/external-communication-request"
              },
              "examples": {
                "log_sms": {
                  "summary": "Create an SMS communication",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "sms",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_sms_reply": {
                  "summary": "Create an SMS reply communication",
                  "value": {
                    "direction": "inbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "sms",
                    "body": "Thanks, see you tomorrow at 3 PM.",
                    "message_type": "patient_reply",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_email": {
                  "summary": "Create an Email communication",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "email",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "html_body": "<p>Your appointment is scheduled for tomorrow at 3 PM.</p>",
                    "subject": "Appointment Reminder",
                    "message_type": "appointment_confirmation",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_letter_with_text": {
                  "summary": "Create a Letter communication with plain text content",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "letter",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_letter_with_link": {
                  "summary": "Create a Letter communication using a link to the content",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "letter",
                    "body_link": "https://example.com/letters/12345/content",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_messaging_app": {
                  "summary": "Create a Messaging App communication",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "messaging_app",
                    "messaging_channel": "whatsapp",
                    "body": "Your appointment is scheduled for tomorrow at 3 PM.",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001"
                  }
                },
                "log_phone_call": {
                  "summary": "Create a Phone Call communication",
                  "value": {
                    "direction": "outbound",
                    "patient_id": "123e4567-e89b-12d3-a456-426614174000",
                    "communication_channel": "phone_call",
                    "message_type": "appointment_reminder",
                    "site_id": "123e4567-e89b-12d3-a456-426614174001",
                    "body": "Left a voicemail reminding the patient of their appointment tomorrow at 3 PM."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/create-external-communication-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/fees": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List fees",
        "description": "Returns a **paginated** list of fees for the practice identified by `X-Practice-Id`. Results are ordered by **creation time**, newest first (`created_at` descending), then by `id` descending for a stable sort.\nOptional query parameters allow filtering by payment plan, treatment, and created/updated date ranges.\n**Date range.** Optional query parameters `created_date_from` and `created_date_to` filter by creation date, while `updated_date_from` and `updated_date_to` filter by update date. Both ends are inclusive.\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.",
        "operationId": "list-fees",
        "tags": [
          "Fees"
        ],
        "security": [
          {
            "oauth2": [
              "fee:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          },
          {
            "name": "payment_plan_id",
            "in": "query",
            "required": false,
            "description": "Filter fees to those associated with the specified fee schedule (payment plan). The value should be a UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "treatment_id",
            "in": "query",
            "required": false,
            "description": "Filter fees to those associated with the specified treatment. The value should be a UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-fees-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/fees/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get fee by ID",
        "description": "Returns the **single fee** matching `id` for the practice identified by `X-Practice-Id`. The identifier is the same `id` returned when listing fees.\nIf no fee exists for that practice and `id`, the API responds with **404**.",
        "operationId": "get-fee",
        "tags": [
          "Fees"
        ],
        "security": [
          {
            "oauth2": [
              "fee:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-fee-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/fee_schedules": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List fee schedules",
        "description": "Returns a paginated list of fee schedules for the practice identified by\n`X-Practice-Id`. Dentally's user interface in the United Kingdom sometimes\ncalls these payment plans.\n\nWhen `site_id` is supplied, the response includes only schedules assigned\nto that site. Schedules with a null `site_id` are not included.\n\nWhen `is_active` is `true`, results are restricted to active schedules.\nWhen `false`, results are restricted to inactive schedules. When omitted,\nall schedules are returned.\n\nResults are ordered by **creation time** and ID, newest first (`created_at`\ndescending, then `id` descending). Use `limit` and the `meta.cursor` value\nfrom the response to retrieve further pages.\n",
        "operationId": "list-fee-schedules",
        "tags": [
          "Fee Schedules"
        ],
        "security": [
          {
            "oauth2": [
              "fee_schedule:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/site-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-fee-schedules-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/fee_schedules/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get fee schedule by ID",
        "description": "Returns the single fee schedule matching `id` for the practice identified by\n`X-Practice-Id`. Dentally's user interface in the United Kingdom sometimes\ncalls this a payment plan. The identifier is the same `id` returned when\nlisting fee schedules.\n\nIf no fee schedule exists for that practice and `id`, the API responds with\n404.\n",
        "operationId": "get-fee-schedule",
        "tags": [
          "Fee Schedules"
        ],
        "security": [
          {
            "oauth2": [
              "fee_schedule:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-fee-schedule-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/invoices": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List invoices",
        "description": "Returns a **paginated** list of invoices for the practice identified by\n`X-Practice-Id`. Results are ordered by **creation time**, most recent created first\n(`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameters allow filtering results by patient, site, \ncreate and update date ranges, and if the invoice has been paid.\n\nWhen `is_paid` is `true`, results are restricted to invoices that have been paid. \nWhen `false`, results are restricted to invoices that have not been paid. \nWhen omitted, all invoices are returned.\n\n**Date range.** Optional query parameters `created_date_from` and `created_date_to` filter by creation date, \nwhile `updated_date_from` and `updated_date_to` filter by update date. Both ends are inclusive.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-invoices",
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "oauth2": [
              "invoice:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          },
          {
            "name": "patient_id",
            "in": "query",
            "required": false,
            "description": "Filter invoices to those associated with the specified patient. The value should be a UUID corresponding to a patient within the practice.\n",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "is_paid",
            "in": "query",
            "required": false,
            "description": "Filter invoices to those that have been paid or unpaid.\n",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-invoices-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/invoices/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get invoice by ID",
        "description": "Returns the **single invoice** matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing invoices.\n\nIf no invoice exists for that practice and `id`, the API responds with **404**.\n",
        "operationId": "get-invoice",
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "oauth2": [
              "invoice:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-invoice-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/invoices/{id}/invoice_items": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List invoice items",
        "description": "Returns a **paginated** list of invoice items for the invoice\nidentified by `id` in the path, within the practice identified by `X-Practice-Id`. Results are ordered by\n**creation time**, newest first (`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameters allow filtering by created and updated date ranges.\n\n**Date range.** Optional query parameters `created_date_from` and\n`created_date_to` filter by creation date, while `updated_date_from` and\n`updated_date_to` filter by update date. Both ends are inclusive.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-invoice-invoice-items",
        "tags": [
          "Invoices"
        ],
        "security": [
          {
            "oauth2": [
              "invoice:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-invoice-invoice-items-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/nhs/contracts": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List NHS contracts",
        "description": "Returns a paginated list of NHS contracts for the practice identified by\n`X-Practice-Id`.\n\nWhen `site_id` is supplied, the response includes only contracts assigned\nto that site. Contracts with a null `site_id` are not included.\n\nResults are ordered by creation time and ID, newest first (`created_at`\ndescending, then `id` descending). Use `limit` and the `meta.cursor` value\nfrom the response to retrieve further pages.\n",
        "operationId": "nhs-list-contracts",
        "tags": [
          "NHS Contracts"
        ],
        "security": [
          {
            "oauth2": [
              "nhs:contract:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-nhs-contracts-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/nhs/contracts/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get NHS contract by ID",
        "description": "Returns the single NHS contract matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing NHS\ncontracts.\n\nIf no NHS contract exists for that practice and `id`, the API responds with\n404.\n",
        "operationId": "nhs-get-contract",
        "tags": [
          "NHS Contracts"
        ],
        "security": [
          {
            "oauth2": [
              "nhs:contract:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-nhs-contract-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/calendar_zones": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List calendar zones",
        "description": "Returns a paginated list of calendar zones for the practice identified by\n`X-Practice-Id`. A calendar zone is one occurrence of a scheduled, recurring\nblock of diary time reserved for a specific purpose, for a practitioner or a\nroom.\n\n**Required query parameters:** `date_from` and `date_to` (inclusive,\n`YYYY-MM-DD`). Calendar zones that overlap the window are returned: a\ncalendar zone is included when it starts on or before the end of `date_to`\nand finishes on or after the start of `date_from`. Past and future dates\nare accepted. `date_to` must be on or after `date_from`, and the window must\nnot exceed **90 days**; otherwise the API responds with **422**.\n\nWhen `practitioner_id` is supplied, only calendar zones scheduled for that\npractitioner are returned. A `practitioner_id` that is not a valid UUID\nresults in **422**.\n\nResults are ordered by start time and ID, earliest first (`start_time`\nascending, then `id` ascending). Use `limit` and the `meta.cursor` value\nfrom the response to retrieve further pages.\n\n**Note:** calendar zones were known as session appointments\n(`session_appointments`) in the previous API version.\n",
        "operationId": "list-calendar-zones",
        "tags": [
          "Calendar Zones"
        ],
        "security": [
          {
            "oauth2": [
              "calendar:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/required-date-from"
          },
          {
            "$ref": "#/components/parameters/required-date-to"
          },
          {
            "$ref": "#/components/parameters/practitioner-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-calendar-zones-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "422": {
            "$ref": "#/components/responses/unprocessable-entity-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/calendar_zones/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get calendar zone by ID",
        "description": "Returns the single calendar zone matching `id` for the practice identified\nby `X-Practice-Id`. The identifier is the same `id` returned when listing\ncalendar zones.\n\nIf no calendar zone exists for that practice and `id`, the API responds\nwith 404.\n\n**Note:** calendar zones were known as session appointments\n(`session_appointments`) in the previous API version.\n",
        "operationId": "get-calendar-zone",
        "tags": [
          "Calendar Zones"
        ],
        "security": [
          {
            "oauth2": [
              "calendar:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-calendar-zone-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/identifier_mappings": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "post": {
        "summary": "Map legacy ids to UUIDs",
        "description": "Maps legacy integer sequential ids to their UUID values for the\npractice identified by `X-Practice-Id`.\n\nThe request must include:\n- `resource` — one of `patient`, `practitioner`, `appointment`, or `invoice`\n- `ids` — between 1 and 100 inclusive legacy integer ids\n\nThe response contains a mapping only for ids that match a record. Requested\nids with no match are omitted.\n",
        "operationId": "map-identifiers",
        "tags": [
          "Identifier Mappings"
        ],
        "security": [
          {
            "oauth2": [
              "identifier_mapping:read"
            ]
          }
        ],
        "requestBody": {
          "description": "Legacy identifiers to map.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/map-identifiers-request"
              },
              "examples": {
                "map_patient_ids": {
                  "summary": "Map patient legacy ids",
                  "value": {
                    "resource": "patient",
                    "ids": [
                      42,
                      43
                    ]
                  }
                },
                "map_appointment_ids": {
                  "summary": "Map appointment legacy ids",
                  "value": {
                    "resource": "appointment",
                    "ids": [
                      1001
                    ]
                  }
                },
                "map_invoice_ids": {
                  "summary": "Map invoice legacy ids",
                  "value": {
                    "resource": "invoice",
                    "ids": [
                      501,
                      502
                    ]
                  }
                },
                "map_practitioner_ids": {
                  "summary": "Map practitioner legacy ids",
                  "value": {
                    "resource": "practitioner",
                    "ids": [
                      7
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/map-identifiers-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatment_categories": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List treatment categories",
        "description": "Returns a **paginated** list of treatment categories for the practice identified by\n`X-Practice-Id`. Treatment categories are the folders a practice uses to group its\ntreatment catalogue.\n\n**Practice-wide:** treatment categories belong to the practice as a whole, not to a\nsite. This endpoint does not accept a `site_id` filter, and every treatment category\nfor the practice is returned, whichever site a treatment is used at.\n\nResults are ordered by **creation time**, latest first (`created_at` descending),\nthen by `id` descending for a stable sort.\n\nOptional date filters (`created_date_from`, `created_date_to`, `updated_date_from`,\n`updated_date_to`) restrict results by creation or last update date. When omitted,\nthe whole catalogue is returned.\n",
        "operationId": "list-treatment-categories",
        "tags": [
          "Treatment Categories"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-treatment-categories-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatment_categories/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get treatment category by ID",
        "description": "Returns the single treatment category matching `id` for the practice identified by\n`X-Practice-Id`. The identifier is the same `id` returned when listing treatment\ncategories.\n\n**Practice-wide:** treatment categories belong to the practice as a whole, not to a\nsite. Lookup is by practice and `id` only; no `site_id` is needed or accepted.\n\nIf no treatment category exists for that practice and `id`, the API responds with\n404.\n",
        "operationId": "get-treatment-category",
        "tags": [
          "Treatment Categories"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-treatment-category-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatment_plans": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List treatment plans",
        "description": "Returns a **paginated** list of treatment plans for the practice identified by\n`X-Practice-Id`. Results are ordered by **creation time**, newest first\n(`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameters allow filtering by patient, practitioner, site, start date, completed date,\ncreated/updated date ranges and if the treatment plan is completed.\n\nWhen `is_completed` is `true`, results are restricted to plans that are completed. \nWhen `false`, results are restricted to plans that have not been completed. \nWhen omitted, all treatment plans are returned.\n\n**Date range.** Optional query parameters `created_date_from` and\n`created_date_to` filter by creation date, while `updated_date_from` and\n`updated_date_to` filter by update date. Additionally, `start_date_from` and\n`start_date_to` filter by start date, and `completed_date_from` and\n`completed_date_to` filter by completed at date. Both ends are inclusive.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-treatment-plans",
        "tags": [
          "Treatment Plans"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/site-id"
          },
          {
            "$ref": "#/components/parameters/practitioner-id"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          },
          {
            "name": "patient_id",
            "in": "query",
            "required": false,
            "description": "Filter treatment plans to those associated with the specified patient. The value should be a UUID corresponding to a patient within the practice.\n",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "is_completed",
            "in": "query",
            "required": false,
            "description": "Filter treatment plans to those those that have been completed or incompleted.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "start_date_from",
            "in": "query",
            "required": false,
            "description": "Inclusive start of the start date range (`YYYY-MM-DD`). \nUse together with `start_date_to` for explicit date range control.\n- When used together with `start_date_to`, the range between the two values must not exceed 90 days.\n- When used without `start_date_to`, returns records from `start_date_from` up to 90 days later\n(or up to the current date if it is earlier).\n",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-01-01"
            }
          },
          {
            "name": "start_date_to",
            "in": "query",
            "required": false,
            "description": "Inclusive end of the start date range (`YYYY-MM-DD`). Use together with `start_date_from` for explicit date range control. - When used together with `start_date_from`, the range between the two values must not exceed 90 days. - When used without `start_date_from`, returns records from 90 days before `start_date_to` (or from the earliest available date if less than 90 days of data exists) up to `start_date_to`.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-03-31"
            }
          },
          {
            "name": "completed_date_from",
            "in": "query",
            "required": false,
            "description": "Inclusive start of the completed date range (`YYYY-MM-DD`). \nUse together with `completed_date_to` for explicit date range control.\n- When used together with `completed_date_to`, the range between the two values must not exceed 90 days.\n- When used without `completed_date_to`, returns records from `completed_date_from` up to 90 days later\n(or up to the current date if it is earlier).\n",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-01-01"
            }
          },
          {
            "name": "completed_date_to",
            "in": "query",
            "required": false,
            "description": "Inclusive end of the completed date range (`YYYY-MM-DD`).\nUse together with `completed_date_from` for explicit date range control.\n- When used together with `completed_date_from`, the range between the two values must not exceed 90 days.\n- When used without `completed_date_from`, returns records from 90 days before `completed_date_to` (or from the\nearliest available date if less than 90 days of data exists) up to `completed_date_to`.\n",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-03-31"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-treatment-plans-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatment_plans/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get treatment plan by ID",
        "description": "Returns the **single treatment plan** matching `id` for the practice identified by `X-Practice-Id`. The identifier is the same `id` returned when listing treatment plans.\nIf no treatment plan exists for that practice and `id`, the API responds with **404**.",
        "operationId": "get-treatment-plan",
        "tags": [
          "Treatment Plans"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-treatment-plan-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatment_plans/{id}/treatment_plan_items": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List treatment plan items",
        "description": "Returns a **paginated** list of treatment plan items for the treatment plan\nidentified by `id` in the path, within the practice identified by `X-Practice-Id`. Results are ordered by\n**creation time**, newest first (`created_at` descending), then by `id` descending for a stable sort.\n\nOptional query parameters allow filtering by created/updated date ranges.\n\n**Date range.** Optional query parameters `created_date_from` and\n`created_date_to` filter by creation date, while `updated_date_from` and\n`updated_date_to` filter by update date. Both ends are inclusive.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-treatment-plan-treatment-plan-items",
        "tags": [
          "Treatment Plan Items"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-treatment-plan-treatment-plan-items-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatments": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "List treatments",
        "description": "Returns a **paginated** list of treatments for the practice identified by\n`X-Practice-Id`. Treatments are the practice-level catalogue of procedures\nthat can be assigned to a patient treatment plan.\n\n**Practice-wide:** treatments belong to the practice as a whole, not to a\nsite. This endpoint does not accept a `site_id` filter, and every treatment\nfor the practice is returned, whichever site a treatment is used at.\n\nResults are ordered by **creation time**, latest first (`created_at`\ndescending), then by `id` descending for a stable sort.\n\nOptional query parameter `is_active`, when `true`, restricts results to\nactive treatments. When `false`, restricts results to inactive treatments.\nWhen omitted, all treatments are returned.\n\nOptional date filters (`created_date_from`, `created_date_to`,\n`updated_date_from`, `updated_date_to`) restrict results by creation or last\nupdate date. When omitted, the whole catalogue is returned.\n",
        "operationId": "list-treatments",
        "tags": [
          "Treatments"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/is_active"
          },
          {
            "$ref": "#/components/parameters/created-date-from"
          },
          {
            "$ref": "#/components/parameters/created-date-to"
          },
          {
            "$ref": "#/components/parameters/updated-date-from"
          },
          {
            "$ref": "#/components/parameters/updated-date-to"
          },
          {
            "name": "treatment_category_id",
            "in": "query",
            "required": false,
            "description": "Filter treatments to those in the specified treatment category. The value should be a UUID.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-treatments-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/treatments/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/x-practice-id"
        }
      ],
      "get": {
        "summary": "Get treatment by ID",
        "description": "Returns the single treatment matching `id` for the practice identified by\n`X-Practice-Id`. Treatments are practice-wide. The identifier is the same\n`id` returned when listing treatments.\n\nIf no treatment exists for that practice and `id`, the API responds with\n404.\n",
        "operationId": "get-treatment",
        "tags": [
          "Treatments"
        ],
        "security": [
          {
            "oauth2": [
              "treatment:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-treatment-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/market/subscriptions": {
      "get": {
        "summary": "List subscriptions",
        "description": "Returns a **paginated** list of subscriptions for for the authenticated product client. \nResults are ordered by **creation time**, earliest first (`created_at` descending), \nthen by `id` descending for a stable sort.\n\nUse `limit` and the `meta.cursor` value from the response to retrieve further pages.\n",
        "operationId": "list-subscriptions",
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "oauth2": [
              "subscription:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/list-subscriptions-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    },
    "/market/subscriptions/{id}": {
      "get": {
        "summary": "Get subscription",
        "description": "Returns the **single subscription** matching `id`. \nThe identifier is the same `id` returned when listing subscriptions.\n\nIf no subscription exists for that `id`, the API responds with **404**.\n",
        "operationId": "get-subscription",
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "oauth2": [
              "subscription:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/get-subscription-response"
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      },
      "delete": {
        "summary": "Delete subscription",
        "description": "Deletes the active subscription matching `id`, terminating it immediately.\nIf no subscription exists for that `id`, the API responds with **404**.",
        "operationId": "delete-subscription",
        "tags": [
          "Subscriptions"
        ],
        "security": [
          {
            "oauth2": [
              "subscription:manage"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/resource-id"
          }
        ],
        "responses": {
          "204": {
            "description": "Subscription successfully deleted."
          },
          "400": {
            "$ref": "#/components/responses/bad-request-response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized-response"
          },
          "404": {
            "$ref": "#/components/responses/not-found-response"
          },
          "4XX": {
            "$ref": "#/components/responses/user-error-response"
          },
          "5XX": {
            "$ref": "#/components/responses/server-error-response"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      },
      "oauth2": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.api.dentally.co/oauth/token",
            "scopes": {
              "fee:read": "List and retrieve fees.",
              "patient:write": "Create and modify patient records for a practice.",
              "patient:read": "List and retrieve patients.",
              "appointment:read": "List and retrieve appointments.",
              "appointment:write": "Create and modify appointments.",
              "calendar:read": "List and retrieve calendar zones.",
              "communication:write": "Send communications to patients on behalf of a practice.",
              "communication:read": "List and retrieve communications sent to patients on behalf of a practice or replies received from patients.",
              "communication:external:write": "Log externally created communications that were sent to patients on behalf of a practice.",
              "communication:external:sms:write": "Log externally created SMS communications that were sent to the patients on behalf of a practice.",
              "invoice:read": "List and retrieve invoices.",
              "account:read": "Retrieve patient account balances.",
              "fee_schedule:read": "List and retrieve fee schedules.",
              "nhs:contract:read": "List and retrieve NHS contracts.",
              "site:read": "List and retrieve sites.",
              "practitioner:read": "List and retrieve practitioners.",
              "practitioner:rota_schedule:read": "List rota schedule history for a practitioner.",
              "practitioner:availability:read": "List practitioner availability slots for booking.",
              "subscription:read": "List and retrieve subscriptions.",
              "subscription:manage": "Manage subscriptions.",
              "identifier_mapping:read": "List UUID for a resource",
              "treatment:read": "List and retrieve treatment information, including treatments and treatment categories."
            }
          }
        }
      }
    },
    "parameters": {
      "x-practice-id": {
        "name": "X-Practice-Id",
        "in": "header",
        "required": true,
        "description": "UUID of the **practice** in whose context the request is executed. The API\nuses this to resolve data the caller is permitted to access for that practice.\n",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of records to return per page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Cursor reference to the next page of records.",
        "schema": {
          "type": "string"
        }
      },
      "site-id": {
        "name": "site_id",
        "in": "query",
        "required": false,
        "description": "Filter records to those occurring at the specified site. The value should be a UUID corresponding to a site within the practice.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "created-date-from": {
        "name": "created_date_from",
        "in": "query",
        "required": false,
        "description": "Inclusive start of a created date range filter. Calendar date only (`YYYY-MM-DD`).\nUse together with `created_date_to` for explicit date range control.\n- When used together with `created_date_to`, the range between the two values must not exceed 90 days.\n- When used without `created_date_to`, returns records from `created_date_from` up to 90 days later\n(or up to the current date-time if it is earlier).\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-01-01"
        }
      },
      "created-date-to": {
        "name": "created_date_to",
        "in": "query",
        "required": false,
        "description": "Inclusive end of a created date range filter. Calendar date only (`YYYY-MM-DD`).\nUse together with `created_date_from` for explicit date range control.\n- When used together with `created_date_from`, the range between the two values must not exceed 90 days.\n- When used without `created_date_from`, returns records from 90 days before `created_date_to` (or from the\nearliest available date if less than 90 days of data exists) up to `created_date_to`.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-01-01"
        }
      },
      "updated-date-from": {
        "name": "updated_date_from",
        "in": "query",
        "required": false,
        "description": "Inclusive start of an updated date range filter. Calendar date only (`YYYY-MM-DD`).\nUse together with `updated_date_to` for explicit date range control.\n- When used together with `updated_date_to`, the range between the two values must not exceed 90 days.\n- When used without `updated_date_to`, returns records from `updated_date_from` up to 90 days later\n(or up to the current date-time if it is earlier).\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-01-01"
        }
      },
      "updated-date-to": {
        "name": "updated_date_to",
        "in": "query",
        "required": false,
        "description": "Inclusive end of an updated date range filter. Calendar date only (`YYYY-MM-DD`).\nUse together with `updated_date_from` for explicit date range control.\n- When used together with `updated_date_from`, the range between the two values must not exceed 90 days.\n- When used without `updated_date_from`, returns records from 90 days before `updated_date_to` (or from the\nearliest available date if less than 90 days of data exists) up to `updated_date_to`.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2026-01-01"
        }
      },
      "resource-id": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Resource identifier to filter/find.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "is_active": {
        "name": "is_active",
        "in": "query",
        "required": false,
        "description": "- When `true`, only records with `active: true` are returned.\n- When `false`, only records with `active: false` are returned. \n- When omitted, all records are returned.\n",
        "schema": {
          "type": "boolean",
          "example": true
        }
      },
      "date-from": {
        "name": "date_from",
        "in": "query",
        "required": false,
        "description": "Inclusive start of a date range filter (`YYYY-MM-DD`). Pair with\n`date_to` when an endpoint supports bounded date-range queries. Specific range\nlimits and defaults are defined per endpoint.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2025-01-01"
        }
      },
      "date-to": {
        "name": "date_to",
        "in": "query",
        "required": false,
        "description": "Inclusive end of a date range filter (`YYYY-MM-DD`). Pair with\n`date_from` when an endpoint supports bounded date-range queries. Specific range\nlimits and defaults are defined per endpoint.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2025-03-31"
        }
      },
      "required-date-from": {
        "name": "date_from",
        "in": "query",
        "required": true,
        "description": "Inclusive start of a required date range filter (`YYYY-MM-DD`). Pair with\n`date_to`. Specific range limits and matching rules are defined per\nendpoint.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2025-01-01"
        }
      },
      "required-date-to": {
        "name": "date_to",
        "in": "query",
        "required": true,
        "description": "Inclusive end of a required date range filter (`YYYY-MM-DD`). Pair with\n`date_from`. Specific range limits and matching rules are defined per\nendpoint.\n",
        "schema": {
          "type": "string",
          "format": "date",
          "example": "2025-03-31"
        }
      },
      "practitioner-id": {
        "name": "practitioner_id",
        "in": "query",
        "required": false,
        "description": "Filter records to those associated with the specified practitioner. The value should be a UUID corresponding to a practitioner within the practice.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "schemas": {
      "appointment-state": {
        "type": "string",
        "enum": [
          "Pending",
          "Confirmed",
          "Arrived",
          "In surgery",
          "Completed",
          "Cancelled",
          "Did not attend"
        ],
        "description": "Current state of the appointment.",
        "example": "Pending"
      },
      "entity-timestamps": {
        "type": "object",
        "required": [
          "created_at",
          "updated_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the resource was created (UTC, ISO 8601) in UTC.",
            "example": "2024-01-15T09:30:00Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the resource was last updated (UTC, ISO 8601) in UTC.",
            "example": "2024-06-20T14:05:22Z"
          }
        }
      },
      "patient-ref": {
        "type": "object",
        "description": "The patient associated with the parent resource. Retrieve the full patient record for additional details.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the patient.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "first_name": {
            "type": "string",
            "description": "Given (first) name as stored for the patient.",
            "example": "Jane"
          },
          "middle_name": {
            "type": "string",
            "nullable": true,
            "description": "Middle name or additional given name, when stored.",
            "example": "Marie"
          },
          "last_name": {
            "type": "string",
            "description": "Family (last) name as stored for the patient.",
            "example": "Doe"
          }
        }
      },
      "appointment-reason-ref": {
        "type": "object",
        "description": "The reason for the appointment — for example an examination, a scale and polish, or a consultation. Retrieve the full appointment reason record for additional details.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the appointment reason.",
            "example": "550e8400-e29b-41d4-a716-446655440002"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Display name of the appointment reason as shown in Dentally.",
            "example": "Routine dental check-up.",
            "readOnly": true
          }
        },
        "additionalProperties": false
      },
      "practitioner-ref": {
        "type": "object",
        "description": "The practitioner (dentist, hygienist, or other clinical professional) associated with the parent resource. Retrieve the full practitioner record for additional details.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the practitioner.",
            "example": "550e8400-e29b-41d4-a716-446655440003"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Full display name of the practitioner.",
            "example": "Dr. John Smith",
            "readOnly": true
          }
        }
      },
      "created_at": {
        "type": "string",
        "format": "date-time",
        "description": "When the resource was created (UTC, ISO 8601) in UTC.",
        "example": "2024-01-15T09:30:00Z"
      },
      "updated_at": {
        "type": "string",
        "format": "date-time",
        "description": "When the resource was last updated (UTC, ISO 8601) in UTC.",
        "example": "2024-06-20T14:05:22Z"
      },
      "appointment": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Appointment"
            ]
          },
          {
            "type": "object",
            "description": "An appointment record representing a scheduled or completed appointment for a patient at a practice.",
            "required": [
              "id",
              "patient",
              "start_time",
              "finish_time",
              "duration_minutes",
              "site_id",
              "practitioner"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the appointment.",
                "example": "123e4567-e89b-12d3-a456-426614174000",
                "readOnly": true
              },
              "patient": {
                "$ref": "#/components/schemas/patient-ref"
              },
              "start_time": {
                "type": "string",
                "format": "date-time",
                "description": "Start time of the appointment in ISO 8601 format in UTC.",
                "example": "2026-01-01T09:00:00Z"
              },
              "finish_time": {
                "type": "string",
                "format": "date-time",
                "description": "Finish time of the appointment in ISO 8601 format in UTC.",
                "example": "2026-01-01T10:00:00Z"
              },
              "duration_minutes": {
                "type": "integer",
                "description": "Duration of the appointment in minutes.",
                "example": 60,
                "readOnly": true
              },
              "reason": {
                "type": "object",
                "nullable": true,
                "allOf": [
                  {
                    "$ref": "#/components/schemas/appointment-reason-ref"
                  }
                ]
              },
              "notes": {
                "type": "string",
                "nullable": true,
                "description": "Additional notes about the appointment.",
                "example": "Patient requested a morning appointment."
              },
              "practitioner": {
                "type": "object",
                "nullable": true,
                "allOf": [
                  {
                    "$ref": "#/components/schemas/practitioner-ref"
                  }
                ]
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "description": "Identifier of the site where the appointment is scheduled.",
                "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                "readOnly": true
              },
              "state": {
                "$ref": "#/components/schemas/appointment-state",
                "readOnly": true
              },
              "cancelled_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Timestamp of when the appointment was cancelled, if applicable.",
                "example": "2026-01-02T12:00:00Z",
                "readOnly": true
              },
              "payment_plan_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the payment plan associated with this appointment, if applicable.",
                "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
              },
              "room_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the room where the appointment is scheduled, if applicable.",
                "example": "550e8400-e29b-41d4-a716-446655440004"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "meta": {
        "type": "object",
        "description": "Cursor-based pagination metadata. When an operation supports paging, pass `cursor` from this object on a subsequent request to continue after the current page.",
        "required": [
          "cursor"
        ],
        "properties": {
          "cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque pagination cursor for the next page. Clients should treat this value as an opaque token.\n",
            "example": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        },
        "additionalProperties": false
      },
      "problem-details": {
        "type": "object",
        "additionalProperties": true,
        "minProperties": 1,
        "description": "The Problem Details JSON Object [[RFC7807](https://tools.ietf.org/html/rfc7807)].\n",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference [[RFC3986](https://tools.ietf.org/html/rfc3986)] that\nidentifies the problem type. It should provide human-readable\ndocumentation for the problem type. When this member is not present, its\nvalue is assumed to be \"about:blank\".\n",
            "format": "uri",
            "example": "https://httpstatuses.io/400"
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.",
            "example": "Bad Request"
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code.",
            "minimum": 400,
            "maximum": 599,
            "example": 400
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem.",
            "example": "Missing required field 'address'"
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence of the problem.  It may or may not yield further information if de-referenced.",
            "example": "/v2/sites"
          }
        },
        "example": {
          "type": "https://httpstatuses.io/400",
          "title": "Bad Request",
          "status": 400,
          "detail": "Missing required field 'address'",
          "instance": "/api/v1/physical-post/letters",
          "traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00"
        }
      },
      "bad-request": {
        "allOf": [
          {
            "$ref": "#/components/schemas/problem-details"
          }
        ],
        "example": {
          "type": "https://httpstatuses.io/400",
          "title": "The Name field is required.",
          "detail": "The Name field is required.",
          "status": 400,
          "traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00"
        }
      },
      "unauthorized": {
        "allOf": [
          {
            "$ref": "#/components/schemas/problem-details"
          }
        ],
        "example": {
          "type": "https://httpstatuses.io/401",
          "title": "Unauthorized",
          "status": 401,
          "traceId": "48DCED5A-79E0-4205-9392-24EB70E391BA"
        }
      },
      "server-error": {
        "allOf": [
          {
            "$ref": "#/components/schemas/problem-details"
          }
        ],
        "example": {
          "type": "https://httpstatuses.io/500",
          "title": "Internal Server Error",
          "detail": "An unexpected error occurred while processing your request.",
          "status": 500,
          "traceId": "638736D7-ACFB-4210-BFFF-DBD4A6C31569"
        }
      },
      "create-appointment-request": {
        "type": "object",
        "description": "Fields accepted when creating an appointment.",
        "required": [
          "patient_id",
          "practitioner_id",
          "start_time",
          "reason_id"
        ],
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID of the patient associated with the appointment. The patient must be active within the practice and not blocked from booking appointments."
          },
          "practitioner_id": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID of an active practitioner within the practice. The appointment site (`site_id`) is determined from this practitioner's assigned site."
          },
          "room_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "(Optional) The UUID of the room where the appointment will take place. If provided, this should correspond to a room within the specified site."
          },
          "start_time": {
            "type": "string",
            "format": "date-time",
            "description": "The start time of the appointment in ISO 8601 format. The time should be specified in UTC."
          },
          "duration_minutes": {
            "type": "integer",
            "maximum": 120,
            "description": "(Optional) The duration of the appointment in minutes. If omitted, the practice's minimum appointment duration is used. When provided, must be greater than or equal to the practice's minimum appointment duration and less than or equal to 120 minutes."
          },
          "reason_id": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID of an active appointment reason configured for the practice."
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "description": "(Optional) Additional notes or comments about the appointment."
          }
        },
        "additionalProperties": false
      },
      "unprocessable-entity": {
        "allOf": [
          {
            "$ref": "#/components/schemas/problem-details"
          }
        ],
        "example": {
          "type": "https://httpstatuses.io/422",
          "title": "Unprocessable Entity",
          "status": 422,
          "detail": "start_time must be before finish_time.",
          "traceId": "48DCED5A-79E0-4205-9392-24EB70E391BA"
        }
      },
      "not-found": {
        "allOf": [
          {
            "$ref": "#/components/schemas/problem-details"
          }
        ],
        "example": {
          "type": "https://httpstatuses.io/404",
          "title": "Not Found",
          "detail": "Could not find a practice matching id X.",
          "status": 404,
          "traceId": "19565C8F-29D3-44E4-9457-0EE49587E3E3"
        }
      },
      "update-appointment-request": {
        "type": "object",
        "description": "Fields accepted when updating an appointment. Only the provided fields will be modified; omitted fields remain unchanged.",
        "properties": {
          "start_time": {
            "type": "string",
            "format": "date-time",
            "description": "The new start time of the appointment in ISO 8601 format. The time should be specified in UTC."
          },
          "duration_minutes": {
            "type": "integer",
            "maximum": 120,
            "description": "(Optional) The duration of the appointment in minutes. When provided, must be greater than or equal to the practice's minimum appointment duration and less than or equal to 120 minutes."
          },
          "reason_id": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID of an active appointment reason configured for the practice."
          }
        },
        "additionalProperties": false
      },
      "cancel-appointment-request": {
        "type": "object",
        "description": "Fields accepted when cancelling an appointment.",
        "required": [
          "cancellation_reason_id"
        ],
        "properties": {
          "cancellation_reason_id": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID of the cancellation reason. This should correspond to a cancellation reason configured for the practice."
          }
        },
        "additionalProperties": false
      },
      "appointment-reason": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "An **appointment reason** describes the purpose of a patient visit (for example an examination, a scale and polish, or a consultation).",
            "required": [
              "id",
              "name"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for this appointment reason within the practice.",
                "example": "4EE0FA3E-12F4-4942-9347-1702EB89EBCC"
              },
              "name": {
                "type": "string",
                "description": "The name of the appointment reason as displayed in Dentally.",
                "example": "Exam + Scale & Polish"
              },
              "is_active": {
                "type": "boolean",
                "description": "Whether the appointment reason is active and available for use in Dentally.",
                "example": true
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "appointment-cancellation-reason": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "An **appointment cancellation reason** describes and tracks both who initiated the cancellation, and what the reason for it was. This information is aggregated into reporting for the practice.",
            "required": [
              "id",
              "name",
              "type"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the appointment cancellation reason within the practice.",
                "example": "A5AD2D60-B4A1-4092-B31F-3EF9577588E6"
              },
              "name": {
                "type": "string",
                "description": "The appointment cancellation reason as displayed in Dentally.",
                "example": "Patient - Illness"
              },
              "type": {
                "type": "string",
                "enum": [
                  "cancelled",
                  "did_not_attend"
                ],
                "description": "The underlying type or outcome of an appointment cancellation reason (`cancelled` / `did_not_attend`).",
                "example": "cancelled"
              },
              "is_active": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether the appointment cancellation reason is active and available for use in Dentally.",
                "example": true
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "address": {
        "type": "object",
        "description": "Physical mailing or street address for a location. Field meanings depend on the\ncountry or region (for example, what appears in `administrative_area` in one\ncountry may differ from another). Every field may be `null` if it has not been\nsupplied; the object is still returned so clients can rely on a stable shape.\nWhen provided, **fully replaces** the patient's stored address: each field is set to the value sent. \n\nFor **update** operations, the address is replacing the\nprevious value for all fields. Omit `address` entirely to leave the stored address unchanged.\n",
        "properties": {
          "address_line_1": {
            "type": "string",
            "nullable": true,
            "description": "Primary street line (building number, street name, or equivalent).",
            "example": "42 High Street"
          },
          "address_line_2": {
            "type": "string",
            "nullable": true,
            "description": "Secondary street line (flat, suite, district, or equivalent), if applicable.",
            "example": "Suite 2"
          },
          "address_line_3": {
            "type": "string",
            "nullable": true,
            "description": "Third address line. Meaning varies by country: in some regions (for example Australia and New Zealand) this line typically holds **suburb**; elsewhere it may be any extra line needed after `address_line_1` and `address_line_2`.",
            "example": "Suburbia"
          },
          "locality": {
            "type": "string",
            "nullable": true,
            "description": "City, town, or other local place name, as used in that country.",
            "example": "London"
          },
          "administrative_area": {
            "type": "string",
            "nullable": true,
            "description": "First-level subdivision when applicable for that country (for example state, province, county, or region—whichever is conventional for that address).",
            "example": "Greater London"
          },
          "postal_code": {
            "type": "string",
            "nullable": true,
            "description": "Postal or ZIP code for that country, in the format stored for the address (not normalised to a single global format).",
            "example": "EC1A 1BB"
          }
        },
        "additionalProperties": false
      },
      "ethnicity": {
        "type": "string",
        "enum": [
          "01",
          "02",
          "03",
          "04",
          "05",
          "06",
          "07",
          "08",
          "09",
          "10",
          "11",
          "12",
          "13",
          "14",
          "15",
          "16",
          "17",
          "18",
          "97",
          "98",
          "99"
        ],
        "description": "NHS ethnicity code for the patient, expressed as a two-digit zero-padded string\n(for example `\"01\"`). Ethnicity is collected for UK practices that support patient\nethnicity (England, Wales, Northern Ireland, Channel Islands, and Isle of Man).\n\n**Post–April 2026 codes** (England and Wales practices with NHS contract reform)\n\n- `01` — White: English or Welsh or Scottish or Northern Irish or British\n- `02` — White: Irish\n- `03` — White: Any other White background\n- `04` — Mixed multiple ethnic groups: White and Black Caribbean\n- `05` — Mixed multiple ethnic groups: White and Black African\n- `06` — Mixed multiple ethnic groups: White and Asian\n- `07` — Mixed multiple ethnic groups: Any other Mixed or Multiple ethnic background\n- `08` — Asian or Asian British: Indian\n- `09` — Asian or Asian British: Pakistani\n- `10` — Asian or Asian British: Bangladeshi\n- `11` — Asian or Asian British: Any other Asian background\n- `12` — Black or African or Caribbean or Black British: Caribbean\n- `13` — Black or African or Caribbean or Black British: African\n- `14` — Black or African or Caribbean or Black British: Other Black or African or Caribbean background\n- `15` — Asian or Asian British: Chinese\n- `16` — Other Ethnic Group: Any other Ethnic Group\n- `17` — White: Gypsy or Irish Traveller\n- `18` — Other Ethnic Group: Arab\n- `97` — Other: Ethnicity Not Stated\n- `98` — Other: Patient Ethnicity Unknown\n- `99` — Other: Patient declined\n",
        "example": "01"
      },
      "biological-sex": {
        "type": "string",
        "enum": [
          "male",
          "female"
        ],
        "description": "Biological sex recorded for the patient (`male` / `female`)",
        "example": "male"
      },
      "phone_type": {
        "type": "string",
        "enum": [
          "home",
          "mobile",
          "work"
        ],
        "description": "Home, mobile, or work — how Dentally categorises patient phone numbers.",
        "example": "home"
      },
      "phone": {
        "type": "object",
        "description": "A single contact number (home, mobile, or work) with optional country and normalised forms, aligned with how Dentally stores phone fields on the patient record.",
        "required": [
          "phone_type"
        ],
        "properties": {
          "phone_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/phone_type"
              }
            ],
            "description": "Which patient phone slot this row maps to in Dentally."
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Raw number as stored for the practice (not necessarily E.164).",
            "example": "01234567890"
          },
          "phone_country": {
            "type": "string",
            "nullable": true,
            "description": "ISO-style country code for interpreting `phone_number`, when set.",
            "example": "NZ"
          },
          "phone_number_normalized": {
            "type": "string",
            "nullable": true,
            "description": "Normalised representation (for example E.164) when available.",
            "example": "+641234567890"
          }
        },
        "additionalProperties": false
      },
      "patient-communication": {
        "type": "object",
        "description": "Patient communication and marketing preferences.",
        "required": [
          "is_marketing_enabled",
          "is_email_enabled",
          "is_sms_enabled"
        ],
        "properties": {
          "is_marketing_enabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the patient accepts marketing communications; `null` if unspecified.",
            "example": true
          },
          "is_email_enabled": {
            "type": "boolean",
            "description": "Whether the patient accepts email communications.",
            "example": true
          },
          "is_sms_enabled": {
            "type": "boolean",
            "description": "Whether the patient accepts SMS communications.",
            "example": false
          }
        },
        "additionalProperties": false
      },
      "patient-recall-method": {
        "type": "string",
        "enum": [
          "letter",
          "sms",
          "email",
          "phone"
        ],
        "description": "Preferred method for patient recall communications.",
        "example": "email"
      },
      "patient-recall": {
        "type": "object",
        "description": "Patient recall schedule and preferred contact method.",
        "required": [
          "dentist",
          "hygienist",
          "method"
        ],
        "properties": {
          "dentist": {
            "type": "object",
            "description": "Dentist recall schedule.",
            "required": [
              "date",
              "interval_months"
            ],
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "nullable": true,
                "description": "Next dentist recall date (`YYYY-MM-DD`); `null` when not scheduled.",
                "example": "2026-03-15"
              },
              "interval_months": {
                "type": "integer",
                "minimum": 0,
                "maximum": 24,
                "description": "Recall interval in months.",
                "example": 6
              }
            },
            "additionalProperties": false
          },
          "hygienist": {
            "type": "object",
            "description": "Hygienist recall schedule.",
            "required": [
              "date",
              "interval_months"
            ],
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "nullable": true,
                "description": "Next hygienist recall date (`YYYY-MM-DD`); `null` when not scheduled.",
                "example": "2026-04-01"
              },
              "interval_months": {
                "type": "integer",
                "minimum": 0,
                "maximum": 24,
                "description": "Recall interval in months.",
                "example": 6
              }
            },
            "additionalProperties": false
          },
          "method": {
            "type": "string",
            "nullable": true,
            "description": "Preferred recall contact method; `null` if unspecified.",
            "allOf": [
              {
                "$ref": "#/components/schemas/patient-recall-method"
              }
            ]
          }
        },
        "additionalProperties": false
      },
      "patient-archived-reason": {
        "type": "string",
        "nullable": true,
        "enum": [
          "no_reason_given",
          "deceased",
          "lapsed",
          "duplicate",
          "discharged_failed_to_attend",
          "discharged_no_longer_meets_criteria",
          "discharged_treatment_complete",
          "legal_request_to_remove",
          "patient_in_arrears",
          "patient_moved_away",
          "patient_not_happy_with_service",
          "patient_opted_out_due_to_cost",
          "referral_patient",
          "test_or_created_in_error",
          "transferred_to_another_provider",
          null
        ],
        "description": "Reason a patient record was archived.\nReturns `null` when the patient is active or no reason is recorded.\n",
        "example": "lapsed",
        "x-enumDescriptions": {
          "null": "No archive reason is recorded; returned for active patients or when the reason is unset.",
          "no_reason_given": "Patient was archived without a specific reason recorded.",
          "deceased": "Patient was archived because they are deceased.",
          "lapsed": "Patient was archived due to lapse from care.",
          "duplicate": "Patient was archived as a duplicate record.",
          "discharged_failed_to_attend": "Patient was discharged for repeated failure to attend appointments.",
          "discharged_no_longer_meets_criteria": "Patient was discharged because they no longer meet practice criteria.",
          "discharged_treatment_complete": "Patient was discharged after treatment was completed.",
          "legal_request_to_remove": "Patient was archived following a legal request to remove their record.",
          "patient_in_arrears": "Patient was archived while in arrears.",
          "patient_moved_away": "Patient was archived because they moved away from the area.",
          "patient_not_happy_with_service": "Patient was archived because they were not happy with the service.",
          "patient_opted_out_due_to_cost": "Patient was archived because they opted out due to cost.",
          "referral_patient": "Patient was archived as a referral patient.",
          "test_or_created_in_error": "Patient was archived because the record was a test entry or created in error.",
          "transferred_to_another_provider": "Patient was archived because they transferred to another provider."
        }
      },
      "title": {
        "type": "string",
        "enum": [
          "Mr",
          "Mrs",
          "Miss",
          "Ms",
          "Dr",
          "Master",
          "Prof",
          "Hon",
          "Rev",
          "Sir",
          "Lady",
          "Lord",
          "Earl",
          "Judge",
          "Dame"
        ],
        "description": "The different patient titles supported by Dentally.",
        "example": "Ms"
      },
      "patient": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **patient** is a person registered with a practice: demographics, contact details, care preferences, and links to sites and payment plans.",
            "required": [
              "id",
              "first_name",
              "last_name",
              "date_of_birth",
              "title",
              "ethnicity",
              "payment_plan_id",
              "site_id",
              "address",
              "phones"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for this patient within the practice.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "is_active": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether the patient record is active;",
                "example": true
              },
              "address": {
                "description": "Patient postal address. See `components/schemas/address.yml` for field meanings.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/address"
                  }
                ]
              },
              "date_of_birth": {
                "type": "string",
                "format": "date",
                "description": "Date of birth in ISO 8601 calendar date form (`YYYY-MM-DD`).",
                "example": "1990-04-12"
              },
              "dentist_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the dentist associated with this patient for recall or care routing.",
                "example": "550e8400-e29b-41d4-a716-446655440001"
              },
              "email_address": {
                "type": "string",
                "nullable": true,
                "description": "Primary email address for contact.",
                "example": "jane.doe@example.com"
              },
              "ethnicity": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/ethnicity"
                  }
                ]
              },
              "first_name": {
                "type": "string",
                "description": "Given (first) name as stored for the patient.",
                "example": "Jane"
              },
              "middle_name": {
                "type": "string",
                "nullable": true,
                "description": "Middle name or additional given name, when stored.",
                "example": "Marie"
              },
              "last_name": {
                "type": "string",
                "description": "Family (last) name as stored for the patient.",
                "example": "Doe"
              },
              "family_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier linking this patient to a family or household group when used by the practice; otherwise `null`.",
                "example": "660e8400-e29b-41d4-a716-446655440003"
              },
              "biological_sex": {
                "type": "string",
                "nullable": true,
                "description": "Biological sex when set on the patient record; `null` when unknown or not applicable.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/biological-sex"
                  }
                ]
              },
              "phones": {
                "type": "array",
                "description": "Home, mobile, and work contact numbers from the patient record.",
                "items": {
                  "$ref": "#/components/schemas/phone"
                }
              },
              "hygienist_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the hygienist associated with this patient for recall or care routing; `null` if not assigned.",
                "example": "550e8400-e29b-41d4-a716-446655440004"
              },
              "payment_plan_id": {
                "type": "string",
                "format": "uuid",
                "description": "Identifier of the payment plan assigned to this patient.",
                "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
              },
              "preferred_name": {
                "type": "string",
                "nullable": true,
                "description": "Name the patient prefers to be called, when different from formal names.",
                "example": "Janey"
              },
              "preferred_phone_type": {
                "type": "string",
                "nullable": true,
                "description": "Preferred phone type for contact.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/phone_type"
                  }
                ],
                "example": "mobile"
              },
              "is_appointment_booking_prevented": {
                "type": "boolean",
                "nullable": true,
                "description": "When `true`, online or automated appointment booking may be blocked for this patient per practice rules.",
                "example": false
              },
              "communication": {
                "type": "object",
                "nullable": true,
                "description": "Patient communication and marketing preferences.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/patient-communication"
                  }
                ]
              },
              "recall": {
                "type": "object",
                "nullable": true,
                "description": "Patient recall schedule and preferred contact method.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/patient-recall"
                  }
                ]
              },
              "archived_reason": {
                "type": "string",
                "nullable": true,
                "description": "Reason the patient was archived; `null` when the patient is active or no reason is recorded.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/patient-archived-reason"
                  }
                ]
              },
              "is_bad_debtor": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether the patient is flagged as a bad debtor; `null` if unspecified.",
                "example": false
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "description": "Default or primary site (location) this patient is associated with.",
                "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
              },
              "title": {
                "$ref": "#/components/schemas/title"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "create-patient-request": {
        "type": "object",
        "description": "Fields accepted when creating a new patient. Required attributes cover the core demographic information needed to register a patient record.",
        "required": [
          "first_name",
          "last_name",
          "date_of_birth",
          "ethnicity",
          "site_id",
          "title"
        ],
        "properties": {
          "first_name": {
            "type": "string",
            "example": "Jane"
          },
          "last_name": {
            "type": "string",
            "example": "Doe"
          },
          "date_of_birth": {
            "type": "string",
            "format": "date",
            "description": "Date of birth in ISO 8601 format (`YYYY-MM-DD`).",
            "example": "1990-04-12"
          },
          "ethnicity": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ethnicity"
              }
            ]
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
          },
          "payment_plan_id": {
            "type": "string",
            "format": "uuid",
            "description": "Payment plan for the patient. When not provided, the default payment plan for the given site is applied.",
            "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
          },
          "title": {
            "$ref": "#/components/schemas/title"
          },
          "biological_sex": {
            "description": "Maps to the patient `gender` field at creation time.",
            "allOf": [
              {
                "$ref": "#/components/schemas/biological-sex"
              }
            ]
          },
          "email_address": {
            "type": "string",
            "nullable": true,
            "description": "Primary email address for contact.",
            "example": "jane.doe@example.com"
          },
          "address": {
            "allOf": [
              {
                "$ref": "#/components/schemas/address"
              }
            ]
          },
          "phones": {
            "type": "array",
            "description": "Contact numbers (`phone_type`, `phone_number`, and `phone_country`). Each `phone_type` maps to home, work, or mobile on the patient record.",
            "items": {
              "$ref": "#/components/schemas/phone"
            }
          }
        },
        "additionalProperties": false
      },
      "update-patient-request": {
        "type": "object",
        "description": "Fields to update on an existing patient. Omitted members are left unchanged.",
        "properties": {
          "first_name": {
            "type": "string",
            "description": "New given (first) name when updating.",
            "example": "Jane"
          },
          "last_name": {
            "type": "string",
            "description": "New family (last) name when updating.",
            "example": "Doe"
          },
          "date_of_birth": {
            "type": "string",
            "format": "date",
            "description": "New date of birth in ISO 8601 format (`YYYY-MM-DD`).",
            "example": "1990-04-12"
          },
          "ethnicity": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ethnicity"
              }
            ]
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "New default site (location) for the patient when changing association.",
            "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
          },
          "payment_plan_id": {
            "type": "string",
            "format": "uuid",
            "description": "New payment plan identifier when reassigning the patient's plan.",
            "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
          },
          "title": {
            "$ref": "#/components/schemas/title"
          },
          "biological_sex": {
            "description": "Maps to the patient `gender` field when updating.",
            "allOf": [
              {
                "$ref": "#/components/schemas/biological-sex"
              }
            ]
          },
          "email_address": {
            "type": "string",
            "nullable": true,
            "description": "Primary email address for contact.",
            "example": "jane.doe@example.com"
          },
          "address": {
            "allOf": [
              {
                "$ref": "#/components/schemas/address"
              }
            ]
          },
          "phones": {
            "type": "array",
            "description": "Contact numbers (`phone_type`, `phone_number`, and `phone_country`). Each `phone_type` maps to home, work, or mobile on the patient record.",
            "items": {
              "$ref": "#/components/schemas/phone"
            }
          }
        },
        "additionalProperties": false
      },
      "patient-account": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Account"
            ]
          },
          {
            "type": "object",
            "description": "The money position of a patient account: what the patient owes the practice, or what the practice holds in credit for them. All amounts are signed. A negative amount means money is owed to the practice. A positive amount means the account is in credit.",
            "required": [
              "owning_patient_id",
              "balance_amount",
              "patient_balance_amount",
              "pending_payments_amount",
              "deposit_amount"
            ],
            "properties": {
              "owning_patient_id": {
                "type": "string",
                "format": "uuid",
                "description": "Patient who owns the account. When this differs from the patient requested in the path, the requested patient shares this account.",
                "example": "550e8400-e29b-41d4-a716-446655440004"
              },
              "balance_amount": {
                "type": "number",
                "description": "Total balance of the account. This covers the patient's own balance, pending payments and deposits. Negative when the account owes the practice, positive when it is in credit.",
                "example": -125.5
              },
              "patient_balance_amount": {
                "type": "number",
                "description": "The part of the balance the patient is responsible for, excluding pending payments and deposits. Negative when the patient owes the practice, positive when the patient is in credit.",
                "example": -100.5
              },
              "pending_payments_amount": {
                "type": "number",
                "description": "Amounts the practice is waiting to receive from insurers or other third parties. Zero or negative, because the amounts are still owed to the practice.",
                "example": -25
              },
              "deposit_amount": {
                "type": "number",
                "description": "Value of paid deposits not yet used. Zero for practices that do not use deposits.",
                "example": 0
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "practitioner": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **practitioner** at the practice (dentist, hygienist, or other practice professional).",
            "required": [
              "id",
              "user_id",
              "site_id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the practitioner.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "name": {
                "type": "string",
                "nullable": true,
                "description": "Full display name of the linked user.",
                "example": "Jane Doe"
              },
              "user_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the user account associated with this practitioner",
                "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the site where this practitioner primarily works, when set.",
                "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
              },
              "role": {
                "type": "string",
                "nullable": true,
                "description": "The clinical role of this practitioner when they are a Dental Care\nProfessional (DCP) — a clinician who supports or works alongside\ndentists rather than practising as one.\nWhen set, one of:\n- Therapist — performs a defined range of dental treatments\n(for example fillings, extractions of deciduous teeth, and\npreventive care) under a dentist's prescription.\n- Hygienist — focuses on preventive oral care, including scaling,\npolishing, and patient education.\n- Dental Nurse — assists the clinician chairside during treatment\nand supports patient care.\n- Clinical Technician — designs, fits, and maintains dentures\nand other removable dental appliances.\nnull when the practitioner does not have a DCP role — most\ncommonly because they are a dentist, whose role is not represented\nby this field.\n",
                "example": "Hygienist"
              },
              "nhs_number": {
                "type": "string",
                "nullable": true,
                "description": "NHS number stored on the practitioner record, when present.",
                "example": "9998887777"
              },
              "gdc_number": {
                "type": "string",
                "nullable": true,
                "description": "General Dental Council registration number or regional equivalent (for example provider or payee number), when present on the practitioner record.",
                "example": "123456"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "availability-slot": {
        "type": "object",
        "description": "A bookable availability window for a practitioner within the requested date-time range. Each slot represents available time.",
        "required": [
          "start_time",
          "finish_time",
          "practitioner_id"
        ],
        "properties": {
          "start_time": {
            "type": "string",
            "format": "date-time",
            "description": "Inclusive start of the availability slot.",
            "example": "2031-12-01T09:00:00+00:00"
          },
          "finish_time": {
            "type": "string",
            "format": "date-time",
            "description": "Exclusive end of the availability slot.",
            "example": "2031-12-01T10:00:00+00:00"
          },
          "practitioner_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the practitioner this slot belongs to.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }
        },
        "additionalProperties": false
      },
      "rota-schedule-history": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **snapshotted rota day** for a practitioner: effective scheduled working hours and breaks for a single calendar date. Records are produced from the practice rota (including overrides active when the snapshot was taken) and are intended for historical reporting such as payroll hours.",
            "required": [
              "practitioner_id",
              "date",
              "is_available",
              "breaks"
            ],
            "properties": {
              "practitioner_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the practitioner this history row belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "date": {
                "type": "string",
                "format": "date",
                "description": "Calendar date this rota snapshot applies to.",
                "example": "2025-01-15"
              },
              "is_available": {
                "type": "boolean",
                "description": "Whether the practitioner was scheduled as available for clinical work on this date.",
                "example": true
              },
              "start_time": {
                "type": "string",
                "nullable": true,
                "description": "Scheduled day start time (`HH:MM`).",
                "example": "09:00"
              },
              "finish_time": {
                "type": "string",
                "nullable": true,
                "description": "Scheduled day finish time (`HH:MM`).",
                "example": "17:30"
              },
              "breaks": {
                "type": "array",
                "description": "Scheduled breaks on this date. Empty when `is_available` is `false` or there are no breaks.",
                "items": {
                  "type": "object",
                  "description": "A scheduled break on a rota day (for example lunch).",
                  "required": [
                    "name",
                    "start_time",
                    "finish_time"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Display name of the break, when set.",
                      "example": "Lunch"
                    },
                    "start_time": {
                      "type": "string",
                      "description": "Break start time (`HH:MM`).",
                      "example": "13:00"
                    },
                    "finish_time": {
                      "type": "string",
                      "description": "Break finish time (`HH:MM`).",
                      "example": "14:00"
                    }
                  },
                  "additionalProperties": false
                }
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "site-contact-details": {
        "type": "object",
        "description": "Public contact information for the site. Fields may be `null` when not provided.",
        "properties": {
          "email_address": {
            "type": "string",
            "nullable": true,
            "format": "email",
            "description": "General contact email for this location (for example reception or bookings).",
            "example": "reception@example.com"
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Primary telephone number for this location, as stored (may include country or area codes; format is not guaranteed to be normalised).",
            "example": "+44 20 7946 0958"
          },
          "website_url": {
            "type": "string",
            "nullable": true,
            "description": "Public website for this location, if any (absolute URL as stored).",
            "example": "https://www.example.com/dentally-high-street"
          }
        },
        "additionalProperties": false
      },
      "site-opening-hours": {
        "type": "object",
        "description": "Scheduled opening and closing times for one weekday. Times are in **local civil time** for the site (not UTC). Rows belong to the site's `opening_hours` array, usually ordered **Sunday** through **Saturday**.",
        "required": [
          "weekday",
          "open_at",
          "close_at"
        ],
        "properties": {
          "weekday": {
            "type": "string",
            "enum": [
              "Sunday",
              "Monday",
              "Tuesday",
              "Wednesday",
              "Thursday",
              "Friday",
              "Saturday"
            ],
            "description": "Calendar day this row describes.",
            "example": "Monday"
          },
          "open_at": {
            "type": "string",
            "nullable": true,
            "pattern": "^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$",
            "description": "Time the site opens on this weekday, **24-hour clock** (`HH:MM`). `null` means not set or closed that day (see `close_at`).",
            "example": "09:00"
          },
          "close_at": {
            "type": "string",
            "nullable": true,
            "pattern": "^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$",
            "description": "Time the site stops accepting patients or closes on this weekday, **24-hour clock** (`HH:MM`). `null` means not set or closed that day (see `open_at`).",
            "example": "17:30"
          }
        },
        "additionalProperties": false
      },
      "site": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **site** is a physical location belonging to a practice (for example a clinic or surgery).",
            "required": [
              "id",
              "name",
              "address"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Stable unique identifier for this site. Use this value when referring to the site in subsequent API calls.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "name": {
                "type": "string",
                "description": "Human-readable name of the location as shown to patients or staff (for example the practice name at this address or a branch name).",
                "example": "Dentally High Street"
              },
              "address": {
                "$ref": "#/components/schemas/address"
              },
              "contact_details": {
                "$ref": "#/components/schemas/site-contact-details"
              },
              "opening_hours": {
                "type": "array",
                "description": "Regular weekly schedule for this location. Entries are shown in order **Sunday** through **Saturday**. Each entry lists that day's `open_at` and `close_at` in **local time** for the site. `null` times mean hours are not published or the site is closed that day.",
                "maxItems": 7,
                "items": {
                  "$ref": "#/components/schemas/site-opening-hours"
                }
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "communication-message-type": {
        "type": "string",
        "enum": [
          "appointment_reminder",
          "appointment_confirmation",
          "appointment_cancellation",
          "task_reminder",
          "feedback_request",
          "marketing",
          "estimate",
          "invoice",
          "fta",
          "recall",
          "patient_reply",
          "payment_request",
          "medical_history",
          "unclassified"
        ],
        "description": "The different types of communications that can be sent to patients.",
        "x-enumDescriptions": {
          "appointment_reminder": "Communication sent to remind a patient of an upcoming appointment.",
          "appointment_confirmation": "Communication sent to confirm a patient's appointment booking.",
          "appointment_cancellation": "Communication sent to notify a patient of an appointment cancellation.",
          "task_reminder": "Communication sent to remind a patient of a task they need to complete (e.g., fill out a form).",
          "feedback_request": "Communication sent to request feedback from a patient after an appointment or interaction.",
          "marketing": "Communication sent for marketing purposes, such as promotions or newsletters.",
          "estimate": "Communication sent to provide a patient with an estimate for a treatment or procedure.",
          "invoice": "Communication sent to provide a patient with an invoice for services rendered.",
          "fta": "Communication sent to notify a patient of a missed appointment (FTA = \"Failure To Attend\").",
          "recall": "Communication sent to recall a patient for follow-up care or routine check-ups.",
          "patient_reply": "Communication that is a reply from a patient, which may be received via certain channels and logged in the system.",
          "payment_request": "Communication sent to request payment from a patient for a deposit or outstanding balance.",
          "medical_history": "Communication sent to request or provide information about a patient's medical history.",
          "unclassified": "Communication that does not fit into any of the other predefined categories."
        }
      },
      "communication-sms-message-content": {
        "type": "object",
        "description": "Request payload for sending an SMS to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "message_type",
          "body"
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who is the intended recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "maxLength": 1600,
            "description": "The main plain text content of the SMS message.",
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          }
        }
      },
      "communication-email-message-content": {
        "type": "object",
        "description": "Request payload for sending an email to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "message_type",
          "subject"
        ],
        "anyOf": [
          {
            "required": [
              "body"
            ]
          },
          {
            "required": [
              "html_body"
            ]
          }
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who is the intended recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "email"
            ]
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "description": "The main plain text content of the email message.",
            "maxLength": 50000,
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          },
          "html_body": {
            "type": "string",
            "description": "The main HTML content of the email message.\nIf not provided, the `body` content will be used as the HTML content as well.\nA maximum of 50,000 characters of text is allowed for this property.  \nThe character limit will apply to the text content only, and will not include HTML tags.\n",
            "example": "<p>Your appointment is scheduled for tomorrow at 3 PM.</p>"
          },
          "subject": {
            "type": "string",
            "nullable": true,
            "description": "Subject line for the email message.",
            "example": "Appointment Reminder"
          }
        }
      },
      "send-communication-request": {
        "description": "Request object for sending a communication to a patient.",
        "discriminator": {
          "propertyName": "communication_channel",
          "mapping": {
            "sms": "#/components/schemas/communication-sms-message-content",
            "email": "#/components/schemas/communication-email-message-content"
          }
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/communication-sms-message-content"
          },
          {
            "$ref": "#/components/schemas/communication-email-message-content"
          }
        ]
      },
      "resource_timestamps": {
        "type": "object",
        "properties": {
          "created_at": {
            "$ref": "#/components/schemas/created_at"
          },
          "updated_at": {
            "$ref": "#/components/schemas/updated_at"
          }
        }
      },
      "communication-channel": {
        "type": "string",
        "enum": [
          "sms",
          "email",
          "messaging_app",
          "phone_call",
          "letter"
        ],
        "description": "The different communication channels supported by Dentally.  \n**Note:** ONLY \"sms\" and \"email\" can be used for sending communications to patients via the API. \n",
        "x-enumDescriptions": {
          "email": "Communication sent via email.",
          "sms": "Communication sent via SMS text message.",
          "messaging_app": "Communication sent via a messaging app (e.g., WhatsApp).",
          "phone_call": "Communication done via a phone call.",
          "letter": "Communication sent via postal mail."
        }
      },
      "external-communication-sms-content": {
        "type": "object",
        "description": "Request payload for sending an SMS to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "direction",
          "message_type",
          "body"
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who is the intended recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "The direction of the communication.  \nInbound indicates that the communication was received from the patient, while \noutbound indicates that the communication was sent to the patient.\n"
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "maxLength": 1600,
            "description": "The main plain text content of the SMS message.",
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          }
        }
      },
      "external-communication-email-content": {
        "type": "object",
        "description": "Request payload for sending an email to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "direction",
          "message_type",
          "subject"
        ],
        "anyOf": [
          {
            "required": [
              "body"
            ]
          },
          {
            "required": [
              "html_body"
            ]
          }
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who is the intended recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "email"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "The direction of the communication.  \nInbound indicates that the communication was received from the patient, while \noutbound indicates that the communication was sent to the patient.\n"
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "description": "The main plain text content of the email message.",
            "maxLength": 50000,
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          },
          "html_body": {
            "type": "string",
            "maxLength": 100000,
            "description": "The main HTML content of the email message.\nIf not provided, the `body` content will be used as the HTML content as well.\nA maximum of 100,000 characters of text is allowed for this property, including all html tags and their content.  \nA 50,000 character limit will also apply to the text content only, and will not include HTML tags.\n",
            "example": "<p>Your appointment is scheduled for tomorrow at 3 PM.</p>"
          },
          "subject": {
            "type": "string",
            "nullable": true,
            "description": "Subject line for the email message.",
            "example": "Appointment Reminder"
          }
        }
      },
      "external-communication-letter-content": {
        "type": "object",
        "description": "Request payload for logging that a letter was sent to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "direction",
          "message_type"
        ],
        "anyOf": [
          {
            "required": [
              "body"
            ]
          },
          {
            "required": [
              "body_link"
            ]
          }
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who was the recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "letter"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "The direction of the communication.  \nInbound indicates that the communication was received from the patient, while \noutbound indicates that the communication was sent to the patient.\n"
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "description": "The plain text content of the letter.",
            "maxLength": 50000,
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          },
          "body_link": {
            "type": "string",
            "format": "uri",
            "description": "A link to the full content of the letter, which may be hosted on an external document storage service.\nThis can be used for letters that have content that exceeds typical size limits for API requests, or for letters that include rich formatting or attachments that cannot be represented in plain text.  \n**NOTE:** This must be a URL that is accessible to the API service with appropriate authentication (e.g. a pre-signed URL for an object in cloud storage).\n",
            "maxLength": 1600,
            "example": "https://example.com/letters/12345/content"
          }
        }
      },
      "messaging-channel": {
        "type": "string",
        "enum": [
          "whatsapp",
          "messenger",
          "signal",
          "telegram",
          "other"
        ],
        "description": "The messaging channel that is/was used to send messages to patients.  This allows for rich media messages and interactive communication."
      },
      "external-communication-messaging-app-content": {
        "type": "object",
        "description": "Request payload for logging that a was sent to a patient via messaging app.",
        "required": [
          "patient_id",
          "communication_channel",
          "direction",
          "message_type",
          "messaging_channel",
          "body"
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who was the recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "messaging_app"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "The direction of the communication.  \nInbound indicates that the communication was received from the patient, while \noutbound indicates that the communication was sent to the patient.\n"
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "messaging_channel": {
            "$ref": "#/components/schemas/messaging-channel"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "description": "The main plain text content of the messaging app message.",
            "maxLength": 1600,
            "example": "Your appointment is scheduled for tomorrow at 3 PM."
          }
        }
      },
      "external-communication-phone-call-content": {
        "type": "object",
        "description": "Request payload for logging that a phone call was made to a patient.",
        "required": [
          "patient_id",
          "communication_channel",
          "message_type",
          "body"
        ],
        "additionalProperties": false,
        "properties": {
          "patient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the patient who was the recipient of the communication."
          },
          "communication_channel": {
            "type": "string",
            "enum": [
              "phone_call"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "The direction of the communication.  \nInbound indicates that the communication was received from the patient, while \noutbound indicates that the communication was sent to the patient.\n"
          },
          "message_type": {
            "$ref": "#/components/schemas/communication-message-type"
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the site associated with the communication.",
            "example": "123e4567-e89b-12d3-a456-426614174089"
          },
          "body": {
            "type": "string",
            "description": "A summary of the phone call with the patient, which may include details such as whether the call was answered or went to voicemail, and any key information that was communicated during the call.  \n",
            "maxLength": 1600,
            "example": "Left a voicemail reminding the patient of their appointment tomorrow at 3 PM."
          }
        }
      },
      "external-communication-request": {
        "description": "Request object for creating an external communication to a patient.",
        "discriminator": {
          "propertyName": "communication_channel",
          "mapping": {
            "sms": "#/components/schemas/external-communication-sms-content",
            "email": "#/components/schemas/external-communication-email-content",
            "letter": "#/components/schemas/external-communication-letter-content",
            "messaging_app": "#/components/schemas/external-communication-messaging-app-content",
            "phone_call": "#/components/schemas/external-communication-phone-call-content"
          }
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/external-communication-sms-content"
          },
          {
            "$ref": "#/components/schemas/external-communication-email-content"
          },
          {
            "$ref": "#/components/schemas/external-communication-letter-content"
          },
          {
            "$ref": "#/components/schemas/external-communication-messaging-app-content"
          },
          {
            "$ref": "#/components/schemas/external-communication-phone-call-content"
          }
        ]
      },
      "fee-tier": {
        "type": "object",
        "description": "A pricing tier for a fee. Quantity `5` represents five or more units.",
        "required": [
          "quantity",
          "price",
          "duration_minutes"
        ],
        "properties": {
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "The number of units this tier applies to. `5` means five or more.",
            "example": 1
          },
          "price": {
            "type": "number",
            "description": "The price for this tier.",
            "example": 55
          },
          "duration_minutes": {
            "type": "integer",
            "description": "Appointment duration in minutes for this tier.",
            "example": 15
          }
        },
        "additionalProperties": false
      },
      "fee": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **fee** is the price a practice charges for one treatment under one fee schedule, so the same treatment can cost different amounts on Private, a health provider, or a membership plan. Prices and appointment durations are exposed as five ordered `tiers` (quantities 1–4 and 5 or more) rather than flat `price_*` / `duration_*` fields.",
            "required": [
              "id",
              "payment_plan_id",
              "treatment_id",
              "is_multiple_pricing",
              "tiers"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the fee.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "payment_plan_id": {
                "type": "string",
                "format": "uuid",
                "description": "The payment plan (fee schedule) id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_id": {
                "type": "string",
                "format": "uuid",
                "description": "The treatment id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "is_multiple_pricing": {
                "type": "boolean",
                "description": "When true, all five quantity-based pricing tiers are returned. When false, only the first tier (`quantity` 1 / `*_one` fields) is returned.",
                "example": true
              },
              "tiers": {
                "type": "array",
                "minItems": 1,
                "maxItems": 5,
                "description": "Pricing tiers for quantities 1, 2, 3, 4, and 5 (five or more), in that order. When `is_multiple_pricing` is true, all five tiers are included; when false, only the first tier is included.",
                "items": {
                  "$ref": "#/components/schemas/fee-tier"
                }
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "fee-schedule-funding": {
        "type": "object",
        "description": "How treatment fees on this fee schedule are split between the patient and any third party, and whether Dentally treats the schedule as a national scheme.",
        "required": [
          "type",
          "scheme",
          "claim_timing"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Who is expected to pay fees charted against this fee schedule.\n\n- `private` - the patient pays the full fee. No third-party claim is\n  filed through this funding model (NHS dentistry uses a separate claims\n  process, even when `scheme` is `nhs`).\n- `co_payment_split` - a third party meets part of the fee and the\n  patient pays the remainder.\n- `insurance_funded` - a third party is expected to meet the full fee.\n",
            "enum": [
              "private",
              "co_payment_split",
              "insurance_funded"
            ],
            "example": "private"
          },
          "scheme": {
            "type": "string",
            "nullable": true,
            "description": "National care scheme Dentally recognises for this fee schedule, when one\napplies. `null` when the schedule is practice-defined and is not a\nrecognised scheme.\n\nKnown values:\n\n- `nhs` - UK NHS\n- `nz_moh_sds` - New Zealand Ministry of Health, Special Dental Services\n- `nz_moh_ohsa` - New Zealand Ministry of Health, Oral Health Services Adolescents\n- `nz_moh_ohsa_hc` - New Zealand Ministry of Health, High Caries\n- `nz_acc` - New Zealand Accident Compensation Corporation\n\nAdditional values may be added in the future, this is an open set.\n",
            "example": "nhs"
          },
          "claim_timing": {
            "type": "string",
            "nullable": true,
            "description": "When a third-party claim is filed for items on this fee schedule. `null` when\n`type` is `private`, including NHS plans, because this funding model does\nnot file claims through this process.\n\n- `on_completion` - a claim is filed when the treatment plan is completed.\n- `on_charge` - a claim is filed each time treatment is charged.\n",
            "enum": [
              "on_completion",
              "on_charge",
              null
            ],
            "example": null
          }
        },
        "additionalProperties": false
      },
      "fee-schedule-default-appointment-duration": {
        "type": "object",
        "description": "Default appointment lengths, in minutes, used when booking common visit types for a patient on this fee schedule (examination, scale and polish, both together, or emergency). These are booking defaults, not per-treatment durations.",
        "required": [
          "exam_minutes",
          "scale_and_polish_minutes",
          "exam_scale_and_polish_minutes",
          "emergency_minutes"
        ],
        "properties": {
          "exam_minutes": {
            "type": "integer",
            "minimum": 5,
            "maximum": 120,
            "description": "Default length in minutes for an examination appointment.",
            "example": 10
          },
          "scale_and_polish_minutes": {
            "type": "integer",
            "minimum": 5,
            "maximum": 120,
            "description": "Default length in minutes for a scale and polish appointment.",
            "example": 10
          },
          "exam_scale_and_polish_minutes": {
            "type": "integer",
            "minimum": 5,
            "maximum": 120,
            "description": "Default length in minutes for a combined examination and scale and polish appointment.",
            "example": 20
          },
          "emergency_minutes": {
            "type": "integer",
            "minimum": 5,
            "maximum": 120,
            "description": "Default length in minutes for an emergency appointment.",
            "example": 10
          }
        },
        "additionalProperties": false
      },
      "fee-schedule-patient-default": {
        "type": "object",
        "description": "Suggested recall and communication values for a **new** patient assigned to\nthis fee schedule. Dentally's own user interface copies these onto the patient\nform when a receptionist creates a patient.\n\nThey are never applied automatically by the API or by the server. Creating or\nupdating a patient with a `payment_plan_id` leaves the patient's own `recall`\nand `communication` fields unchanged. Integrations that want the same starting\npoint as the Dentally UI must copy these values onto the patient record\nthemselves. Existing patients keep the values already stored on their record;\nchanging this fee schedule later does not cascade.\n",
        "required": [
          "recall",
          "communication"
        ],
        "properties": {
          "recall": {
            "type": "object",
            "description": "Default recall schedule and contact method to copy onto a new patient.",
            "required": [
              "dentist_interval_months",
              "hygienist_interval_months",
              "method"
            ],
            "properties": {
              "dentist_interval_months": {
                "type": "integer",
                "minimum": 0,
                "maximum": 24,
                "description": "Default months between dentist recalls. `0` means no dentist recall interval is suggested.",
                "example": 6
              },
              "hygienist_interval_months": {
                "type": "integer",
                "minimum": 0,
                "maximum": 24,
                "description": "Default months between hygienist recalls. `0` means no hygienist recall interval is suggested.",
                "example": 6
              },
              "method": {
                "$ref": "#/components/schemas/patient-recall-method"
              }
            },
            "additionalProperties": false
          },
          "communication": {
            "type": "object",
            "description": "Default email and SMS contact flags to copy onto a new patient. These are not the patient's live preferences.",
            "required": [
              "is_email_enabled",
              "is_sms_enabled"
            ],
            "properties": {
              "is_email_enabled": {
                "type": "boolean",
                "description": "Whether a new patient should default to accepting email contact.",
                "example": true
              },
              "is_sms_enabled": {
                "type": "boolean",
                "description": "Whether a new patient should default to accepting SMS contact.",
                "example": true
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "fee-schedule-membership": {
        "type": "object",
        "description": "Monthly membership (subscription) configuration for this fee schedule. A `monthly_fee` of `0` means the schedule is not a membership plan. Membership is optional practice configuration; many fee schedules never use it.",
        "required": [
          "monthly_fee",
          "exam_appointments_included",
          "hygiene_appointments_included"
        ],
        "properties": {
          "monthly_fee": {
            "type": "number",
            "description": "Monthly membership price. `0` when the plan is not sold as a subscription.",
            "example": 0
          },
          "exam_appointments_included": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of examination appointments included per year.",
            "example": 0
          },
          "hygiene_appointments_included": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of hygiene appointments included per year.",
            "example": 0
          }
        },
        "additionalProperties": false
      },
      "fee-schedule": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Fee Schedule"
            ]
          },
          {
            "type": "object",
            "description": "A **fee schedule** is a practice-defined pricing and care category (for\nexample Private, NHS, or a membership plan), not an instalment schedule.\nDentally's user interface in the United Kingdom sometimes calls this a\npayment plan. Each patient is assigned one fee schedule. The schedule\ndetermines default booking lengths, suggested recall and communication\nvalues for new patients, how fees are funded, and optional membership\npricing.\n\nTreatment prices live on a separate fee list and are not included here.\n",
            "required": [
              "id",
              "name",
              "patient_friendly_name",
              "is_active",
              "site_id",
              "account_code",
              "funding",
              "default_appointment_duration",
              "patient_default",
              "membership"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for this fee schedule within the practice.",
                "example": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
                "readOnly": true
              },
              "name": {
                "type": "string",
                "description": "Staff-facing name of the fee schedule as shown in Dentally.",
                "example": "Private"
              },
              "patient_friendly_name": {
                "type": "string",
                "nullable": true,
                "description": "Optional name for patient-facing documents such as estimates. `null` when unset; callers that need a patient-facing label may fall back to `name`.",
                "example": null
              },
              "is_active": {
                "type": "boolean",
                "description": "Whether the fee schedule is active. Inactive schedules remain assigned to existing patients but are not offered for new assignments in Dentally.",
                "example": true
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Site this fee schedule is tied to. `null` when the schedule is shared across the practice.",
                "example": "a11df716-ce65-4210-be87-8b8ec448f85c"
              },
              "account_code": {
                "type": "string",
                "description": "Accounting code used for financial reporting.",
                "example": "200"
              },
              "funding": {
                "$ref": "#/components/schemas/fee-schedule-funding"
              },
              "default_appointment_duration": {
                "$ref": "#/components/schemas/fee-schedule-default-appointment-duration"
              },
              "patient_default": {
                "$ref": "#/components/schemas/fee-schedule-patient-default"
              },
              "membership": {
                "$ref": "#/components/schemas/fee-schedule-membership"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "invoice": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Invoice"
            ]
          },
          {
            "type": "object",
            "description": "An invoice record representing a billing statement for dental services provided to a patient at a practice.",
            "required": [
              "id",
              "patient_id",
              "site_id",
              "reference",
              "invoice_amount",
              "invoice_amount_outstanding",
              "patient_owed_amount",
              "insurance_owed_amount",
              "insurance_paid_amount",
              "pending_payments_amount",
              "tax_amount",
              "discount_amount",
              "is_paid",
              "is_editable"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the invoice.",
                "example": "123e4567-e89b-12d3-a456-426614174000"
              },
              "patient_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the patient associated with this invoice.",
                "example": "550e8400-e29b-41d4-a716-446655440004"
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the site associated with this invoice.",
                "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
              },
              "reference": {
                "type": "string",
                "description": "Human readable invoice identifier.",
                "example": "00103"
              },
              "invoice_amount": {
                "type": "number",
                "description": "Total invoice amount.",
                "example": 150
              },
              "invoice_amount_outstanding": {
                "type": "number",
                "description": "Total amount still owed for this invoice.",
                "example": 10
              },
              "patient_owed_amount": {
                "type": "number",
                "description": "Amount the patient owes for this invoice.",
                "example": 15
              },
              "insurance_owed_amount": {
                "type": "number",
                "description": "Amount the insurance provider owes for this invoice.",
                "example": 20
              },
              "insurance_paid_amount": {
                "type": "number",
                "nullable": true,
                "description": "Amount the insurance provider has paid for this invoice.",
                "example": 30
              },
              "pending_payments_amount": {
                "type": "number",
                "description": "Total pending payments by the insurance provider for this invoice.",
                "example": 20
              },
              "tax_amount": {
                "type": "number",
                "description": "Total tax amount for this invoice.",
                "example": 20
              },
              "discount_amount": {
                "type": "number",
                "description": "Total discount amount for this invoice.",
                "example": 20
              },
              "is_paid": {
                "type": "boolean",
                "description": "Whether the invoice has been paid or not.",
                "example": false
              },
              "paid_on": {
                "type": "string",
                "format": "date",
                "nullable": true,
                "description": "When the invoice was paid on.",
                "example": "2019-05-14"
              },
              "is_editable": {
                "type": "boolean",
                "description": "Whether the invoice can be edited or not.",
                "example": false
              },
              "created_by": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the user who created the invoice, if applicable.",
                "example": "550e8400-e29b-41d4-a716-446655440005"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "invoice-item-pricing": {
        "type": "object",
        "description": "Pricing amounts for an invoice item line.",
        "required": [
          "item_price",
          "total_price"
        ],
        "properties": {
          "discount_amount": {
            "type": "number",
            "nullable": true,
            "description": "Discount applied to this line item.",
            "example": 10
          },
          "insurance_expected": {
            "type": "number",
            "nullable": true,
            "description": "Amount expected from insurance for this line item.",
            "example": 10
          },
          "item_price": {
            "type": "number",
            "description": "Unit price of the line item before quantity.",
            "example": 10
          },
          "total_price": {
            "type": "number",
            "description": "Total price for the line item after quantity and discount.",
            "example": 10
          }
        },
        "additionalProperties": false
      },
      "health-provider": {
        "type": "object",
        "description": "Health provider base schema.",
        "required": [
          "provider_name"
        ],
        "properties": {
          "provider_name": {
            "type": "string",
            "description": "The name of the health provider.",
            "enum": [
              "nhs",
              "prsi",
              "private"
            ],
            "example": "nhs"
          }
        }
      },
      "invoice-item-health-provider": {
        "allOf": [
          {
            "$ref": "#/components/schemas/health-provider"
          },
          {
            "type": "object",
            "description": "Health-provider details for an invoice item line.",
            "required": [
              "is_provider_charge"
            ],
            "properties": {
              "is_provider_charge": {
                "type": "boolean",
                "description": "Whether this line item is a charge associated with the health provider.",
                "example": false
              }
            }
          }
        ]
      },
      "invoice-item": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "An **invoice item** line on an invoice. Pricing amounts are nested under `pricing`; health-provider charge information under `health_provider`.",
            "required": [
              "id",
              "pricing",
              "health_provider",
              "name",
              "quantity",
              "invoice_id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "The id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "pricing": {
                "$ref": "#/components/schemas/invoice-item-pricing"
              },
              "health_provider": {
                "$ref": "#/components/schemas/invoice-item-health-provider"
              },
              "name": {
                "type": "string",
                "description": "The name of the resource.",
                "example": "Example name"
              },
              "quantity": {
                "type": "integer",
                "description": "The quantity of the resource.",
                "example": 1
              },
              "treatment_code": {
                "type": "string",
                "nullable": true,
                "description": "The treatment code of the resource.",
                "example": "example"
              },
              "invoice_id": {
                "type": "string",
                "format": "uuid",
                "description": "The invoice id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "practitioner_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "The practitioner id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "sundry_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "The sundry id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_plan_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "The treatment plan id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_plan_item_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "The treatment plan item id of the resource.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "created_by_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "UUID of the user who created the invoice item.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "nhs-contract": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "NHS Contract"
            ]
          },
          {
            "type": "object",
            "description": "An NHS dental service contract configured for a practice.",
            "required": [
              "id",
              "name",
              "is_active",
              "site_id",
              "nhs_contract_number",
              "nhs_site_id",
              "nhs_location_id",
              "start_date",
              "end_date",
              "is_pds_plus",
              "notes"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the NHS contract.",
                "example": "74299a51-bb9a-47eb-9524-20ec9c3958a8",
                "readOnly": true
              },
              "name": {
                "type": "string",
                "description": "User-assigned name for the NHS contract.",
                "example": "Main Surgery NHS Contract"
              },
              "is_active": {
                "type": "boolean",
                "description": "Whether the NHS contract is active in Dentally.",
                "example": true
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Identifier of the Dentally site associated with the contract. Null indicates a contract shared across the practice.",
                "example": "a11df716-ce65-4210-be87-8b8ec448f85c"
              },
              "nhs_contract_number": {
                "type": "string",
                "nullable": true,
                "description": "The NHS-assigned contract number, when one is recorded.",
                "example": "1234567890"
              },
              "nhs_site_id": {
                "type": "string",
                "nullable": true,
                "description": "The NHS-assigned site identifier, when one is recorded.",
                "example": "12345"
              },
              "nhs_location_id": {
                "type": "string",
                "nullable": true,
                "description": "The NHS-assigned treatment location identifier, when one is recorded.",
                "example": "200006"
              },
              "start_date": {
                "type": "string",
                "format": "date",
                "nullable": true,
                "description": "Date on which the contract started, when recorded.",
                "example": "2025-04-01"
              },
              "end_date": {
                "type": "string",
                "format": "date",
                "nullable": true,
                "description": "Date on which the contract ends, when recorded.",
                "example": "2028-03-31"
              },
              "is_pds_plus": {
                "type": "boolean",
                "description": "Whether the contract is marked as PDS Plus.",
                "example": false
              },
              "notes": {
                "type": "string",
                "nullable": true,
                "description": "User-defined notes about the contract.",
                "example": null
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "id": {
        "type": "string",
        "format": "uuid",
        "description": "Unique identifier of the practitioner.",
        "example": "550e8400-e29b-41d4-a716-446655440003"
      },
      "name": {
        "type": "string",
        "nullable": true,
        "description": "Full display name of the practitioner.",
        "example": "Dr. John Smith",
        "readOnly": true
      },
      "zone-group-ref": {
        "type": "object",
        "nullable": true,
        "description": "The zone group the calendar zone belongs to, if any. Zone groups are practice-defined labels that group related calendar zones together.",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the zone group.",
            "example": "0f8fad5b-d9cb-469f-a165-70867728950e"
          },
          "name": {
            "type": "string",
            "description": "Display name of the zone group.",
            "example": "New patient exams",
            "readOnly": true
          }
        }
      },
      "calendar-zone": {
        "type": "object",
        "x-tags": [
          "Calendar Zone"
        ],
        "description": "A calendar zone: one occurrence of a scheduled, recurring block of diary time reserved for a specific purpose, for a practitioner or a room. Calendar zones do not restrict which appointments can be booked within them.",
        "required": [
          "id",
          "title",
          "start_time",
          "finish_time",
          "practitioner",
          "room_id",
          "zone_group",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the calendar zone.",
            "example": "9b2f4c1e-3d5a-4e8b-a7c6-1f2e3d4c5b6a",
            "readOnly": true
          },
          "title": {
            "type": "string",
            "description": "Title of the calendar zone, as shown in the practice diary.",
            "example": "Emergency slots"
          },
          "start_time": {
            "type": "string",
            "format": "date-time",
            "description": "Start time of the calendar zone in ISO 8601 format in UTC.",
            "example": "2026-01-05T09:00:00Z"
          },
          "finish_time": {
            "type": "string",
            "format": "date-time",
            "description": "Finish time of the calendar zone in ISO 8601 format in UTC.",
            "example": "2026-01-05T12:00:00Z"
          },
          "practitioner": {
            "type": "object",
            "nullable": true,
            "description": "The practitioner the calendar zone is scheduled for. Null when the calendar zone is scheduled for a room instead. Retrieve the full practitioner record for additional details.",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/id"
              },
              "name": {
                "$ref": "#/components/schemas/name"
              }
            }
          },
          "room_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Identifier of the room the calendar zone is scheduled for, if applicable.",
            "example": "550e8400-e29b-41d4-a716-446655440004"
          },
          "zone_group": {
            "$ref": "#/components/schemas/zone-group-ref"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the calendar zone was created (UTC, ISO 8601). Null for some older calendar zones.",
            "example": "2025-12-01T10:15:00Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the calendar zone was last updated (UTC, ISO 8601). Null for some older calendar zones.",
            "example": "2025-12-01T10:15:00Z"
          }
        },
        "additionalProperties": false
      },
      "map-identifiers-request": {
        "type": "object",
        "description": "Legacy identifiers to map to UUIDs for a NexGen resource. At most 100 ids may be supplied per request.",
        "required": [
          "resource",
          "ids"
        ],
        "properties": {
          "resource": {
            "type": "string",
            "description": "The NexGen resource type to map identifiers for. Supported values are `patient`, `practitioner`, `appointment`, and `invoice`.",
            "enum": [
              "patient",
              "practitioner",
              "appointment",
              "invoice"
            ]
          },
          "ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "description": "Legacy integer sequential ids to map. Between 1 and 100 ids must be supplied. Each value must be a numeric sequential id for the requested resource.",
            "items": {
              "type": "integer"
            }
          }
        },
        "additionalProperties": false
      },
      "identifier-mapping": {
        "type": "object",
        "description": "A mapping from a legacy integer identifier to its UUID.",
        "required": [
          "id",
          "uuid"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "The legacy integer sequential id for the matched resource.",
            "example": 42
          },
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "The UUID for the resource within the practice.",
            "example": "4EE0FA3E-12F4-4942-9347-1702EB89EBCC"
          }
        },
        "additionalProperties": false
      },
      "treatment-category": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Treatment Category"
            ]
          },
          {
            "type": "object",
            "description": "A **treatment category** is a practice-defined folder that groups treatments in the Dentally treatment catalogue, for example Diagnostic Related Services or Restorative. Every treatment belongs to exactly one treatment category.\nTreatment categories are **practice-wide**. They are not tied to a site, so the list returned for a practice is the complete catalogue, and no `site_id` is returned or accepted as a filter.",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the treatment category within the practice. Use this value when referring to the treatment category in subsequent API calls.",
                "example": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc",
                "readOnly": true
              },
              "name": {
                "type": "string",
                "nullable": true,
                "description": "The name of the treatment category as displayed in Dentally. `null` when the category has no name. Names are not unique within a practice. The built-in category named \"System Treatments\" is returned like any other category.",
                "example": "Diagnostic Related Services"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "treatment-plan-nhs-health-provider": {
        "allOf": [
          {
            "$ref": "#/components/schemas/health-provider"
          },
          {
            "type": "object",
            "properties": {
              "uda_value": {
                "type": "number",
                "nullable": true,
                "description": "The NHS UDA value for the treatment plan.",
                "example": 10
              },
              "completed_uda_value": {
                "type": "number",
                "nullable": true,
                "description": "The NHS UDA value for completed work on the treatment plan.",
                "example": 10
              }
            }
          }
        ]
      },
      "treatment-plan-private-health-provider": {
        "allOf": [
          {
            "$ref": "#/components/schemas/health-provider"
          },
          {
            "type": "object",
            "properties": {
              "treatment_value": {
                "type": "number",
                "nullable": true,
                "description": "The total value of treatment under this health provider.",
                "example": 10
              }
            }
          }
        ]
      },
      "treatment-plan-health-provider": {
        "type": "object",
        "description": "Health provider details for a treatment plan.",
        "anyOf": [
          {
            "$ref": "#/components/schemas/treatment-plan-nhs-health-provider"
          },
          {
            "$ref": "#/components/schemas/treatment-plan-private-health-provider"
          }
        ],
        "discriminator": {
          "propertyName": "provider_name",
          "mapping": {
            "nhs": "#/components/schemas/treatment-plan-nhs-health-provider",
            "private": "#/components/schemas/treatment-plan-private-health-provider"
          }
        }
      },
      "treatment-plan": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Treatment Plan"
            ]
          },
          {
            "type": "object",
            "description": "A **treatment plan** is a planned course of dental treatment for a patient at a practice.\n",
            "required": [
              "id",
              "patient_id",
              "health_provider",
              "start_date",
              "completed_at",
              "is_completed"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the treatment plan.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "patient_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the patient this treatment plan belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "practitioner_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier of the practitioner this treatment plan belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "site_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier for the site associated with this treatment plan.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "health_provider": {
                "type": "array",
                "description": "Health provider details for a treatment plan. A plan may include more than one provider.",
                "items": {
                  "$ref": "#/components/schemas/treatment-plan-health-provider"
                }
              },
              "start_date": {
                "type": "string",
                "description": "The start date of the treatment plan.",
                "example": "2026-01-01"
              },
              "end_date": {
                "type": "string",
                "nullable": true,
                "description": "The end date of the treatment plan.",
                "example": "2026-01-01"
              },
              "completed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "When the treatment plan was first marked as completed.",
                "example": "2025-06-01T08:00:00Z"
              },
              "is_completed": {
                "type": "boolean",
                "description": "Whether the treatment plan is completed.",
                "example": false
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "treatment-plan-item-custom-fields": {
        "type": "object",
        "description": "A custom field value charted on a treatment plan item.",
        "required": [
          "id",
          "value"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the custom field on the treatment plan item.",
            "example": "2c19fdf0-987c-4e5a-aa71-06ad8a58ee22"
          },
          "value": {
            "description": "The value for this custom field on the treatment plan item.",
            "oneOf": [
              {
                "type": "string",
                "nullable": true
              },
              {
                "type": "boolean",
                "nullable": true
              }
            ],
            "example": true
          }
        },
        "additionalProperties": false
      },
      "treatment-plan-item-clinical": {
        "type": "object",
        "description": "Clinical details for a treatment plan item.",
        "required": [
          "region",
          "surfaces",
          "teeth"
        ],
        "properties": {
          "region": {
            "type": "string",
            "description": "The region that the treatment plan item is applied to.",
            "enum": [
              "item",
              "patient",
              "site",
              "surface",
              "tooth",
              "toothCoordinate"
            ],
            "example": "tooth"
          },
          "surfaces": {
            "type": "array",
            "nullable": true,
            "description": "The surfaces to be treated. Surfaces are numbered 1-5 for incisors, canines, premolars and deciduous teeth  and 1-8 for molar teeth. Surface numbering starts from the top left hand corner of the tooth  and is counted clockwise around the edge of the tooth and into the center.",
            "items": {
              "type": "integer"
            },
            "example": [
              1
            ]
          },
          "teeth": {
            "type": "array",
            "nullable": true,
            "description": "The teeth to be treated. All teeth are stored using Palmer notation.",
            "items": {
              "type": "string"
            },
            "example": [
              "LR4"
            ]
          }
        },
        "additionalProperties": false
      },
      "treatment-health-provider": {
        "allOf": [
          {
            "$ref": "#/components/schemas/health-provider"
          },
          {
            "type": "object",
            "description": "Health-provider details for a treatment.",
            "required": [
              "provider_treatment_category"
            ],
            "properties": {
              "provider_treatment_category": {
                "type": "string",
                "nullable": true,
                "description": "The treatment category or claim code under the health provider.",
                "example": "9317"
              }
            }
          }
        ]
      },
      "treatment-nhs-health-provider": {
        "allOf": [
          {
            "$ref": "#/components/schemas/treatment-health-provider"
          },
          {
            "type": "object",
            "description": "NHS health-provider details for a treatment.",
            "properties": {
              "uda_band": {
                "type": "integer",
                "nullable": true,
                "description": "The NHS UDA band of the treatment.",
                "example": 1
              }
            }
          }
        ]
      },
      "treatment-plan-item-health-provider": {
        "type": "object",
        "description": "Health provider details for a treatment plan item.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/treatment-nhs-health-provider"
          }
        ],
        "discriminator": {
          "propertyName": "provider_name",
          "mapping": {
            "nhs": "#/components/schemas/treatment-nhs-health-provider"
          }
        }
      },
      "treatment-plan-item": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "type": "object",
            "description": "A **treatment plan item** is a treatment charted on a patient’s treatment plan. \nEach item links a treatment to a plan, with pricing, clinical details, completion status, notes, \nand health provider details where applicable.\n",
            "required": [
              "id",
              "patient_id",
              "practitioner_id",
              "fee_schedule_id",
              "treatment_plan_id",
              "nomenclature",
              "price",
              "is_charged",
              "is_completed",
              "duration_minutes",
              "custom_fields",
              "clinical",
              "health_provider"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the treatment plan item.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "patient_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the patient this treatment plan item belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "practitioner_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the practitioner this treatment plan item belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "fee_schedule_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the fee schedule this treatment plan item belongs to. Dentally's user interface in the  United Kingdom sometimes calls this a payment plan.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "referrer_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier of the referrer of the treatment plan item.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "invoice_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier of the invoice the treatment plan item belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_appointment_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier of the treatment appointment the treatment plan item belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Unique identifier of the treatment the treatment plan item belongs to.",
                "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
              },
              "treatment_plan_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier of the treatment plan the treatment plan item belongs to."
              },
              "nomenclature": {
                "type": "string",
                "description": "The classification of the treatment plan item.",
                "example": "Acute Mucosal Infection"
              },
              "patient_friendly_nomenclature": {
                "type": "string",
                "nullable": true,
                "description": "The patient friendly classification of the treatment plan item.",
                "example": "Urgent/Emergency Assessment"
              },
              "price": {
                "type": "number",
                "description": "The price of the treatment plan item.",
                "example": 10
              },
              "is_charged": {
                "type": "boolean",
                "description": "Whether the treatment plan item is charged.",
                "example": false
              },
              "is_completed": {
                "type": "boolean",
                "description": "Whether the treatment plan item is completed.",
                "example": false
              },
              "completed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "When the treatment plan item was first marked as completed.",
                "example": "2025-06-01T08:00:00Z"
              },
              "duration_minutes": {
                "type": "integer",
                "description": "The duration in minutes of the treatment plan item.",
                "example": 30
              },
              "notes": {
                "type": "string",
                "nullable": true,
                "description": "The notes relating to the treatment plan item in HTML.",
                "example": "<p>This is a note</p>"
              },
              "custom_fields": {
                "type": "array",
                "description": "The custom fields for this treatment plan item.",
                "items": {
                  "$ref": "#/components/schemas/treatment-plan-item-custom-fields"
                }
              },
              "clinical": {
                "$ref": "#/components/schemas/treatment-plan-item-clinical"
              },
              "health_provider": {
                "$ref": "#/components/schemas/treatment-plan-item-health-provider"
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "treatment": {
        "allOf": [
          {
            "$ref": "#/components/schemas/entity-timestamps"
          },
          {
            "x-tags": [
              "Treatment"
            ]
          },
          {
            "type": "object",
            "description": "A **treatment** is a practice-level catalogue entry for a dental procedure that can be assigned to a patient treatment plan. Every treatment belongs to exactly one treatment category.\nTreatments are **practice-wide**. They are not tied to a site, so the list returned for a practice is the complete catalogue, and no `site_id` is returned or accepted as a filter.",
            "required": [
              "id",
              "is_active",
              "owner",
              "treatment_category_id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for the treatment within the practice. Use this value when referring to the treatment in subsequent API calls.",
                "example": "94525b9c-af18-40a5-905f-f539f1c45f6f",
                "readOnly": true
              },
              "code": {
                "type": "string",
                "nullable": true,
                "description": "Short procedure code for the treatment within the practice.",
                "example": "100"
              },
              "nomenclature": {
                "type": "string",
                "nullable": true,
                "description": "Display name of the treatment in Dentally.",
                "example": "Exam"
              },
              "description": {
                "type": "string",
                "nullable": true,
                "description": "Longer description of the treatment.",
                "example": "An evaluation performed on a patient of record to determine any changes in the patient's dental and medical health status."
              },
              "patient_nomenclature": {
                "type": "string",
                "nullable": true,
                "description": "Patient-facing name for the treatment.",
                "example": "Examination"
              },
              "patient_description": {
                "type": "string",
                "nullable": true,
                "description": "Patient-facing description of the treatment.",
                "example": null
              },
              "treatment_category_id": {
                "type": "string",
                "format": "uuid",
                "description": "Identifier of the treatment category this treatment belongs to.",
                "example": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc"
              },
              "is_active": {
                "type": "boolean",
                "description": "Whether the treatment is active in the practice catalogue.",
                "example": true
              },
              "is_displayed_on_invoice": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether the treatment is displayed on patient invoices.",
                "example": true
              },
              "region": {
                "type": "string",
                "nullable": true,
                "description": "Chart targeting for how the treatment is applied.",
                "enum": [
                  "item",
                  "patient",
                  "site",
                  "surface",
                  "tooth",
                  "toothCoordinate"
                ],
                "example": "patient"
              },
              "owner": {
                "type": "string",
                "description": "Who manages the treatment. `practice` for practice-authored entries; `system` for Dentally-managed system treatments.",
                "enum": [
                  "practice",
                  "system"
                ],
                "example": "practice"
              },
              "health_provider": {
                "type": "object",
                "nullable": true,
                "description": "Health-provider details for this treatment.",
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/treatment-health-provider"
                  },
                  {
                    "$ref": "#/components/schemas/treatment-nhs-health-provider"
                  }
                ],
                "discriminator": {
                  "propertyName": "provider_name",
                  "mapping": {
                    "nhs": "#/components/schemas/treatment-nhs-health-provider",
                    "prsi": "#/components/schemas/treatment-health-provider"
                  }
                }
              },
              "created_at": {
                "$ref": "#/components/schemas/created_at"
              },
              "updated_at": {
                "$ref": "#/components/schemas/updated_at"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "subscription-status": {
        "type": "string",
        "enum": [
          "Unknown",
          "Pending",
          "Completed"
        ],
        "description": "The status of the subscription."
      },
      "subscription": {
        "type": "object",
        "required": [
          "id",
          "partner_id",
          "product_id",
          "practice_id",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The identifier of the subscription, as a uuid."
          },
          "partner_id": {
            "type": "string",
            "format": "uuid",
            "description": "The identifier of the partner which owns the product, as a uuid."
          },
          "product_id": {
            "type": "string",
            "description": "The identifier of the product which is subscribed to, as a uuid."
          },
          "practice_id": {
            "type": "string",
            "format": "uuid",
            "description": "The identifier of the practice which the subscription is for, as a uuid."
          },
          "site_id": {
            "type": "string",
            "format": "uuid",
            "description": "An optional identifier of the site within the practice which the subscription is for, as a uuid. If not specified, the subscription is for all sites within the practice.",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/subscription-status",
            "description": "The status of the subscription."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp of when this subscription was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp of when this subscription was updated.",
            "nullable": true
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp of when this subscription was deleted, or when it will expire if a future date is specified.",
            "nullable": true
          }
        }
      }
    },
    "examples": {
      "response-appointment-list-example": {
        "summary": "First page of appointments",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "patient": {
                "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "first_name": "Jane",
                "middle_name": "Marie",
                "last_name": "Doe"
              },
              "start_time": "2025-06-01T08:00:00Z",
              "finish_time": "2025-06-01T09:00:00Z",
              "duration_minutes": 60,
              "reason": {
                "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "name": "Routine dental check-up"
              },
              "notes": "Patient requested a morning appointment.",
              "practitioner": {
                "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "name": "Dr. Smith"
              },
              "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "state": "Pending",
              "cancelled_at": null,
              "payment_plan_id": null,
              "room_id": null,
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "patient": {
                "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                "first_name": "John",
                "middle_name": null,
                "last_name": "Smith"
              },
              "start_time": "2025-09-01T11:00:00Z",
              "finish_time": "2025-09-01T11:45:00Z",
              "duration_minutes": 45,
              "notes": "Follow-up appointment.",
              "practitioner": {
                "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
                "name": "Dr. Johnson"
              },
              "site_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "state": "Confirmed",
              "cancelled_at": null,
              "payment_plan_id": null,
              "room_id": null,
              "created_at": "2025-08-05T10:30:00Z",
              "updated_at": "2025-08-20T16:15:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "problem-bad-request-example": {
        "summary": "Malformed or invalid request",
        "description": "RFC 7807 problem details when validation fails (e.g. missing required field).",
        "value": {
          "type": "https://api.dentally.co/problems/bad-request",
          "title": "Bad Request",
          "status": 400,
          "detail": "The request is missing required header 'X-Practice-Id'.",
          "instance": "/v2/sites"
        }
      },
      "problem-unauthorized-example": {
        "summary": "Missing or invalid credentials",
        "description": "RFC 7807 problem details when the caller is not authenticated.",
        "value": {
          "type": "https://api.dentally.co/problems/unauthorized",
          "title": "Unauthorized",
          "status": 401,
          "detail": "Valid bearer token required."
        }
      },
      "problem-user-error-example": {
        "summary": "Generic client error response",
        "description": "RFC 7807 problem details for a generic client error (e.g. conflict, unsupported media type).",
        "value": {
          "type": "https://api.dentally.co/problems/client-error",
          "title": "Unprocessable Entity",
          "status": 422,
          "detail": "The request could not be processed with the current state of the resource."
        }
      },
      "problem-server-error-example": {
        "summary": "Unexpected server error",
        "description": "RFC 7807 problem details for an internal failure.",
        "value": {
          "type": "https://api.dentally.co/problems/internal-error",
          "title": "Internal Server Error",
          "status": 500,
          "detail": "An unexpected error occurred while processing your request."
        }
      },
      "response-appointment-single-example": {
        "summary": "Single appointment",
        "description": "Wrapper returned by get, create, or update appointment.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "patient": {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "first_name": "Jane",
              "middle_name": "Marie",
              "last_name": "Doe"
            },
            "start_time": "2025-06-01T08:00:00Z",
            "finish_time": "2025-06-01T09:00:00Z",
            "duration_minutes": 60,
            "reason": {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Routine dental check-up"
            },
            "notes": "Patient requested a morning appointment.",
            "practitioner": {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Dr. Smith"
            },
            "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "state": "Pending",
            "cancelled_at": null,
            "payment_plan_id": null,
            "room_id": null,
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z"
          }
        }
      },
      "problem-unprocessable-entity-example": {
        "summary": "Validation error",
        "description": "RFC 7807 problem details when the request is well-formed but fails business validation.",
        "value": {
          "type": "https://api.dentally.co/problems/unprocessable-entity",
          "title": "Unprocessable Entity",
          "status": 422,
          "detail": "start_time must be before finish_time.",
          "instance": "/v2/appointments"
        }
      },
      "problem-not-found-example": {
        "summary": "Resource not found",
        "description": "RFC 7807 problem details when no resource matches the given identifier.",
        "value": {
          "type": "https://api.dentally.co/problems/not-found",
          "title": "Not Found",
          "status": 404,
          "detail": "No site found for the given id in this practice.",
          "instance": "/v2/sites/8c7f4c9b-0e3d-5f2a-b6c7-4d8e9f0a1b2c"
        }
      },
      "response-appointment-reason-list-example": {
        "summary": "First page of appointment reasons",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "4EE0FA3E-12F4-4942-9347-1702EB89EBCC",
              "name": "Exam + Scale & Polish",
              "is_active": true,
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "9A2B3C4D-5E6F-7081-92A3-B4C5D6E7F809",
              "name": "New Patient Consultation",
              "is_active": true,
              "created_at": "2025-08-12T11:00:00Z",
              "updated_at": "2026-01-05T09:45:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-appointment-cancellation-reason-list-example": {
        "summary": "First page of appointment cancellation reasons",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "AE492D60-8970-4AA0-8D5C-84FFAF4A16A3",
              "name": "Patient - Illness",
              "type": "cancelled",
              "is_active": true,
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "EFB3701D-649E-407F-860E-D08C31FBF2F4",
              "name": "Practice - Staff Issue",
              "type": "cancelled",
              "is_active": true,
              "created_at": "2025-08-12T11:00:00Z",
              "updated_at": "2026-01-05T09:45:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-patient-single-example": {
        "summary": "Single patient",
        "description": "Wrapper returned by get, create, or update patient.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "is_active": true,
            "is_appointment_booking_prevented": false,
            "preferred_phone_type": "mobile",
            "first_name": "Jane",
            "last_name": "Doe",
            "date_of_birth": "1990-04-12",
            "title": "Ms",
            "ethnicity": "01",
            "payment_plan_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
            "site_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
            "address": {
              "address_line_1": "42 High Street",
              "locality": "London",
              "administrative_area": "Greater London",
              "postal_code": "EC1A 1BB"
            },
            "email_address": "jane.doe@example.com",
            "biological_sex": "female",
            "phones": [
              {
                "phone_type": "mobile",
                "phone_number": "+447911123456",
                "phone_country": "GB",
                "phone_number_normalized": "+447911123456"
              }
            ],
            "communication": {
              "is_marketing_enabled": true,
              "is_email_enabled": true,
              "is_sms_enabled": false
            },
            "recall": {
              "dentist": {
                "date": "2026-03-15",
                "interval_months": 6
              },
              "hygienist": {
                "date": "2026-04-01",
                "interval_months": 6
              },
              "method": "email"
            },
            "archived_reason": null,
            "is_bad_debtor": false,
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z"
          }
        }
      },
      "response-patient-account-example": {
        "summary": "Patient account balance",
        "description": "Example where the patient owes the practice: monetary amounts in this sample are negative. Accounts in credit have positive amounts.",
        "value": {
          "data": {
            "owning_patient_id": "550e8400-e29b-41d4-a716-446655440004",
            "balance_amount": -125.5,
            "patient_balance_amount": -100.5,
            "pending_payments_amount": -25,
            "deposit_amount": 0,
            "created_at": "2026-01-05T09:12:44Z",
            "updated_at": "2026-10-02T14:03:10Z"
          }
        }
      },
      "response-practitioner-list-example": {
        "summary": "First page of practitioners",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Jane Doe",
              "user_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "site_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "role": "Hygienist",
              "nhs_number": "9998887777",
              "gdc_number": "123456",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "name": "John Smith",
              "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "site_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "role": null,
              "nhs_number": null,
              "gdc_number": null,
              "created_at": "2025-08-12T11:00:00Z",
              "updated_at": "2026-01-05T09:45:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-practitioner-availability-list-example": {
        "summary": "First page of practitioner availability slots",
        "description": "Paginated list of availability slots for the requested practitioners, ordered by start time ascending.",
        "value": {
          "data": [
            {
              "start_time": "2031-12-01T09:00:00+00:00",
              "finish_time": "2031-12-01T10:00:00+00:00",
              "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            },
            {
              "start_time": "2031-12-01T10:00:00+00:00",
              "finish_time": "2031-12-01T11:00:00+00:00",
              "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-practitioner-single-example": {
        "summary": "Single practitioner",
        "description": "Wrapper returned by get practitioner.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "name": "Jane Doe",
            "user_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
            "site_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
            "role": "Therapist",
            "nhs_number": "NHS-001",
            "gdc_number": "123456",
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z"
          }
        }
      },
      "response-rota-schedule-history-list-example": {
        "summary": "First page of rota schedule histories",
        "description": "Paginated list of snapshotted rota days for a practitioner, ordered by date descending.",
        "value": {
          "data": [
            {
              "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "date": "2025-01-15",
              "is_available": true,
              "start_time": "09:00",
              "finish_time": "17:30",
              "breaks": [
                {
                  "name": "Lunch",
                  "start_time": "13:00",
                  "finish_time": "14:00"
                }
              ],
              "created_at": "2025-01-16T00:05:12Z",
              "updated_at": "2025-01-16T00:05:12Z"
            },
            {
              "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "date": "2025-01-14",
              "is_available": false,
              "start_time": null,
              "finish_time": null,
              "breaks": [],
              "created_at": "2025-01-15T00:05:08Z",
              "updated_at": "2025-01-15T00:05:08Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-site-list-example": {
        "summary": "First page of sites",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "8c7f4c9b-0e3d-5f2a-b6c7-4d8e9f0a1b2c",
              "name": "Dentally High Street",
              "address": {
                "address_line_1": "42 High Street",
                "address_line_2": null,
                "address_line_3": null,
                "locality": "Manchester",
                "administrative_area": "Greater Manchester",
                "postal_code": "M1 1AA"
              },
              "contact_details": {
                "email_address": "reception@example.com",
                "phone_number": "+441612345678",
                "website_url": "https://example.com/high-street"
              },
              "opening_hours": [
                {
                  "weekday": "Sunday",
                  "open_at": null,
                  "close_at": null
                },
                {
                  "weekday": "Monday",
                  "open_at": "09:00",
                  "close_at": "17:30"
                },
                {
                  "weekday": "Tuesday",
                  "open_at": "09:00",
                  "close_at": "17:30"
                },
                {
                  "weekday": "Wednesday",
                  "open_at": "09:00",
                  "close_at": "17:30"
                },
                {
                  "weekday": "Thursday",
                  "open_at": "09:00",
                  "close_at": "17:30"
                },
                {
                  "weekday": "Friday",
                  "open_at": "09:00",
                  "close_at": "17:00"
                },
                {
                  "weekday": "Saturday",
                  "open_at": null,
                  "close_at": null
                }
              ],
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80901",
              "name": "Dentally Riverside",
              "address": {
                "address_line_1": "10 River Road",
                "address_line_2": "Unit 2",
                "address_line_3": null,
                "locality": "Salford",
                "administrative_area": "Greater Manchester",
                "postal_code": "M50 1AB"
              },
              "contact_details": {
                "email_address": "riverside@example.com",
                "phone_number": "+441614445566",
                "website_url": null
              },
              "opening_hours": [
                {
                  "weekday": "Sunday",
                  "open_at": null,
                  "close_at": null
                },
                {
                  "weekday": "Monday",
                  "open_at": "08:30",
                  "close_at": "18:00"
                },
                {
                  "weekday": "Tuesday",
                  "open_at": "08:30",
                  "close_at": "18:00"
                },
                {
                  "weekday": "Wednesday",
                  "open_at": "08:30",
                  "close_at": "18:00"
                },
                {
                  "weekday": "Thursday",
                  "open_at": "08:30",
                  "close_at": "18:00"
                },
                {
                  "weekday": "Friday",
                  "open_at": "08:30",
                  "close_at": "18:00"
                },
                {
                  "weekday": "Saturday",
                  "open_at": "09:00",
                  "close_at": "13:00"
                }
              ],
              "created_at": "2025-08-12T11:00:00Z",
              "updated_at": "2026-01-05T09:45:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wOC0xMlQxMTowMDowMFoifQ"
          }
        }
      },
      "response-site-single-example": {
        "summary": "Single site",
        "description": "Wrapper returned by get site.",
        "value": {
          "data": {
            "id": "8c7f4c9b-0e3d-5f2a-b6c7-4d8e9f0a1b2c",
            "name": "Dentally High Street",
            "address": {
              "address_line_1": "42 High Street",
              "address_line_2": null,
              "address_line_3": null,
              "locality": "Manchester",
              "administrative_area": "Greater Manchester",
              "postal_code": "M1 1AA"
            },
            "contact_details": {
              "email_address": "reception@example.com",
              "phone_number": "+441612345678",
              "website_url": "https://example.com/high-street"
            },
            "opening_hours": [
              {
                "weekday": "Sunday",
                "open_at": null,
                "close_at": null
              },
              {
                "weekday": "Monday",
                "open_at": "09:00",
                "close_at": "17:30"
              },
              {
                "weekday": "Tuesday",
                "open_at": "09:00",
                "close_at": "17:30"
              },
              {
                "weekday": "Wednesday",
                "open_at": "09:00",
                "close_at": "17:30"
              },
              {
                "weekday": "Thursday",
                "open_at": "09:00",
                "close_at": "17:30"
              },
              {
                "weekday": "Friday",
                "open_at": "09:00",
                "close_at": "17:00"
              },
              {
                "weekday": "Saturday",
                "open_at": null,
                "close_at": null
              }
            ],
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z"
          }
        }
      },
      "response-fee-list-example": {
        "summary": "First page of fees",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "payment_plan_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "treatment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "is_multiple_pricing": true,
              "tiers": [
                {
                  "quantity": 1,
                  "price": 55,
                  "duration_minutes": 15
                },
                {
                  "quantity": 2,
                  "price": 75,
                  "duration_minutes": 20
                },
                {
                  "quantity": 3,
                  "price": 95,
                  "duration_minutes": 25
                },
                {
                  "quantity": 4,
                  "price": 110,
                  "duration_minutes": 30
                },
                {
                  "quantity": 5,
                  "price": 125,
                  "duration_minutes": 35
                }
              ],
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2025-06-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wOC0xMlQxMTowMDowMFoifQ"
          }
        }
      },
      "response-fee-single-example": {
        "summary": "Single fee",
        "description": "Wrapper returned by get fee.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "payment_plan_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "treatment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "is_multiple_pricing": true,
            "tiers": [
              {
                "quantity": 1,
                "price": 55,
                "duration_minutes": 15
              },
              {
                "quantity": 2,
                "price": 75,
                "duration_minutes": 20
              },
              {
                "quantity": 3,
                "price": 95,
                "duration_minutes": 25
              },
              {
                "quantity": 4,
                "price": 110,
                "duration_minutes": 30
              },
              {
                "quantity": 5,
                "price": 125,
                "duration_minutes": 35
              }
            ],
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2025-06-01T08:00:00Z"
          }
        }
      },
      "response-fee-schedule-list-example": {
        "summary": "First page of fee schedules",
        "description": "Paginated list with a cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "NHS",
              "patient_friendly_name": null,
              "is_active": true,
              "site_id": null,
              "account_code": "200",
              "funding": {
                "type": "private",
                "scheme": "nhs",
                "claim_timing": null
              },
              "default_appointment_duration": {
                "exam_minutes": 10,
                "scale_and_polish_minutes": 10,
                "exam_scale_and_polish_minutes": 20,
                "emergency_minutes": 10
              },
              "patient_default": {
                "recall": {
                  "dentist_interval_months": 6,
                  "hygienist_interval_months": 6,
                  "method": "letter"
                },
                "communication": {
                  "is_email_enabled": true,
                  "is_sms_enabled": true
                }
              },
              "membership": {
                "monthly_fee": 0,
                "exam_appointments_included": 0,
                "hygiene_appointments_included": 0
              },
              "created_at": "2024-01-15T09:30:00Z",
              "updated_at": "2026-03-02T11:12:00Z"
            },
            {
              "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "name": "Private",
              "patient_friendly_name": null,
              "is_active": true,
              "site_id": "a11df716-ce65-4210-be87-8b8ec448f85c",
              "account_code": "200",
              "funding": {
                "type": "private",
                "scheme": null,
                "claim_timing": null
              },
              "default_appointment_duration": {
                "exam_minutes": 10,
                "scale_and_polish_minutes": 10,
                "exam_scale_and_polish_minutes": 20,
                "emergency_minutes": 10
              },
              "patient_default": {
                "recall": {
                  "dentist_interval_months": 6,
                  "hygienist_interval_months": 6,
                  "method": "letter"
                },
                "communication": {
                  "is_email_enabled": true,
                  "is_sms_enabled": true
                }
              },
              "membership": {
                "monthly_fee": 0,
                "exam_appointments_included": 0,
                "hygiene_appointments_included": 0
              },
              "created_at": "2024-01-15T09:31:00Z",
              "updated_at": "2025-11-04T16:22:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-fee-schedule-single-example": {
        "summary": "Fee schedule",
        "description": "A fee schedule configured for the practice.",
        "value": {
          "data": {
            "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
            "name": "OHSA - MoH",
            "patient_friendly_name": "Oral Health Services Adolescents (OHSA)",
            "is_active": true,
            "site_id": null,
            "account_code": "200",
            "funding": {
              "type": "insurance_funded",
              "scheme": "nz_moh_ohsa",
              "claim_timing": "on_completion"
            },
            "default_appointment_duration": {
              "exam_minutes": 30,
              "scale_and_polish_minutes": 30,
              "exam_scale_and_polish_minutes": 30,
              "emergency_minutes": 30
            },
            "patient_default": {
              "recall": {
                "dentist_interval_months": 12,
                "hygienist_interval_months": 12,
                "method": "email"
              },
              "communication": {
                "is_email_enabled": true,
                "is_sms_enabled": true
              }
            },
            "membership": {
              "monthly_fee": 0,
              "exam_appointments_included": 0,
              "hygiene_appointments_included": 0
            },
            "created_at": "2024-04-01T00:00:00Z",
            "updated_at": "2026-01-20T08:45:00Z"
          }
        }
      },
      "response-invoice-list-example": {
        "summary": "First page of invoices",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "patient_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "reference": "00103",
              "invoice_amount": 150,
              "invoice_amount_outstanding": 50,
              "patient_owed_amount": 20,
              "insurance_owed_amount": 10,
              "insurance_paid_amount": 5,
              "pending_payments_amount": 5,
              "tax_amount": 10,
              "discount_amount": 10,
              "is_paid": false,
              "paid_on": null,
              "is_editable": false,
              "created_by": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            },
            {
              "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "patient_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "reference": "00103",
              "invoice_amount": 150,
              "invoice_amount_outstanding": 0,
              "patient_owed_amount": 150,
              "insurance_owed_amount": 0,
              "insurance_paid_amount": 0,
              "pending_payments_amount": 0,
              "tax_amount": 0,
              "discount_amount": 0,
              "is_paid": true,
              "paid_on": "2026-01-18",
              "is_editable": true,
              "created_by": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-invoice-single-example": {
        "summary": "Single invoice",
        "description": "Wrapper returned by get, create, or update invoice.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "patient_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "reference": "00103",
            "invoice_amount": 150,
            "invoice_amount_outstanding": 50,
            "patient_owed_amount": 20,
            "insurance_owed_amount": 10,
            "insurance_paid_amount": 5,
            "pending_payments_amount": 5,
            "tax_amount": 10,
            "discount_amount": 10,
            "is_paid": false,
            "paid_on": null,
            "is_editable": false,
            "created_by": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z"
          }
        }
      },
      "response-invoice-invoice-item-list-example": {
        "summary": "First page of invoice items",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "pricing": {
                "discount_amount": 10,
                "insurance_expected": 10,
                "item_price": 10,
                "total_price": 10
              },
              "health_provider": {
                "is_provider_charge": false,
                "provider_name": "nhs"
              },
              "name": "Example name",
              "quantity": 1,
              "treatment_code": "example",
              "invoice_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "sundry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "treatment_plan_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "treatment_plan_item_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "created_by_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2025-06-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wOC0xMlQxMTowMDowMFoifQ"
          }
        }
      },
      "response-nhs-contract-list-example": {
        "summary": "First page of NHS contracts",
        "description": "Paginated list with a cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "74299a51-bb9a-47eb-9524-20ec9c3958a8",
              "name": "Main Surgery NHS Contract",
              "is_active": true,
              "site_id": "a11df716-ce65-4210-be87-8b8ec448f85c",
              "nhs_contract_number": "1234567890",
              "nhs_site_id": "12345",
              "nhs_location_id": "200006",
              "start_date": "2025-04-01",
              "end_date": null,
              "is_pds_plus": false,
              "notes": null,
              "created_at": "2025-01-10T09:00:00Z",
              "updated_at": "2026-08-20T11:20:00Z"
            },
            {
              "id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
              "name": "Previous Main Surgery Contract",
              "is_active": false,
              "site_id": null,
              "nhs_contract_number": "1234567891",
              "nhs_site_id": "12345",
              "nhs_location_id": "200006",
              "start_date": "2024-04-01",
              "end_date": "2026-03-31",
              "is_pds_plus": false,
              "notes": "Historical contract",
              "created_at": "2024-02-01T08:30:00Z",
              "updated_at": "2026-04-02T10:15:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-nhs-contract-single-example": {
        "summary": "NHS contract",
        "description": "An NHS contract configured for the practice.",
        "value": {
          "data": {
            "id": "74299a51-bb9a-47eb-9524-20ec9c3958a8",
            "name": "Main Surgery NHS Contract",
            "is_active": true,
            "site_id": "a11df716-ce65-4210-be87-8b8ec448f85c",
            "nhs_contract_number": "1234567890",
            "nhs_site_id": "12345",
            "nhs_location_id": "200006",
            "start_date": "2025-04-01",
            "end_date": null,
            "is_pds_plus": false,
            "notes": null,
            "created_at": "2025-01-10T09:00:00Z",
            "updated_at": "2026-08-20T11:20:00Z"
          }
        }
      },
      "response-calendar-zone-list-example": {
        "summary": "First page of calendar zones",
        "description": "Paginated list with a cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "9b2f4c1e-3d5a-4e8b-a7c6-1f2e3d4c5b6a",
              "title": "Emergency slots",
              "start_time": "2026-01-05T09:00:00Z",
              "finish_time": "2026-01-05T12:00:00Z",
              "practitioner": {
                "id": "550e8400-e29b-41d4-a716-446655440003",
                "name": "Dr. John Smith"
              },
              "room_id": null,
              "zone_group": {
                "id": "0f8fad5b-d9cb-469f-a165-70867728950e",
                "name": "Emergencies"
              },
              "created_at": "2025-12-01T10:15:00Z",
              "updated_at": "2025-12-01T10:15:00Z"
            },
            {
              "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
              "title": "Hygiene clinic",
              "start_time": "2026-01-06T13:00:00Z",
              "finish_time": "2026-01-06T17:00:00Z",
              "practitioner": null,
              "room_id": "550e8400-e29b-41d4-a716-446655440004",
              "zone_group": null,
              "created_at": null,
              "updated_at": null
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-calendar-zone-single-example": {
        "summary": "Single calendar zone",
        "description": "One calendar zone scheduled for a practitioner.",
        "value": {
          "data": {
            "id": "9b2f4c1e-3d5a-4e8b-a7c6-1f2e3d4c5b6a",
            "title": "Emergency slots",
            "start_time": "2026-01-05T09:00:00Z",
            "finish_time": "2026-01-05T12:00:00Z",
            "practitioner": {
              "id": "550e8400-e29b-41d4-a716-446655440003",
              "name": "Dr. John Smith"
            },
            "room_id": null,
            "zone_group": {
              "id": "0f8fad5b-d9cb-469f-a165-70867728950e",
              "name": "Emergencies"
            },
            "created_at": "2025-12-01T10:15:00Z",
            "updated_at": "2025-12-01T10:15:00Z"
          }
        }
      },
      "response-treatment-category-list-example": {
        "summary": "First page of treatment categories",
        "description": "Paginated list with cursor for the next page. Categories may have a null name.",
        "value": {
          "data": [
            {
              "id": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc",
              "name": "Diagnostic Related Services",
              "created_at": "2026-01-05T09:12:44Z",
              "updated_at": "2026-10-02T14:03:10Z"
            },
            {
              "id": "9a2b3c4d-5e6f-4081-92a3-b4c5d6e7f809",
              "name": "Restorative",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2025-06-01T08:00:00Z"
            },
            {
              "id": "09b2e37e-8f42-4676-adf3-cb97fc9ee3e6",
              "name": null,
              "created_at": "2025-05-01T08:00:00Z",
              "updated_at": "2025-05-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wNi0wMVQwODowMDowMFoifQ"
          }
        }
      },
      "response-treatment-category-single-example": {
        "summary": "Single treatment category",
        "description": "One treatment category in the practice catalogue.",
        "value": {
          "data": {
            "id": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc",
            "name": "Diagnostic Related Services",
            "created_at": "2026-01-05T09:12:44Z",
            "updated_at": "2026-10-02T14:03:10Z"
          }
        }
      },
      "response-treatment-plan-list-example": {
        "summary": "First page of treatment plans",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "patient_id": "ea845d0d-d6d7-4dd4-8321-1bd803c897e8",
              "practitioner_id": "c8e79da4-e253-4887-8084-04786bff7e4f",
              "site_id": "2836b794-0d77-4788-b06f-da6927cab30d",
              "health_provider": [
                {
                  "provider_name": "nhs",
                  "uda_value": 1.5,
                  "completed_uda_value": 3
                },
                {
                  "provider_name": "private",
                  "treatment_value": 50
                }
              ],
              "start_date": "2026-06-01",
              "end_date": "2026-10-01",
              "completed_at": "2026-07-01T08:00:00Z",
              "is_completed": true,
              "created_at": "2026-06-01T08:00:00Z",
              "updated_at": "2026-10-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wOC0xMlQxMTowMDowMFoifQ"
          }
        }
      },
      "response-treatment-plan-single-example": {
        "summary": "Single treatment plan",
        "description": "Wrapper returned by get treatment plan.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "patient_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "practitioner_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "site_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "health_provider": [
              {
                "provider_name": "nhs",
                "uda_value": 1.5,
                "completed_uda_value": 3
              }
            ],
            "start_date": "2026-06-01",
            "end_date": null,
            "completed_at": null,
            "is_completed": false,
            "created_at": "2026-06-01T08:00:00Z",
            "updated_at": "2026-10-01T08:00:00Z"
          }
        }
      },
      "response-treatment-plan-treatment-plan-item-list-example": {
        "summary": "First page of treatment plan items",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "patient_id": "9efcb282-8f4f-4ac1-9259-d4e3fe9b6531",
              "practitioner_id": "0930501c-aafd-45e7-90c3-76498ba2d126",
              "fee_schedule_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "referrer_id": "e1d854af-15db-4482-8e29-39e74a6c7f75",
              "invoice_id": "10548353-ea10-451f-beac-9b5858a87e01",
              "treatment_appointment_id": "a58310cd-5473-421e-b6ad-ff31f647140d",
              "treatment_id": "68adfa9e-a3c9-47c8-812c-3fe55640b560",
              "treatment_plan_id": "a2f6bdbb-ac9b-4a24-8136-98f1c06fbb89",
              "nomenclature": "Acute Mucosal Infection",
              "patient_friendly_nomenclature": "Urgent/Emergency Assessment",
              "price": 10,
              "is_charged": false,
              "is_completed": true,
              "completed_at": "2025-06-01T08:00:00Z",
              "duration_minutes": 30,
              "notes": "<p>This is a note</p>",
              "custom_fields": [
                {
                  "id": "e4b5cd1e-4a43-46ce-bdb0-fe75f2e8cd14",
                  "value": true
                }
              ],
              "clinical": {
                "region": "tooth",
                "surfaces": [
                  1
                ],
                "teeth": [
                  "LR4"
                ]
              },
              "health_provider": {
                "provider_name": "nhs",
                "provider_treatment_category": "9306",
                "uda_band": 2
              },
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2025-06-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wOC0xMlQxMTowMDowMFoifQ"
          }
        }
      },
      "response-treatment-list-example": {
        "summary": "First page of treatments",
        "description": "Paginated list with cursor for the next page. Includes a practice-authored treatment and a Dentally-managed system treatment.",
        "value": {
          "data": [
            {
              "id": "94525b9c-af18-40a5-905f-f539f1c45f6f",
              "code": "100",
              "nomenclature": "Exam",
              "description": "An evaluation performed on a patient of record to determine any changes in the patient's dental and medical health status.",
              "patient_nomenclature": "Examination",
              "patient_description": null,
              "treatment_category_id": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc",
              "is_active": true,
              "is_displayed_on_invoice": true,
              "region": "patient",
              "owner": "practice",
              "health_provider": {
                "provider_name": "nhs",
                "provider_treatment_category": "9317",
                "uda_band": 1
              },
              "created_at": "2026-01-05T09:12:44Z",
              "updated_at": "2026-10-02T14:03:10Z"
            },
            {
              "id": "a1b2c3d4-e5f6-4789-a012-3456789abcde",
              "code": "SYS001",
              "nomenclature": "Unerupted",
              "description": null,
              "patient_nomenclature": null,
              "patient_description": null,
              "treatment_category_id": "09b2e37e-8f42-4676-adf3-cb97fc9ee3e6",
              "is_active": true,
              "is_displayed_on_invoice": false,
              "region": "tooth",
              "owner": "system",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2025-06-01T08:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wNi0wMVQwODowMDowMFoifQ"
          }
        }
      },
      "response-treatment-single-example": {
        "summary": "Single treatment",
        "description": "One treatment in the practice catalogue.",
        "value": {
          "data": {
            "id": "94525b9c-af18-40a5-905f-f539f1c45f6f",
            "code": "100",
            "nomenclature": "Exam",
            "description": "An evaluation performed on a patient of record to determine any changes in the patient's dental and medical health status.",
            "patient_nomenclature": "Examination",
            "patient_description": null,
            "treatment_category_id": "4ee0fa3e-12f4-4942-9347-1702eb89ebcc",
            "is_active": true,
            "is_displayed_on_invoice": true,
            "region": "patient",
            "owner": "practice",
            "health_provider": {
              "provider_name": "nhs",
              "provider_treatment_category": "9317",
              "uda_band": 1
            },
            "created_at": "2026-01-05T09:12:44Z",
            "updated_at": "2026-10-02T14:03:10Z"
          }
        }
      },
      "response-subscription-list-example": {
        "summary": "First page of subscriptions",
        "description": "Paginated list with cursor for the next page.",
        "value": {
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "partner_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
              "product_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
              "practice_id": "6657287f-28fc-4ce7-9452-4ea8c27aa7b9",
              "site_id": "0c28be69-430a-422e-a4fc-8b1d512a2fbe",
              "status": "Completed",
              "created_at": "2025-06-01T08:00:00Z",
              "updated_at": "2026-01-18T12:00:00Z",
              "deleted_at": "2027-04-16T10:00:00Z"
            },
            {
              "id": "07558d56-1225-49b5-90fa-ab8922b6fd30",
              "partner_id": "d05ff51d-e2be-4a78-8592-41baa8cd6cba",
              "product_id": "2dec7d43-a7de-45d1-a46e-7764ffc17bac",
              "practice_id": "686cd614-9c6e-480b-a55b-b499207782b2",
              "site_id": "abc61d6c-0b23-4795-aee4-1c2e12740b59",
              "status": "Pending",
              "created_at": "2025-07-01T08:00:00Z",
              "updated_at": "2026-02-18T12:00:00Z",
              "deleted_at": "2027-05-16T10:00:00Z"
            }
          ],
          "meta": {
            "cursor": "eyJjdXJzb3IiOiJuZXh0In0"
          }
        }
      },
      "response-subscription-single-example": {
        "summary": "Single subscription",
        "description": "Wrapper returned by get subscription.",
        "value": {
          "data": {
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "partner_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
            "product_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
            "practice_id": "6657287f-28fc-4ce7-9452-4ea8c27aa7b9",
            "site_id": "0c28be69-430a-422e-a4fc-8b1d512a2fbe",
            "status": "Completed",
            "created_at": "2025-06-01T08:00:00Z",
            "updated_at": "2026-01-18T12:00:00Z",
            "deleted_at": "2027-04-16T10:00:00Z"
          }
        }
      }
    },
    "responses": {
      "list-appointments-response": {
        "description": "Paginated list of appointments for the requested practice, ordered by creation time (latest first) and then by ID for a stable sort.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Appointments in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/appointment"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-appointment-list-example"
              }
            }
          }
        }
      },
      "bad-request-response": {
        "description": "Malformed Request ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/bad-request"
            },
            "examples": {
              "badRequest": {
                "$ref": "#/components/examples/problem-bad-request-example"
              }
            }
          }
        }
      },
      "unauthorized-response": {
        "description": "Unauthorized - Provide proof of identity ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/unauthorized"
            },
            "examples": {
              "unauthorized": {
                "$ref": "#/components/examples/problem-unauthorized-example"
              }
            }
          }
        }
      },
      "user-error-response": {
        "description": "User Error ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/problem-details"
            },
            "examples": {
              "clientError": {
                "$ref": "#/components/examples/problem-user-error-example"
              }
            }
          }
        }
      },
      "server-error-response": {
        "description": "Server Error ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/server-error"
            },
            "examples": {
              "serverError": {
                "$ref": "#/components/examples/problem-server-error-example"
              }
            }
          }
        }
      },
      "create-appointment-response": {
        "description": "Successful response containing the newly created appointment resource (`data`).",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the newly created appointment as the `data` member.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Full details for the newly created appointment.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/appointment"
                    }
                  ]
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "appointment": {
                "$ref": "#/components/examples/response-appointment-single-example"
              }
            }
          }
        }
      },
      "unprocessable-entity-response": {
        "description": "Validation Error ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/unprocessable-entity"
            },
            "examples": {
              "unprocessableEntity": {
                "$ref": "#/components/examples/problem-unprocessable-entity-example"
              }
            }
          }
        }
      },
      "get-appointment-response": {
        "description": "Successful response containing a single appointment resource (`data`) for the requested identifier.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the appointment as the `data` member.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Full details for one appointment.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/appointment"
                    }
                  ]
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "appointment": {
                "$ref": "#/components/examples/response-appointment-single-example"
              }
            }
          }
        }
      },
      "not-found-response": {
        "description": "Not Found - Could not find a matching entity ([ProblemDetails](https://tools.ietf.org/html/rfc7807))",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/not-found"
            },
            "examples": {
              "notFound": {
                "$ref": "#/components/examples/problem-not-found-example"
              }
            }
          }
        }
      },
      "update-appointment-response": {
        "description": "Successful response containing the updated appointment resource (`data`).",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the updated appointment as the `data` member.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Full details for the updated appointment.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/appointment"
                    }
                  ]
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "appointment": {
                "$ref": "#/components/examples/response-appointment-single-example"
              }
            }
          }
        }
      },
      "list-appointment-reasons-response": {
        "description": "The list of appointment reasons.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "List of appointment reasons.",
                  "items": {
                    "$ref": "#/components/schemas/appointment-reason"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-appointment-reason-list-example"
              }
            }
          }
        }
      },
      "list-appointment-cancellation-reasons-response": {
        "description": "The list of appointment cancellation reasons.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "List of appointment cancellation reasons.",
                  "items": {
                    "$ref": "#/components/schemas/appointment-cancellation-reason"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-appointment-cancellation-reason-list-example"
              }
            }
          }
        }
      },
      "list-patients-response": {
        "description": "Paginated list of patients for the requested practice, ordered by creation time (latest first) and then by ID for a stable sort.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "List of patients.",
                  "items": {
                    "$ref": "#/components/schemas/patient"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            }
          }
        }
      },
      "create-patient-response": {
        "description": "Response after creating a patient (`201 Created`). The body contains the new patient resource as `data`.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the newly created patient.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Created patient record; see `components/schemas/patient.yml`.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/patient"
                    }
                  ]
                }
              }
            },
            "examples": {
              "patient": {
                "$ref": "#/components/examples/response-patient-single-example"
              }
            }
          }
        }
      },
      "get-patient-response": {
        "description": "Successful response containing a single patient resource (`data`) for the requested identifier.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "The patient record.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/patient"
                    }
                  ]
                }
              }
            },
            "examples": {
              "patient": {
                "$ref": "#/components/examples/response-patient-single-example"
              }
            }
          }
        }
      },
      "update-patient-response": {
        "description": "Response after updating a patient (`200 OK`). The body reflects the patient state after the applied changes.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "The updated patient record.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/patient"
                    }
                  ]
                }
              }
            },
            "examples": {
              "patient": {
                "$ref": "#/components/examples/response-patient-single-example"
              }
            }
          }
        }
      },
      "get-patient-account-response": {
        "description": "Account balance for the requested patient.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/patient-account"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "patientAccount": {
                "$ref": "#/components/examples/response-patient-account-example"
              }
            }
          }
        }
      },
      "list-practitioners-response": {
        "description": "Paginated list of practitioners for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Practitioners in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/practitioner"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-practitioner-list-example"
              }
            }
          }
        }
      },
      "list-practitioner-availabilities-response": {
        "description": "Paginated list of availability slots for the requested practitioners and date-time range.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Availability slots in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/availability-slot"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-practitioner-availability-list-example"
              }
            }
          }
        }
      },
      "get-practitioner-response": {
        "description": "Full details for one practitioner.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/practitioner"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "practitioner": {
                "$ref": "#/components/examples/response-practitioner-single-example"
              }
            }
          }
        }
      },
      "list-rota-schedule-histories-response": {
        "description": "Paginated list of snapshotted rota schedule history rows for the requested practitioner.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Rota schedule history rows in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/rota-schedule-history"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-rota-schedule-history-list-example"
              }
            }
          }
        }
      },
      "list-sites-response": {
        "description": "Paginated list of sites for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Sites in the current page, each including address, contact details, and opening hours for that location.",
                  "items": {
                    "$ref": "#/components/schemas/site"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-site-list-example"
              }
            }
          }
        }
      },
      "get-site-response": {
        "description": "Full details for one site.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/site"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "site": {
                "$ref": "#/components/examples/response-site-single-example"
              }
            }
          }
        }
      },
      "send-communication-response": {
        "description": "Response after sending a communication.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the ID of the communication that was sent.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/resource_timestamps"
                    },
                    {
                      "type": "object",
                      "description": "Object containing the ID of the communication that was sent.",
                      "required": [
                        "id"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "ID of the communication that was sent.",
                          "example": "123e4567-e89b-12d3-a456-426614174005"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "get-communication-details-response": {
        "description": "This response schema defines the structure of the response returned when fetching communication details. \nIt includes information about the communication, such as its ID, status, and related replies if there are any found to be mapped to the original communication.\n\nThis response is typically used in scenarios where clients need to retrieve detailed information about a specific communication, such as when viewing \ncommunication history or analyzing communication patterns.\n",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the communication details as the `data` member.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Full details for one response communication.",
                  "allOf": [
                    {
                      "type": "object",
                      "description": "Object containing the details of the communication.",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "ID of the requested communication.",
                          "example": "123e4567-e89b-12d3-a456-426614174005"
                        },
                        "communication_channel": {
                          "$ref": "#/components/schemas/communication-channel",
                          "description": "The channel used to send the communication (e.g., \"sms\", \"email\").",
                          "example": "sms"
                        },
                        "body": {
                          "type": "string",
                          "description": "The text content of the reply.",
                          "example": "I would love to attend my appointment tomorrow at 3 PM."
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/resource_timestamps"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "create-external-communication-response": {
        "description": "Response after creating an external communication.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the ID of the external communication that was created.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/resource_timestamps"
                    },
                    {
                      "type": "object",
                      "description": "Object containing the ID of the external communication that was created.",
                      "required": [
                        "id"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "ID of the external communication that was created.",
                          "example": "123e4567-e89b-12d3-a456-426614174005"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "list-fees-response": {
        "description": "Paginated list of fees for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Fees in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/fee"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-fee-list-example"
              }
            }
          }
        }
      },
      "get-fee-response": {
        "description": "Full details for one fee.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/fee"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "fee": {
                "$ref": "#/components/examples/response-fee-single-example"
              }
            }
          }
        }
      },
      "list-fee-schedules-response": {
        "description": "Paginated list of fee schedules for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Fee schedules in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/fee-schedule"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-fee-schedule-list-example"
              }
            }
          }
        }
      },
      "get-fee-schedule-response": {
        "description": "Full details for one fee schedule.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/fee-schedule"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "feeSchedule": {
                "$ref": "#/components/examples/response-fee-schedule-single-example"
              }
            }
          }
        }
      },
      "list-invoices-response": {
        "description": "The list of invoices.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "List of invoices.",
                  "items": {
                    "$ref": "#/components/schemas/invoice"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-invoice-list-example"
              }
            }
          }
        }
      },
      "get-invoice-response": {
        "description": "Successful response containing a single invoice resource (`data`) for the requested identifier.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "description": "JSON envelope with the invoice as the `data` member.",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "description": "Full details for one invoice.",
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/invoice"
                    }
                  ]
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "appointment": {
                "$ref": "#/components/examples/response-invoice-single-example"
              }
            }
          }
        }
      },
      "list-invoice-invoice-items-response": {
        "description": "Paginated list of invoice items for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "InvoiceItems in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/invoice-item"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-invoice-invoice-item-list-example"
              }
            }
          }
        }
      },
      "list-nhs-contracts-response": {
        "description": "Paginated list of NHS contracts for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "NHS contracts in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/nhs-contract"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-nhs-contract-list-example"
              }
            }
          }
        }
      },
      "get-nhs-contract-response": {
        "description": "Full details for one NHS contract.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/nhs-contract"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "contract": {
                "$ref": "#/components/examples/response-nhs-contract-single-example"
              }
            }
          }
        }
      },
      "list-calendar-zones-response": {
        "description": "Paginated list of calendar zones for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Calendar zones in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/calendar-zone"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-calendar-zone-list-example"
              }
            }
          }
        }
      },
      "get-calendar-zone-response": {
        "description": "Full details for one calendar zone.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/calendar-zone"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "calendarZone": {
                "$ref": "#/components/examples/response-calendar-zone-single-example"
              }
            }
          }
        }
      },
      "map-identifiers-response": {
        "description": "Mapped identifiers.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Mappings for requested ids that matched a record. Ids with no match are omitted.",
                  "maxItems": 100,
                  "items": {
                    "$ref": "#/components/schemas/identifier-mapping"
                  }
                }
              },
              "additionalProperties": false
            }
          }
        }
      },
      "list-treatment-categories-response": {
        "description": "Paginated list of treatment categories for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Treatment categories in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/treatment-category"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-treatment-category-list-example"
              }
            }
          }
        }
      },
      "get-treatment-category-response": {
        "description": "Full details for one treatment category.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/treatment-category"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "treatmentCategory": {
                "$ref": "#/components/examples/response-treatment-category-single-example"
              }
            }
          }
        }
      },
      "list-treatment-plans-response": {
        "description": "Paginated list of treatment plans for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Treatment Plans in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/treatment-plan"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-treatment-plan-list-example"
              }
            }
          }
        }
      },
      "get-treatment-plan-response": {
        "description": "Full details for one treatment plan.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/treatment-plan"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "treatment_plan": {
                "$ref": "#/components/examples/response-treatment-plan-single-example"
              }
            }
          }
        }
      },
      "list-treatment-plan-treatment-plan-items-response": {
        "description": "Paginated list of treatment plan items for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Treatment Plan Items in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/treatment-plan-item"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-treatment-plan-treatment-plan-item-list-example"
              }
            }
          }
        }
      },
      "list-treatments-response": {
        "description": "Paginated list of treatments for the requested practice.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "Treatments in the current page.",
                  "items": {
                    "$ref": "#/components/schemas/treatment"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-treatment-list-example"
              }
            }
          }
        }
      },
      "get-treatment-response": {
        "description": "Full details for one treatment.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/treatment"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "treatment": {
                "$ref": "#/components/examples/response-treatment-single-example"
              }
            }
          }
        }
      },
      "list-subscriptions-response": {
        "description": "The list of active subscriptions.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data",
                "meta"
              ],
              "properties": {
                "data": {
                  "type": "array",
                  "description": "List of active subscriptions.",
                  "items": {
                    "$ref": "#/components/schemas/subscription"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/meta"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "firstPage": {
                "$ref": "#/components/examples/response-subscription-list-example"
              }
            }
          }
        }
      },
      "get-subscription-response": {
        "description": "Full details for one subscription.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/subscription"
                }
              },
              "additionalProperties": false
            },
            "examples": {
              "subscription": {
                "$ref": "#/components/examples/response-subscription-single-example"
              }
            }
          }
        }
      }
    }
  },
  "x-external-paths": [
    "/market"
  ],
  "x-tagGroups": [
    {
      "name": "Appointments",
      "tags": [
        "Appointments",
        "Appointment Reasons",
        "Calendar Zones"
      ]
    },
    {
      "name": "Patients",
      "tags": [
        "Patients"
      ]
    },
    {
      "name": "Practitioners",
      "tags": [
        "Practitioners"
      ]
    },
    {
      "name": "Sites",
      "tags": [
        "Sites"
      ]
    },
    {
      "name": "Communications",
      "tags": [
        "Communications"
      ]
    },
    {
      "name": "Finance",
      "tags": [
        "Fees",
        "Fee Schedules",
        "Invoices"
      ]
    },
    {
      "name": "NHS",
      "tags": [
        "NHS Contracts"
      ]
    },
    {
      "name": "Identifier Mappings",
      "tags": [
        "Identifier Mappings"
      ]
    },
    {
      "name": "Treatments",
      "tags": [
        "Treatments",
        "Treatment Categories",
        "Treatment Plans",
        "Treatment Plan Items"
      ]
    },
    {
      "name": "Marketplace",
      "tags": [
        "Subscriptions"
      ]
    }
  ]
}