Skip to main content
This is the API for HMOs and insurers that work with clinics outside the United States, and for developers who build billing tools for those clinics. It sits on top of the clinic’s HMO billing in ClinikEHR: the claims the clinic submits, the pre-authorization requests it sends, the enrollees and plans the insurer has agreed with it. The shapes follow the names Curacel’s Health API uses (insurance_no, pa_code, hmo_status, qty_approved, sub_total_billed), so an insurer that already speaks Curacel maps across with little work. It is ClinikEHR’s own API, with its own routes, errors and rules.

Two ways to use it, and who decides

A clinic decides what each connected organization is. Nothing is assumed from the name on the key. An insurer sees only its own rows. A claim, enrollee, plan, authorization request or payment advice that belongs to a different insurer is not hidden behind a permission error: it answers 404, the same as one that does not exist. An insurer also never sees what the clinic has not sent yet: a claim still being prepared, or an authorization request not yet sent for approval. The clinic owner or manager links an organization to an insurer under Settings → API access → Insurer links. A link can be ended at any time, and your access to that insurer’s data stops with it.

What you need

  • A live key that belongs to your organization, with the insurance permissions below. See Permissions.
  • An approval for the Insurer claims, authorizations and enrollees kind of patient data on your organization, and the data-protection addendum accepted. See Getting access to patient data.
  • A connection to the clinic that grants those permissions. See Connections.
  • The clinic’s link from your organization to your insurer record, if you are an insurer.

The endpoints

Lists use the cursor paging described on Pagination. Every write needs an Idempotency-Key, so a retry returns the first answer instead of doing the work twice. See Retries and duplicates.

Verify an enrollee

Send the number the patient presented. It matches the enrollee’s number and their alternate number.
status uses Curacel’s codes: AA active, IA inactive, SX suspended, XX cancelled, PP pending, WP in a waiting period. An enrollee the clinic holds under a different insurer is not found.

Read claims

GET …/insurance/claims lists the claims the clinic has submitted to you. Filter by status, hmo_status, enrollee_id and updated_since. A list row has no lines; read the claim to get them. A claim has two statuses. status is the clinic-side lifecycle (submitted, approved, partially_approved, denied, partially_paid, paid, and so on). hmo_status is your verdict (PENDING, APPROVED, PARTIALLY_APPROVED, REJECTED). paid_amount and written_off_amount are what the clinic has recorded: no API call changes them. Each line carries what was billed (qty_billed, unit_price_billed, sub_total_billed) and, once vetted, what was approved (qty_approved, unit_price_approved, sub_total_approved, hmo_item_status). Attached documents come with their name, type and size only; the files themselves are not served by this API.

Vet a claim

decision is required and sets what every line gets: approved at the billed figures, or rejected at zero. items then overrides individual lines, so “approve everything except this line” is one declined entry. A rejection needs a reason; so does a declined line, unless the body has a reason of its own. The claim’s status follows its lines: The rules the clinic’s books depend on:
  • You cannot approve more than was billed, for a quantity or a price.
  • Vetting never moves money. There is no field for a paid or written-off amount, and sending one is refused as an unknown field.
  • Once the clinic has recorded a payment or a write-off against a claim, it can no longer be vetted. It answers 409 with code: "invalid_status_transition".
  • Until then you can vet again, for example after the clinic sends more information.
The response is the claim with its lines. Send pa_code to tie the claim to an authorization you issued.

Authorization requests

GET …/insurance/pre-authorizations lists the requests the clinic has sent to you. Read one for its lines, diagnoses and the clinical reason given for each line.
An approval needs pa_code; a denial needs a reason. approved_amount defaults to the estimated cost and cannot exceed it. Lines you do not list follow the decision. A request is decided once: a second decision answers 409 with code: "invalid_status_transition".

Tell the clinic what you paid

A payment advice says “we paid this much, by this method, against these claims”. It is a message to the clinic. It does not change a claim, the clinic’s payments or its books. Clinic staff record the money themselves, and only then does a claim move to partially_paid or paid.
Each allocation names a claim of yours that is waiting for payment, for no more than it still owes, and the allocations cannot add up to more than amount. If you send a currency it must be the clinic’s currency.

Submit a claim or an authorization request

For a developer, or the clinic’s own key. A claim is saved as submitted with no money on it and answers 201 with the claim. patient_id must be a patient the clinic has linked to your organization. An organization that is linked to an insurer cannot submit: it answers 403 with code: "role_required".
Authorization requests work the same way: POST …/insurance/pre-authorizations with request_type, the lines (with unit_cost) and, optionally, the diagnosis and the clinical reason for each line. The request is saved as sent_for_authorization.

Events

Subscribe a webhook endpoint, or read the change feed. An insurer receives these events only for its own insurer records, and only while its connection grants the matching permission. Each carries ids, a number, a status and amounts, never a patient’s name or identifier.

Test keys

A test key reaches only its own sandbox clinic, which holds no insurance data. Lists answer an empty page and reads answer 404. Writes also answer 404. Use a live key against a clinic that has linked your organization to try the routes.

Errors you will meet

See Errors for the codes shared by every route.