Testing writes, per system

Which health record systems take each write, what the API does on the others, and how you know a write landed.

Your Open Dental sandbox takes every write the API makes, so you can test all of them there. Live practices run 15 systems, and not every system takes every write. Before you ship, know which writes work on each practice's system.

How to read the tables

Every write can land in two places: NexHealth, and the practice's health record system. Each table shows both.

  • Saved in NexHealth means the API returns 2xx and the NexHealth record changes.
  • Written to the health record system means NexHealth queues the change for the practice's sync and it lands on the next cycle, usually within minutes. See How a write reaches the health record system. On a system the column does not list, the write stays in NexHealth and the practice does not see it.
  • 400 means the API rejects the call. Nothing is saved anywhere.
  • To learn which system a practice runs, call GET /sync_status; each sync returns an emr object with a display_name. On v3.1.0 (beta), GET /locations/{id} returns it as ehr.

Appointments

Every PATCH /appointments write is confirmed the same way: when the command finishes, appointment_updated fires on success, or appointment_updated.failed, .timed_out or .incomplete otherwise, with previous_attributes showing the field you changed.

API callSaved in NexHealthWritten to the health record system onWebhook that confirms it
POST /appointmentsYesEvery system, once the location has insert_appt_client: true. Until then the appointment stays in NexHealth.appointment_insertion: complete, or failed, timed_out or incomplete. On complete the appointment's foreign_id is set.
PATCH /appointments with cancelled: trueYesathenahealth, Cloud9, Curve Hero, Denticon, Dentrix, Dentrix Ascend, Dentrix Enterprise, Dolphin, Eaglesoft, eClinicalWorks, ModMed, NextGen Office, Open Dentalappointment_updated
PATCH /appointments with confirmed: trueYesEvery systemappointment_updated
PATCH /appointments with checkin_atYesDenticon, Dentrix, Dentrix Enterprise, Eaglesoft, ModMed, NextGen Office, Open Dentalappointment_updated
PATCH /appointments with start_time and end_time, operatory_id or noteOnly on the systems in the next column. operatory_id alone: yes on every system. A time or note change on any other system: 400 EMR does not support appointment update, nothing saved.Denticon, Dentrix, Dentrix Enterprise, Eaglesoft, Open Dentalappointment_updated

Two more rules on live practices:

  • PATCH /appointments works once the appointment has reached the system (foreign_id set). Before that, only cancelled: true is accepted, so you can free the slot when an insertion fails. Anything else returns 400 Cannot update appointment because it is not synced with the PMS and/or a live client.
  • A cancelled appointment or a scheduling block cannot be updated.

Patients

API callSaved in NexHealthWritten to the health record system onWebhook that confirms it
POST /patientsYesNo system on v3.0.0. The patient reaches the system when you book their first appointment.None on v3.0.0. The patient's foreign_id stays null until an appointment lands.
POST /appointments for a patient with no foreign_idYesathenahealth, Cloud9, Denticon, Dentrix, Dentrix Ascend, Dentrix Enterprise, Eaglesoft, eClinicalWorks, ModMed, NextGen Office, Open Dental, OrthoTrac. The patient is created in the system as part of the booking. Curve Hero, Dolphin and PracticeWorks cannot take a new patient from the API, so book with a patient the system already has.appointment_insertion. The patient's foreign_id is set when it lands.
PATCH /patientsYesNo system on v3.0.0None on v3.0.0

On v3.1.0 (beta), POST /patients sends the patient straight to Denticon, Dentrix, Eaglesoft and Open Dental and fires patient_insertion; PATCH /patients sends the change and fires patient_update.

Payments and adjustments

API callSaved in NexHealthWritten to the health record system onWebhook that confirms it
POST /paymentsNot directly. The API returns 202 on every system, and the record appears on GET /payments once the sync reads it back from the ledger.Dentrix, Dentrix Enterprise, Eaglesoft, Open Dental, where the practice has ledger sync. On any other system the payment never reaches the ledger.payment_insertion: complete, or failed, timed_out or incomplete
POST /adjustmentsThe same, on GET /adjustmentsThe same fouradjustment_insertion, same suffixes

Both calls return 202 with an empty body.

Documents

POST /patients/{id}/documents reaches the system only where document insertion is turned on for it: Curve Hero, Denticon, Dentrix, Dentrix Ascend, Dentrix Enterprise, Eaglesoft and Open Dental. For athenahealth, eClinicalWorks and OrthoTrac, ask developer support. Elsewhere the document stays in NexHealth. document_insertion fires with complete, or failed, timed_out or incomplete.

v3.1.0 (beta) only

Sandbox keys can call v3.1.0; production keys need access for your organization. See Versioning.

  • POST /insurance_plans, POST /insurance_coverages and DELETE /insurance_coverages/{id} are sent to Dentrix, Eaglesoft and Open Dental. Elsewhere the API accepts the call and the change stays in NexHealth. insurance_plan_insertion, insurance_coverage_insertion and insurance_coverage_deleted tell you whether it landed: the suffix on event_name is .complete, .failed or .timed_out.
  • POST /communication_logs is Open Dental only, and the endpoints are turned on per organization (sandbox keys included). Other systems return 422.

What this means for your sandbox

Every row that names Open Dental works on your Open Dental sandbox, so you can test each write end to end there. The demo practice has no sync behind it: bookings are accepted and never land, and PATCH /appointments returns 400 for anything but a cancel. See Sandbox and test mode.


Did this page help you?
ChangelogMCP serverErrorsdevelopers@nexhealth.com