These docs are for v2.2.2. Click to read the latest docs for v20240412.

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), null when it wasn't booked through NexHealth online booking — and always include a patient object (with guarantor_id only, not a nested guarantor).
  • [v3.1] Patient responses now include cell_phone_number and a new read-only preferred_phone_number field — 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. 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 and PATCH /patients now accept phone number and other demographic fields at the root of the patient object instead of nested under a bio object; 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 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 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") 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. It also no longer returns 422 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 for a patient that hasn't finished syncing to the EHR with 400 Bad Request; 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 appointment, EHR appointment descriptor, provider, patient, location, and operatory responses.
  • [v3.1] POST /patients and PATCH /patients no longer accept street_address, custom_contact_number, drivers_license, fax, height, insurance_name, marital_status, preferred_name, race, salutation, weight, or the untyped phone_number field — all previously available under the nested bio object. phone_number is superseded by the typed cell_phone_number/home_phone_number/work_phone_number fields described above.