Bill a visit and read back what it was paid
Ask Practor to invoice a visit your system sent, issue it and claim from the insurer in the same call, then read the claim's outcome and the payments back.
Once a visit is in Practor, one request turns it into an invoice, priced with the same rates and rules as one made by hand.
Invoice a visit
POST /api/v1/encounters/{encounterId}/bill, with an Idempotency-Key header and a body saying what to do once the invoice is drafted:
{ "issue": true, "submitClaim": true }
| Field | Effect |
|---|---|
issue | true issues the invoice. Without it, the invoice is left as a draft for the practice to check |
submitClaim | true submits it as a claim to the patient's insurer. Needs issue too |
coverageId | The insurance to claim from. Left out, the patient's first medical insurance |
placeOfServiceCode | The code for where the visit took place, for a claim that asks for it |
Billing needs the Create tick on Invoices. Issuing also needs the Update tick on Invoices, because it changes the invoice and tells the patient. Submitting a claim also needs the Submit or verify tick on Claims.
Send no body at all to draft the invoice and leave it for the practice, or to change its prices yourself before you issue it: Change an invoice and claim it from your own system. The invoice a visit page has the body and the answer in full.
Read the answer
The answer is a 201 with "object": "bill_result":
| Field | What it holds |
|---|---|
invoice | The invoice |
issued | Whether the invoice was issued. null when you didn't ask |
issueSkippedReason | Why it wasn't issued, when you asked and it wasn't |
claimQueued | Whether the claim was queued. null when you didn't ask, or the invoice wasn't issued |
claimSkippedReason | Why the claim wasn't queued |
Each reason uses the words the practice sees in Practor. The invoice is kept either way, as a draft if it couldn't be issued, so the practice can fix what's wrong and finish it.
| Status | Message | What to do |
|---|---|---|
| 422 | A claim can only be submitted for an issued invoice. Send issue=true with submitClaim=true. | Add issue |
| 409 | This encounter is already billed on invoice ... | Read that invoice instead. The id varies |
| 422 | An encounter in status ... cannot be billed. | Only a finished visit can be billed. The status varies |
| 403 | This integration client does not have Update on Invoices. A practice owner can add it under Permissions. | Ask the practice to tick Update on Invoices, or send issue as false to leave a draft |
| 403 | This integration client does not have Submit on Claims. A practice owner can add it under Permissions. | Ask the practice to tick Submit or verify on Claims |
| 422 | The encounter has no billable procedures. | Send the visit again with its procedure codes |
| 429 | Too many encounters billed for this practice in the last minute. Slow down and retry. | Wait the Retry-After seconds, then retry with the same Idempotency-Key |
Read an invoice
GET /api/v1/invoices/{invoiceId} gives the invoice, every field of it on the read an invoice page. Amounts are whole numbers in the smallest unit of its currency, such as cents.
| Field | What it holds |
|---|---|
status | Practor's own status: draft, issued, amending, partially_paid, balanced, overdue, cancelled, written_off or entered_in_error |
amountPaid and balanceDue | What's been paid and what's left |
claimStatus | Where the claim is, if one was submitted: submitting, accepted, partially_accepted, rejected, reversing, reversed or reversal_failed. null before then |
coverageId and encounterIds | The insurance claimed against, and the visits billed |
lineItems | Each line's code, quantity, prices, diagnoses, and in pricingSource where its price came from |
GET /api/v1/invoices?encounterId={id} or ?patientId={id} finds invoices for one visit or one patient.
Keep in step with changes
GET /api/v1/invoices?updatedSince=2026-10-01T08:00:00Z lists the invoices that changed after that moment, oldest first. While hasMore is true, send nextCursor back as cursor. Remember the last updatedAt you saw and ask from there next time.
Webhooks tell you without asking: Get told when an invoice, claim or payment changes.
Read the claim's outcome
GET /api/v1/invoices/{invoiceId}/claim gives the claim:
outcomeisqueued,complete,partialorerror. A reversed claim also readscomplete, so checkstatusas well.- Each entry in
itemsis an invoice line, numbered bylineNumber, with what was claimed insubmittedand what the insurer will pay inbenefit. - Each item lists its
rejectionsandwarnings, each with the insurer's code and reason.
Before a claim is submitted, the answer is a 404 that reads "No claim has been submitted for this invoice."
Read the payments
GET /api/v1/invoices/{invoiceId}/payments lists each payment against the invoice, whether the patient paid or the insurer did. method says which, such as medical_aid or card.
Related
Was this helpful?
Next in Security and integrations
Change an invoice and claim it from your own system Bill the visit as a draft, set each line to the price the insurer pays, then issue it and send the claim through the API. 4 min readMore in Security and integrations
- Connect your own software to Practor Create an integration client for your other system, give it the permissions it needs, and hand its key to whoever builds the connection. 5 min read
- See what was done in your practice in the audit log Open the audit log in your organization settings, filter it to one person or connected system, and export what it shows as a CSV. 3 min read
- Send patients and visits to Practor from your own system Register patients under your own patient number, record their insurance, and send each finished visit with its diagnosis and procedure codes. 4 min read