---
agentTools:
  projectIndex: https://docs.nexhealth.com/llms.txt
---

# August 2026

# What's New

This release adds `Provider` and `WorkingHour` webhook events, includes booking details in `appointment_created` webhooks, reworks how v3.1 patient phone numbers are written and returned, and removes `last_sync_time` from several v3.1 responses.

***

## Added

* **\[v3.1]** New `provider_created` and `provider_updated` webhook events, subscribable under the `Provider` resource type.

* **\[v3.1]** New `working_hour_created` and `working_hour_updated` webhook events, subscribable under the `WorkingHour` resource type.

* **\[v3.1]** `appointment_created` webhook payloads (for subscriptions pinned to `v3.1.0`) now include:
  * `booking_details` — context about how the appointment was booked online: `booked_via_nexhealth_generated_link`, `campaign_type`, `campaign_id`, `campaign_medium`, `booked_via_one_click`. This is `null` when the appointment wasn't booked through NexHealth online booking.
  * A `patient` object, which contains `guarantor_id` only (not a nested guarantor).

* **\[v3.1]** Patient responses now include two new fields:
  * `cell_phone_number`
  * `preferred_phone_number` (read-only) — the best-known number, in priority order: the integrated system's untyped primary number, then cell, home, and work numbers. `cell_phone_number` falls back to that same untyped primary number when the integrated system doesn't report a distinct typed cell number.
  * Note: the previous untyped `phone_number` field is no longer present on patient responses (provider responses are unaffected).

* **\[v3.1]** `ssn` is now included in patient responses (previously write-only) — but only on single-patient responses (create, update, and fetch-by-id). It does **not** appear in patient list responses or in patient objects embedded in other resources (e.g., an appointment's `patient`).

* **\[v3.1]** `GET /locations/:id` responses now include an `ehr` field describing the EHR the location syncs with.

***

## Changed

* **\[v3.1]** `POST /patients` / `PATCH /patients` request shape:
  * Phone number and other demographic fields now live at the **root** of the `patient` object (previously nested under `bio`).
  * Address fields move into a new nested `address` object — `line_1`, `line_2`, `city`, `region`, `postal_code` — instead of separate `bio` keys.

* **\[v3.1]** `POST /patients` now requires at least one non-blank phone number (`cell_phone_number`, `home_phone_number`, or `work_phone_number`). On both `POST` and `PATCH`, phone number fields can no longer be set to a blank value.

* **\[v3.1]** `POST /patients` only enqueues insertion into the EHR when the connected EHR supports creating patients directly (currently Denticon, Dentrix, Eaglesoft, and Open Dental). For other EHRs, the response `description` now explains that the patient will be added when an appointment is booked for them.

* **\[v3.1]** `PATCH /patients/:id` no longer returns `422` ("Patient has not been synced to the EHR") in two cases:
  * For a patient at a location with no connected EHR — such a patient can never receive a `foreign_id`, so this update was previously never possible at all.
  * When the patient's EHR insert is merely still in progress — the update is now accepted and applied once the insert completes.

* **\[v3.1]** `GET /payment_plans/:id` with `include=patient` or `include=guarantor`:
  * Now nests the patient/guarantor object in v3.1's patient shape (no `bio` wrapper; includes `cell_phone_number` / `preferred_phone_number`) instead of the v2 shape it previously received.
  * The `location_ids` and `preferred_locale` fields, previously available on that nested object, are no longer present.

* **\[v3.1]** `GET /available_slots`:
  * Now respects an explicitly-provided `slot_interval` even when the location has `book_on_minutes` configured. Previously, `book_on_minutes` always forced a fixed 5-minute step between candidate slots, regardless of any `slot_interval` passed.
  * `slot_interval` must now be a positive integer.

* **\[v3.0, v3.1]** `POST /payments` no longer always rejects a payment with `400 Bad Request` for a patient that hasn't finished syncing to the EHR. If a patient-insert sync is already in flight, the request now returns `202 Accepted` (empty body), and the payment syncs to the EHR once the patient insert completes.

* **\[v2, v3.0]** `GET /locations` and `GET /locations/:id` now exclude locations that are still in onboarding; requesting one directly by id returns `404 Not Found`.

* **\[v3.1]** `GET /locations` (list) also excludes onboarding locations. `GET /locations/:id` does **not** — an onboarding location can still be fetched directly by id.

* NexHealth no longer supports server operating systems prior to Windows 10. To maintain compatibility with the NexHealth Synchronizer, servers running legacy operating systems must be upgraded to Windows 10 or higher.

***

## Fixed

* **\[v3.1]** `GET /appointment_categories` and `GET /appointment_categories/:id` now actually return the `operatories` field when `include=operatories` is passed — previously the parameter was accepted and used internally, but the field was never exposed in the response.

* **\[v3.1]** The `operatory_ids` filter on the `available_slots` endpoint no longer silently falls back to returning slots for every operatory when the filter matches none; it now correctly returns no slots.

* **\[v2]** `POST /webhook_endpoints` and `PATCH /webhook_endpoints/:id` now return the correct `description` message ("New endpoint created successfully" / "Endpoint updated successfully") in the response — a parameter-name typo previously caused a generic fallback message to be returned instead.

***

## Removed

* **\[v3.1]** `last_sync_time` has been removed from responses for:
  * appointment
  * EHR appointment descriptor
  * provider
  * patient
  * location
  * operatory

* **\[v3.1]** `POST /patients` and `PATCH /patients` no longer accept the following fields (all previously available under the nested `bio` object):
  * `street_address`
  * `custom_contact_number`
  * `drivers_license`
  * `fax`
  * `height`
  * `insurance_name`
  * `marital_status`
  * `preferred_name`
  * `race`
  * `salutation`
  * `weight`
  * `phone_number` (untyped) — superseded by the typed `cell_phone_number` / `home_phone_number` / `work_phone_number` fields described above.