Skip to content

Clients

A client represents a pet owner: the human responsible for one or more patients (pets) at a clinic. Clients carry the billing relationship, the contact details, and the household-level preferences. Every patient in the Shepherd API is linked to at least one client, and most clinical and financial workflows start from a client lookup.

Clients have several related sub-resources (phones, notes, info, discount) that are managed through their own endpoints rather than as deep writes on the client object itself.

Authoritative schemas live in the live Swagger UI. The fields below are a representative subset for orientation.

FieldTypeDescription
idstringUnique identifier for the client.
identifierstringShort human-facing identifier shown in the Shepherd UI.
firstName / middleName / lastNamestringName parts.
emailstringPrimary email address.
dateOfBirthstringClient’s date of birth.
clientPhonesarrayPhone numbers. Populated with embed=clientPhones.
clientInfoobjectThe contact block, including the postal address. Populated with embed=clientInfo; there are no address fields on the client itself.
clientCoOwnerobjectCo-owner, with their own phone list. Populated with embed=clientCoOwner.
clientStatusId / clientTypeId / genderIdstringLookup references.
clientDiscountIdstringDiscount program applied to this client.
authorizedAgentsarrayPeople authorised to act for the client.
isTaxExemptbooleanWhether the client is exempt from taxes.
clinicIdstringThe owning clinic.
legacyIdstringIdentifier carried over from a previous practice-management system.
dateCreatedstringISO 8601 UTC timestamp of creation.
dateUpdatedstringISO 8601 UTC timestamp of last update.
deletedbooleanSoft-delete flag; filter on this in queries.
POST /pav2/open-api-clients

Returns a paginated collection of clients for the clinic identified by X-Clinic-Id. Accepts the standard collection parameters: page, rpp, sort, searchQuery, embed, and the dateCreatedFrom / dateCreatedTo date-range pair. See Conventions for the full parameter rules.

Terminal window
curl -X POST https://open-api.shepherd.vet/pav2/open-api-clients \
-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,
"sort": "lastName|asc",
"searchQuery": "smith",
"embed": "clientPhones"
}'
{
"item": [
{
"id": "c_01HXYZ...",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"clientPhones": [
{
"id": "7d7ea1ee-3329-4b06-9966-b2f800c16f53",
"countryId": "158d44c8-d163-4c27-8e77-b2b300f2522f",
"phoneNumber": "5555550123",
"phoneTypeId": "534494bb-d287-eb09-e90b-8a2b4e5b9398",
"isPrimary": true
}
],
"dateCreated": "2026-03-14T18:22:11Z",
"dateUpdated": "2026-05-01T09:14:00Z",
"deleted": false
}
],
"totalRecords": 184,
"page": 1,
"recordsPerPage": 25,
"sort": "lastName|asc",
"searchQuery": "smith",
"embed": "clientPhones",
"links": []
}
POST /pav2/open-api-clients/write

Creates a new client record for the clinic.

Required: firstName, lastName, and clientPhones. The phone array is required by the model, so send it even if the client has no number on file; pass [] in that case.

Each entry in clientPhones requires countryId, phoneNumber, and phoneTypeId, all resolved from Lookups (open-api-countries and open-api-phone-types). isPrimary and phoneNumberName are optional.

A co-owner, the contact block, and authorized agents can be created in the same call via the clientCoOwner, clientInfo, and authorizedAgents objects. Notes and discounts are separate sub-resources.

Terminal window
curl -X POST https://open-api.shepherd.vet/pav2/open-api-clients/write \
-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 '{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"clientPhones": [
{
"countryId": "158d44c8-d163-4c27-8e77-b2b300f2522f",
"phoneNumber": "5555550123",
"phoneTypeId": "534494bb-d287-eb09-e90b-8a2b4e5b9398",
"isPrimary": true
}
]
}'
PUT /pav2/open-api-clients/{id}/update

Updates an existing client. This is a PUT, so it is a full replacement: send the complete client representation, not just the fields you changed. Any editable field omitted from the body is cleared. See Updating records for the general rule.

Required on every update: firstName, lastName, and clientPhones. Omitting any of them is rejected.

clientStatusId and the clientInfo contact block are preserved when omitted. The home clinic, system identifiers, and deleted status cannot be changed here. authorizedAgents is an edit list rather than a replacement: each entry adds an agent (omit id), edits one in place (include id), or removes one (set authorizedAgentIdForRemove with a removalNote); agents you do not reference are left alone.

Preserving co-owners and their phone numbers

Section titled “Preserving co-owners and their phone numbers”

The most common data-loss report against this endpoint involves co-owners. clientCoOwner is a nested object that carries its own clientCoOwnerPhones array, so a body that includes the co-owner but not their phones removes those phone numbers.

Fetch the full co-owner record before you merge. There are two ways to get it:

Embed it in the client read. Ask for the co-owner and their phones by name, using the dot notation described in Embedding related entities:

{ "ids": "c_01HXYZ...", "embed": "clientCoOwner,clientCoOwner.clientCoOwnerPhones" }

Or query the co-owner endpoint directly. POST /pav2/open-api-client-co-owners returns co-owner records with their phone information attached. Co-owners are keyed by the owning client’s ID, so passing that ID in ids returns the co-owner for that client:

{ "ids": "c_01HXYZ...", "embed": "client" }

Either way you end up with the complete co-owner object to resubmit.

Terminal window
# 1. Read the current client, embedding the nested collections you will resend.
curl -X POST https://open-api.shepherd.vet/pav2/open-api-clients \
-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 '{
"ids": "c_01HXYZ...",
"embed": "clientPhones,clientCoOwner,clientCoOwner.clientCoOwnerPhones"
}'
# 2. Merge your change into that full representation, then
# 3. PUT the complete object back.
curl -X PUT https://open-api.shepherd.vet/pav2/open-api-clients/c_01HXYZ.../update \
-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 @merged-client.json

Client-adjacent data lives on its own endpoints. Each follows the same list / write conventions as the parent resource.

EndpointPurpose
/pav2/open-api-client-phonesPhone numbers attached to a client (mobile, home, work).
/pav2/open-api-client-infosExtended profile fields and household metadata.
/pav2/open-api-client-notesFree-form notes recorded by clinic staff against the client.
/pav2/open-api-client-discountsDiscount programs and percentage adjustments applied to the client’s invoices.
/pav2/open-api-client-co-ownersCo-owners attached to a client, with their phone numbers. Keyed by the owning client’s ID.
  • Conventions: pagination, embed, sort, and date-range rules.
  • Authentication: the three required headers.
  • Errors: HTTP status codes and the two JSON error shapes.
  • Patients: the pets attached to each client.