Find invoices by encounter or patient, or list the ones that changed
By encounterId or patientId, or with updatedSince for every invoice that changed since, oldest change first.
API version 1.3.1
Operations in Invoices
- GET Find invoices by encounter or patient, or list the ones that changed
- GET Read an invoice
- POST Add a line to a draft invoice
- PUT Replace a line on a draft invoice, such as its price
- DELETE Remove a line from a draft invoice
- GET List the prices Practor knows for a line
- POST Issue a draft invoice
- POST Reopen an issued invoice to change it
- GET List the payments made against an invoice
/api/v1/invoices While hasMore is true, send nextCursor back as cursor.
The integration client needs INVOICES:READ. A practice owner
grants it under Permissions on the client.
Request
{
"object": "list",
"data": [
{
"object": "invoice",
"id": "i2q6w8e0r4t7y1u3o5p9a6sd",
"number": "INV-000123",
"status": "issued",
"claimStatus": "submitting",
"patientId": "k3v9x2m8q1w7e4r6t0y5u2ia",
"coverageId": "c9d1f4g7h2j5k8l0z3x6v1bn",
"encounterIds": [
"e7j3p5s9d1f4g6h8k2l0m3nb"
],
"recipientName": "Thandi Mokoena",
"date": "2026-10-01",
"dueDate": "2026-10-31",
"currency": "ZAR",
"totalNet": 45000,
"totalGross": 45000,
"amountPaid": 0,
"balanceDue": 45000,
"lineItems": [
{
"id": "l8k5j2h9g6f3d0s7a4q1w8ez",
"serviceDate": "2026-10-01",
"serviceDateEnd": null,
"system": null,
"code": "0190",
"description": "Consultation",
"modifiers": [],
"quantity": 1,
"unitPrice": 45000,
"subtotal": 45000,
"total": 45000,
"pricingSource": "medical_aid",
"diagnoses": [
{
"system": "http://hl7.org/fhir/sid/icd-10-za",
"code": "J06.9",
"display": "Acute upper respiratory infection, unspecified",
"primary": true
}
]
}
],
"updatedAt": "2026-10-01T07:45:12.000Z"
}
],
"hasMore": true,
"nextCursor": "string"
} Parameters
Query
-
encounterIdstring -
The visit billed.
-
patientIdstring -
The patient's id.
-
updatedSincestring (date-time) -
Every invoice that changed after this moment, oldest change first. Keep the last
updatedAtyou saw and ask from there. A change appears once it is 5 seconds old, so a write still being saved can't be skipped.Matches
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$. -
limitinteger -
How many to answer with, from 1 to 100. The default is 50.
Defaults to
50. At least1. At most100. -
cursorstring -
The
nextCursorof the page before, for the page after it.
Responses
200 A page of the invoices that match, in data. While hasMore is true, send nextCursor back as cursor for the next page.
Headers
-
X-Request-Idstring Required -
Quote it if you contact support about this request.
-
X-RateLimit-Limitstring Required -
Requests allowed in the current window.
-
X-RateLimit-Remainingstring Required -
Requests left in the current window.
-
X-RateLimit-Resetstring Required -
When the window resets, in seconds since the Unix epoch.
Body
InvoiceList
-
object"list" Required -
dataarray of Invoice Required-
object"invoice" Required -
idstring Required -
numberstring RequiredThe invoice number the patient sees.
-
statusstring RequiredOne of
draft,issued,amending,balanced,cancelled,entered_in_error,partially_paid,overdue,written_off. -
claimStatusstring or null RequiredWhere the claim to the insurer stands. Null when none was sent.
-
patientIdstring Required -
coverageIdstring or null RequiredThe coverage the claim was sent under. Null on an invoice whose claim has not been sent.
-
encounterIdsarray of string RequiredThe visits billed on it.
-
recipientNamestring or null Required -
datestring RequiredYYYY-MM-DD.
-
dueDatestring or null Required -
currencystring RequiredISO 4217 currency code. Every amount on the resource is in it.
-
totalNetinteger RequiredBefore tax, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
totalGrossinteger RequiredWhat the invoice is for, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
amountPaidinteger RequiredPaid so far, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
balanceDueinteger RequiredStill owed, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
lineItemsarray of object Required-
idstring Required -
serviceDatestring RequiredYYYY-MM-DD.
-
serviceDateEndstring or null Required -
systemstring or null RequiredThe code system, by its URL.
-
codestring Required -
descriptionstring Required -
modifiersarray of string RequiredTariff modifiers applied to the line.
-
quantitynumber Required -
unitPriceinteger RequiredThe price of one, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
subtotalinteger RequiredQuantity times the unit price, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
totalinteger RequiredThe line after any discount or surcharge, in the currency's minor unit (cents for ZAR).
At least
-9007199254740991. At most9007199254740991. -
pricingSourcestring or null RequiredWhere the unit price came from: a professional body, a medical insurance rate, the practice, or set by hand.
-
diagnosesarray of object RequiredWhat the line treats. A claim needs a primary one.
-
systemstring or null RequiredThe code system, by its URL.
-
codestring Required -
displaystring Required -
primaryboolean RequiredThe diagnosis the line is claimed under. One per line.
-
-
-
updatedAtstring RequiredAn ISO 8601 date-time in UTC.
-
-
hasMoreboolean RequiredWhether another page follows this one.
-
nextCursorstring or null RequiredSend it as
cursorfor the next page. Null on the last page.
{
"object": "list",
"data": [
{
"object": "invoice",
"id": "i2q6w8e0r4t7y1u3o5p9a6sd",
"number": "INV-000123",
"status": "issued",
"claimStatus": "submitting",
"patientId": "k3v9x2m8q1w7e4r6t0y5u2ia",
"coverageId": "c9d1f4g7h2j5k8l0z3x6v1bn",
"encounterIds": [
"e7j3p5s9d1f4g6h8k2l0m3nb"
],
"recipientName": "Thandi Mokoena",
"date": "2026-10-01",
"dueDate": "2026-10-31",
"currency": "ZAR",
"totalNet": 45000,
"totalGross": 45000,
"amountPaid": 0,
"balanceDue": 45000,
"lineItems": [
{
"id": "l8k5j2h9g6f3d0s7a4q1w8ez",
"serviceDate": "2026-10-01",
"serviceDateEnd": null,
"system": null,
"code": "0190",
"description": "Consultation",
"modifiers": [],
"quantity": 1,
"unitPrice": 45000,
"subtotal": 45000,
"total": 45000,
"pricingSource": "medical_aid",
"diagnoses": [
{
"system": "http://hl7.org/fhir/sid/icd-10-za",
"code": "J06.9",
"display": "Acute upper respiratory infection, unspecified",
"primary": true
}
]
}
],
"updatedAt": "2026-10-01T07:45:12.000Z"
}
],
"hasMore": true,
"nextCursor": "string"
} 400 A query parameter or header is missing or malformed, or the body isn't JSON. errors names the parameter.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 401 No key was sent, or the key cannot be used: unknown, revoked or expired, its client suspended, or the call made from outside its allowed addresses. All of these answer the same way; the practice audit log names which it was.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 403 The client lacks the permission this endpoint needs, or the practice's Integrations add-on is off.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 405 This endpoint doesn't take that method. The Allow header names the one it does.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 422 patientId names no patient of this practice. errors names the parameter.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 429 Too many requests. Wait the number of seconds in the Retry-After header, then send it again.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 500 Something went wrong on our side. Quote the X-Request-Id if you contact support.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
} 503 The request couldn't be written to the practice audit log, so its result is withheld. Wait the number of seconds in the Retry-After header, then send it again.
Body
Problem
-
typestring RequiredWhere the error is explained:
https://developers.practor.app/guides/errors#and the code, with hyphens for underscores. -
titlestring RequiredA short summary of the kind of problem.
-
statusinteger RequiredThe HTTP status, repeated.
At least
-9007199254740991. At most9007199254740991. -
detailstring RequiredWhat went wrong with this request, in a sentence you can show a person.
-
codestring RequiredThe kind of problem. It stays the same across releases, so branch on it.
One of
invalid_request,invalid_cursor,validation_failed,unauthenticated,forbidden,addon_inactive,not_found,method_not_allowed,conflict,duplicate,business_rule,unprocessable,idempotency_key_reused,payload_too_large,unsupported_media_type,rate_limited,internal_error,service_unavailable. -
requestIdstring RequiredThe same as the X-Request-Id header. Quote it if you contact support.
-
errorsarray of FieldErrorOne entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.
-
fieldstring RequiredThe field, query parameter or header the problem is in. A field in the body is a dotted path, such as
givenNames.0orprocedures.1.code. -
codestring Requiredrequiredwhen it was left out,invalidwhen its value is wrong.One of
required,invalid. -
messagestring RequiredWhat was wrong, in a sentence you can show a person.
-
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{
"field": "lastName",
"code": "required",
"message": "Send lastName."
},
{
"field": "birthDate",
"code": "invalid",
"message": "birthDate must be a real date, written YYYY-MM-DD"
}
]
}