Invoices
An invoice is the billing artifact for a visit or any set of line items a clinic charges to a client. Each invoice belongs to exactly one client and one clinic, and groups one or more invoice items: the individual products, services, or fees that make up the charge. To build a full picture of a visit you usually fetch the invoice, then embed or list the invoice items that hang off it.
Invoices link out to several other resources: the client being billed, the patient receiving care, the products on each line, and the providers who delivered the service. Use embedding to pull related records back in a single round trip.
Schema
Section titled “Schema”Authoritative schemas live in the live Swagger UI. The fields below are a representative subset for orientation.
| Field | Type | Description |
|---|---|---|
id | string | Server-assigned identifier. |
invoiceNumber | integer | The number assigned to the invoice. |
clinicId | string | Clinic that owns the invoice. |
clientId | string | Client (account holder) being billed. |
statusId | string | Lifecycle state reference. invoiceStatus expands it. |
invoiceItems | array | The line items on this invoice. |
subtotal | number | Sum of line-item amounts before tax and discount. |
discount | number | Discount amount applied. |
tax | number | Tax amount applied. |
total | number | Final invoice total after all calculations. |
paid | number | Total amount paid towards the invoice. |
balance | number | Remaining unpaid amount. |
isPaid | boolean | Whether the invoice is fully paid. |
isReturn | boolean | Whether this invoice is a product return. |
isTaxExempt | boolean | Whether the invoice is tax exempt. |
dateIssued | string | ISO 8601 UTC issue date. |
dateCheckedOut | string | ISO 8601 UTC checkout date. |
dateCreated | string | ISO 8601 UTC timestamp of creation. |
dateUpdated | string | ISO 8601 UTC timestamp of last update. |
isDeleted | boolean | Soft-delete flag. Note this is isDeleted, not deleted. |
Invoice items are read through their own endpoint and carry a much wider shape than the invoice itself: alongside id, invoiceId, productId, name, price, productQuantity, discount, taxRate, subtotal, and total, they include lot and inventory tracking (lotNumber, lotExpirationDate, inventoryLotId), controlled-substance and medication detail, return and refund linkage, and production attribution. Note the quantity field is productQuantity, not quantity, and the unit price is price, not unitPrice. See the live Swagger UI for the full list.
List / search
Section titled “List / search”/pav2/open-api-invoices Standard collection envelope, paginated and filterable. See Conventions for the full pagination, sort, and date-range model.
Example
Section titled “Example”curl -X POST https://open-api.shepherd.vet/pav2/open-api-invoices \ -H "Content-Type: application/json" \ -H "X-Integration-Public-Key: $SHEPHERD_PUBLIC_KEY" \ -H "X-Integration-Private-Key: $SHEPHERD_PRIVATE_KEY" \ -H "X-Clinic-Id: $SHEPHERD_CLINIC_ID" \ -d '{ "page": 1, "rpp": 25, "dateCreatedFrom": "2026-04-01T00:00:00Z", "dateCreatedTo": "2026-04-30T23:59:59Z", "sort": "dateCreated|desc" }'import os, requests
resp = requests.post( "https://open-api.shepherd.vet/pav2/open-api-invoices", headers={ "Content-Type": "application/json", "X-Integration-Public-Key": os.environ["SHEPHERD_PUBLIC_KEY"], "X-Integration-Private-Key": os.environ["SHEPHERD_PRIVATE_KEY"], "X-Clinic-Id": os.environ["SHEPHERD_CLINIC_ID"], }, json={ "page": 1, "rpp": 25, "dateCreatedFrom": "2026-04-01T00:00:00Z", "dateCreatedTo": "2026-04-30T23:59:59Z", "sort": "dateCreated|desc", }, timeout=30,)resp.raise_for_status()page = resp.json()print(f"Returned {len(page['item'])} of {page['totalRecords']} invoices")using System.Net.Http.Json;
using var http = new HttpClient();http.DefaultRequestHeaders.Add("X-Integration-Public-Key", publicKey);http.DefaultRequestHeaders.Add("X-Integration-Private-Key", privateKey);http.DefaultRequestHeaders.Add("X-Clinic-Id", clinicId);
var body = JsonContent.Create(new { page = 1, rpp = 25, dateCreatedFrom = "2026-04-01T00:00:00Z", dateCreatedTo = "2026-04-30T23:59:59Z", sort = "dateCreated|desc",});var resp = await http.PostAsync( "https://open-api.shepherd.vet/pav2/open-api-invoices", body);resp.EnsureSuccessStatusCode();var json = await resp.Content.ReadAsStringAsync();Console.WriteLine(json);<?php$ch = curl_init('https://open-api.shepherd.vet/pav2/open-api-invoices');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'X-Integration-Public-Key: ' . getenv('SHEPHERD_PUBLIC_KEY'), 'X-Integration-Private-Key: ' . getenv('SHEPHERD_PRIVATE_KEY'), 'X-Clinic-Id: ' . getenv('SHEPHERD_CLINIC_ID'), ], CURLOPT_POSTFIELDS => json_encode([ 'page' => 1, 'rpp' => 25, 'dateCreatedFrom' => '2026-04-01T00:00:00Z', 'dateCreatedTo' => '2026-04-30T23:59:59Z', 'sort' => 'dateCreated|desc', ]),]);$response = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);curl_close($ch);echo "HTTP $status\n$response\n";const resp = await fetch('https://open-api.shepherd.vet/pav2/open-api-invoices', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Integration-Public-Key': process.env.SHEPHERD_PUBLIC_KEY, 'X-Integration-Private-Key': process.env.SHEPHERD_PRIVATE_KEY, 'X-Clinic-Id': process.env.SHEPHERD_CLINIC_ID, }, body: JSON.stringify({ page: 1, rpp: 25, dateCreatedFrom: '2026-04-01T00:00:00Z', dateCreatedTo: '2026-04-30T23:59:59Z', sort: 'dateCreated|desc', }),});if (!resp.ok) throw new Error(`Shepherd ${resp.status}: ${await resp.text()}`);const page = await resp.json();console.log(`Returned ${page.item.length} of ${page.totalRecords} invoices`);Response
Section titled “Response”{ "item": [ { "id": "8b1f2c3d-4e5f-6789-abcd-ef0123456789", "invoiceNumber": 10428, "clinicId": "9890662f-52db-4a41-a5c1-b2e300d400b4", "clientId": "e45a6e12-3a1c-4e7d-9fd2-3473a4d8a7a6", "statusId": "9f8e7d6c-5b4a-3210-a9f8-fedcba098765", "invoiceStatus": null, "invoiceItems": [], "subtotal": 124.50, "discount": 0.00, "tax": 9.96, "total": 134.46, "paid": 0.00, "balance": 134.46, "isPaid": false, "isReturn": false, "isTaxExempt": false, "dateIssued": "2026-04-28T15:42:11Z", "dateCheckedOut": null, "dateCreated": "2026-04-28T15:42:11Z", "dateUpdated": "2026-04-28T15:42:11Z", "isDeleted": false } ], "totalRecords": 1842, "page": 1, "recordsPerPage": 25, "sort": "dateCreated|desc", "searchQuery": null, "embed": null, "links": []}Writing invoices
Section titled “Writing invoices”The public API surface for invoices is read only. There is no create, update, or delete endpoint for invoices or for invoice items; billing is driven from within the Shepherd application, and integrations consume the resulting records.
If your integration needs to originate charges, the supported path is to record treatments against a SOAP plan, which the clinic then invoices in Shepherd. See Treatments. If that does not cover your use case, raise it with your Shepherd contact rather than looking for an undocumented write endpoint.
Invoice line items are read through their own collection endpoint, POST /pav2/open-api-invoice-items, using the same collection conventions as everything else.
See also
Section titled “See also”- Conventions for pagination, embedding, sorting, and date filters.
- Errors for the two JSON error body shapes.
- Authentication for the three required headers.
- Products for the catalog that invoice items reference.