Troubleshooting payments

What goes wrong on the ledger endpoints, and the fix for each.

Read the response body first. A failed request has code: false and the message in error. A 202 on POST /payments or POST /adjustments means NexHealth accepted the request, so some problems only show up later, when the write into the health record system fails.

The request fails

You don't have access to perform this action. on /charges, /payments, /adjustments, /claims, /fee_schedules, /insurance_plans or a balance endpoint

  • Cause: Financial data is not turned on for your production key. Sandbox locations have it on by default.
  • Fix: Email [email protected]. The ledger backfill takes up to a day after it is turned on.

Payment Type with id 1 not found in location 456 on POST /payments

  • Cause: The payment type does not exist at that location, or is not active there.
  • Fix: Use an id from GET /payment_types called with the same location_id.

Adjustment Type with id 1 not found in location 456 on POST /adjustments

  • Cause: The adjustment type does not exist at that location.
  • Fix: Use an id from GET /adjustment_types called with the same location_id.

Patient with ID 123 not found in location 456 on POST /payments

  • Cause: The patient belongs to another location on the same server. GET /patients returns patients from every location on that server unless you say otherwise.
  • Fix: Send location_strict=true on GET /patients. Check location_ids on GET /patients/{id} before you post.

Something went wrong. Please try again or contact our support team. on POST /payments

  • Cause: The patient is not in the health record system yet. Their foreign_id is null and foreign_id_type is nex. A patient created through the API is written into the health record system with their first appointment.
  • Fix: Book an appointment for the patient first, then post the payment.

A debit adjustment fails on POST /adjustments

  • Cause: A positive adjustment has to be linked to a charge or a provider. The request had neither charge_splits nor provider_splits.
  • Fix: Send charge_splits with the charge IDs the debit applies to, or provider_splits with the provider IDs.

A list call fails with no filter on GET /charges, GET /payments, GET /adjustments or GET /guarantor_balances

  • Cause: These endpoints need at least one filter. Charges take patient_id, provider_id, procedure_id, guarantor_id or updated_since. Guarantor balances take guarantor_id or updated_since.
  • Fix: Add a filter. For a full load, use updated_since with a date before the practice went live.

The request succeeds, but the ledger is wrong

POST /payments returns 202 but the payment never appears

  • Cause: The payment type is inactive or belongs to another location, the transaction_id was already used, or writes are paused because write_status on GET /sync_status is red. The health record system does not accept two payments with the same transaction ID.
  • Fix: Subscribe to payment_insertion to get a complete or failed result for every payment. Use a payment_type_id from GET /payment_types for that location and a new transaction_id on every call. Then check GET /payments with transaction_id to see what landed.

A payment came back as an adjustment

  • Cause: You posted a refund as a positive payment to Dentrix, Dentrix Enterprise or Eaglesoft. Those systems record refunds as adjustments, so NexHealth converted it. The response said an adjustment was created.
  • Fix: Nothing. This is how refunds work on those systems. Open Dental records a refund as a positive payment.

A payment was recorded as a refund

  • Cause: The amount was positive. A payment that lowers the balance is negative.
  • Fix: Send negative amounts for payments and for the values in charge_splits and provider_splits. Post a correcting payment for the one that went in as a refund.

One payment became several records

  • Cause: The payment was split across providers. The health record system stores one payment per provider.
  • Fix: Nothing. All of them carry your transaction_id. Filter GET /payments by it to see the set.

charge_id is null on every payment

  • Cause: The location runs on Dentrix, which cannot link a payment to a charge.
  • Fix: Use provider_splits on Dentrix and match payments to charges in your own records.

The balance does not match what the office sees

  • Cause: Balances are per guarantor, not per patient, so a family's balance sits on the responsible party. NexHealth reads the ledger on a cycle, so a payment the office just entered appears after the next read. Deleted charges and payments are left out unless you ask for them.
  • Fix: Read GET /guarantor_balances with the patient's guarantor_id. Check the time of the last read on GET /sync_status. Send include_deleted=true when you keep your own copy of the ledger.

Charges are missing right after financial data was turned on

  • Cause: The ledger backfill takes up to a day and is still running.
  • Fix: Wait for the backfill. If charges are still missing after a day, email [email protected] with the subdomain and location_id.

Still stuck

Email [email protected] with the request, the full response body, the subdomain, the location_id, the transaction_id and the time of the call in UTC. Every message the API returns is in the Errors reference.


Did this page help you?