Skip to main content
Operations in Invoices
GET /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

Language
curl 'https://dashboard.practor.app/api/v1/invoices?encounterId=e7j3p5s9d1f4g6h8k2l0m3nb' \
  -H "Authorization: Bearer $PRACTOR_API_KEY"
const response = await fetch("https://dashboard.practor.app/api/v1/invoices?encounterId=e7j3p5s9d1f4g6h8k2l0m3nb", {
  headers: {
    Authorization: `Bearer ${process.env.PRACTOR_API_KEY}`,
  },
});
const resource = await response.json();
import os, uuid
import requests

response = requests.get(
    "https://dashboard.practor.app/api/v1/invoices?encounterId=e7j3p5s9d1f4g6h8k2l0m3nb",
    headers={
        "Authorization": f"Bearer {os.environ['PRACTOR_API_KEY']}",
    },
)
resource = response.json()
Response 200
{
  "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

encounterId string

The visit billed.

patientId string

The patient's id.

updatedSince string (date-time)

Every invoice that changed after this moment, oldest change first. Keep the last updatedAt you 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)))$.

limit integer

How many to answer with, from 1 to 100. The default is 50.

Defaults to 50. At least 1. At most 100.

cursor string

The nextCursor of 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-Id string Required

Quote it if you contact support about this request.

X-RateLimit-Limit string Required

Requests allowed in the current window.

X-RateLimit-Remaining string Required

Requests left in the current window.

X-RateLimit-Reset string Required

When the window resets, in seconds since the Unix epoch.

Body

InvoiceList

  • object "list" Required
  • data array of Invoice Required
    • object "invoice" Required
    • id string Required
    • number string Required

      The invoice number the patient sees.

    • status string Required

      One of draft, issued, amending, balanced, cancelled, entered_in_error, partially_paid, overdue, written_off.

    • claimStatus string or null Required

      Where the claim to the insurer stands. Null when none was sent.

    • patientId string Required
    • coverageId string or null Required

      The coverage the claim was sent under. Null on an invoice whose claim has not been sent.

    • encounterIds array of string Required

      The visits billed on it.

    • recipientName string or null Required
    • date string Required

      YYYY-MM-DD.

    • dueDate string or null Required
    • currency string Required

      ISO 4217 currency code. Every amount on the resource is in it.

    • totalNet integer Required

      Before tax, in the currency's minor unit (cents for ZAR).

      At least -9007199254740991. At most 9007199254740991.

    • totalGross integer Required

      What the invoice is for, in the currency's minor unit (cents for ZAR).

      At least -9007199254740991. At most 9007199254740991.

    • amountPaid integer Required

      Paid so far, in the currency's minor unit (cents for ZAR).

      At least -9007199254740991. At most 9007199254740991.

    • balanceDue integer Required

      Still owed, in the currency's minor unit (cents for ZAR).

      At least -9007199254740991. At most 9007199254740991.

    • lineItems array of object Required
      • id string Required
      • serviceDate string Required

        YYYY-MM-DD.

      • serviceDateEnd string or null Required
      • system string or null Required

        The code system, by its URL.

      • code string Required
      • description string Required
      • modifiers array of string Required

        Tariff modifiers applied to the line.

      • quantity number Required
      • unitPrice integer Required

        The price of one, in the currency's minor unit (cents for ZAR).

        At least -9007199254740991. At most 9007199254740991.

      • subtotal integer Required

        Quantity times the unit price, in the currency's minor unit (cents for ZAR).

        At least -9007199254740991. At most 9007199254740991.

      • total integer Required

        The line after any discount or surcharge, in the currency's minor unit (cents for ZAR).

        At least -9007199254740991. At most 9007199254740991.

      • pricingSource string or null Required

        Where the unit price came from: a professional body, a medical insurance rate, the practice, or set by hand.

      • diagnoses array of object Required

        What the line treats. A claim needs a primary one.

        • system string or null Required

          The code system, by its URL.

        • code string Required
        • display string Required
        • primary boolean Required

          The diagnosis the line is claimed under. One per line.

    • updatedAt string Required

      An ISO 8601 date-time in UTC.

  • hasMore boolean Required

    Whether another page follows this one.

  • nextCursor string or null Required

    Send it as cursor for the next page. Null on the last page.

Example 200 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 400 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 401 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 403 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 405 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 422 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 429 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 500 body
{
  "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

  • type string Required

    Where the error is explained: https://developers.practor.app/guides/errors# and the code, with hyphens for underscores.

  • title string Required

    A short summary of the kind of problem.

  • status integer Required

    The HTTP status, repeated.

    At least -9007199254740991. At most 9007199254740991.

  • detail string Required

    What went wrong with this request, in a sentence you can show a person.

  • code string Required

    The 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.

  • requestId string Required

    The same as the X-Request-Id header. Quote it if you contact support.

  • errors array of FieldError

    One entry per field that is missing or wrong, all at once, so you can fix a request in one round trip.

    • field string Required

      The field, query parameter or header the problem is in. A field in the body is a dotted path, such as givenNames.0 or procedures.1.code.

    • code string Required

      required when it was left out, invalid when its value is wrong.

      One of required, invalid.

    • message string Required

      What was wrong, in a sentence you can show a person.

Example 503 body
{
  "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"
    }
  ]
}