When something breaks

The six problems new integrations hit, what each one means, and what to do.

Most new integrations hit the same six problems. Here is what each one means and what to do.

1. You get a 401

The token is missing, expired or wrong.

  • Get a bearer token from POST /authenticates with your API key in the Authorization header, then send Authorization: Bearer <token> on every other call.
  • A token lasts 1 hour. Refresh before it expires, and refresh and retry on a 401.
  • The sandbox key and the production key give different tokens. A sandbox token does not work on a live practice.

2. You get a 403 You don't have access to perform this action.

The token is good, but it cannot reach what you asked for.

  • The sandbox key reaches sandbox practices and the production key reaches live practices. The Test mode toggle in the Developer Portal shows which practices each key sees.
  • The subdomain is misspelled, or it belongs to a practice that is not on your account.
  • On POST /webhook_endpoints/{id}/webhook_subscriptions, subdomain goes in the query string. If you put it in the JSON body instead, the call returns 403.
  • You sent the old Accept: application/vnd.Nexhealth+json;version=2 header instead of Nex-Api-Version: v3.0.0. New accounts reject v2 calls with API version 'v2' is below the minimum allowed. With neither header the call returns 404. See Versioning.

3. You get a 400

The response says what is wrong. Read error in the body. The messages new developers see most:

MessageCause
A patient with that information already exists - id=123Same name and date of birth as a patient already at this location, where 123 is that patient's id. Send return_existing_if_match=true to get the existing patient back with a 200 instead.
EMR does not support appointment updateYou changed start_time, end_time, operatory_id or note on a system that does not take appointment updates. See Testing writes, per system.
Cannot update appointment because it is not synced with the PMS and/or a live clientThe appointment has not reached the system yet (foreign_id is null). Wait for appointment_insertion, or cancel it.
Time slot is in the past, please choose another timeThe end_time you sent is already behind. Check the time zone of the time you send.
Unfortunately this time is no longer available, please go back and choose another time.The provider, or the operatory where the location books by operatory, already has an appointment in that range. Fetch GET /available_slots again and book another.
Cannot create an appointment where the patient attribute new_patient=trueThe patient record is a new-patient placeholder that does not fully exist in the system. Use a patient record with new_patient: false.
Cannot update already cancelled appointmentA cancelled appointment cannot be changed. Book a new one.

A 200 or 201 can also carry a warning. If description says Note that following parameters are ignored, the call worked and the API dropped a parameter the endpoint does not take.

Every error code is listed in Errors.

4. You get a 429

You sent too many requests in a short time. The response carries a Retry-After header with the seconds to wait. Wait that long, then retry. The limits, and how to raise them, are on Rate limits. If you poll on a timer, switch to webhooks.

5. The call returned 2xx and nothing appeared in the practice's system

A 201 or 202 means NexHealth accepted the write. It reaches the system on the next sync cycle, in minutes, or longer when the office is closed.

  1. Is it a write the system takes? Some writes stay in NexHealth with no error. Check Testing writes, per system.
  2. Did the event fire? Subscribe to appointment_insertion, payment_insertion and the other *_insertion events before you test. complete means it landed and foreign_id is set. failed means the system rejected it. The failed event does not say why. For a cancel, confirm, check-in or reschedule, the signal is appointment_updated, or appointment_updated.failed when the system rejected it. The usual causes are on Troubleshooting appointment writes.
  3. Is the sync up? Call GET /sync_status for the practice. A red write_status means the sync has not picked up a write in the last 25 minutes. Server systems are off when the office is closed, and cloud systems need a staff member logged in. See Interpreting sync status.
  4. Is this the demo practice? The demo practice has no system behind it. Nothing you write there goes anywhere. See Sandbox and test mode.
  5. Is foreign_id still null? Then the system does not have the record yet. last_sync_time is the last time NexHealth refreshed the record from the system. Both null means the system has never seen it.

Missing slots are a different problem. See Troubleshooting available slots.

6. You are stuck

Email [email protected] or use the chat in the Developer Portal. Include:

  • the subdomain and location_id
  • the id of the record (appointment, patient or payment) and the time of the call
  • the full response body, including the error text
  • what you expected to see in the practice's system

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