Concepts
Patients and clients
How Vetnio stores animals (patients) and their owners (clients), how they connect to consultations, and what to know about search, linking, deletion and duplicates.
A patient is an animal and a client is the animal's owner (the Vetnio app calls clients "owners"). Both belong to one clinic (a workspace) and are shared by every member of it. Linking a patient to a consultation puts that visit in the patient's history, which is what vets see on the patient page and what VetsGPT reads as patient context.
How patients, clients and consultations relate
| Relationship | Rule |
|---|---|
| Client → patients | A client can own any number of patients. Every patient created through the API has exactly one owner, in clientId. |
| Patient → consultations | A patient can be linked to any number of consultations; together they are its history. |
| Consultation → patient | A consultation has at most one patient. The consultation list returns it as patientId. |
Patients and clients have no status or archive state: a record exists until someone deletes it, and deletion is permanent.
Identifiers
Every patient and client has an id, a UUID that Vetnio generates. You cannot choose it, and there is no field for your own system's ID, so keep a mapping from your IDs to Vetnio IDs on your side. Sync patients from a practice system shows how.
The patient's identifier is something else: the animal's microchip, tattoo or registration number. It is free text and not unique, so two patients can share one.
Fields and formats
Every field is optional free text. Vetnio stores values as given, without validation or normalization. The conventions below are what the Vetnio app writes; follow them so that the app's filters and screens behave the same for your data.
| Patient field | Format | Notes |
|---|---|---|
name | Text | The animal's name. |
species | Text | English species name, plus - <breed> when a breed is known: Cat - Maine Coon. |
breed | Text | Also stored separately, even when it is part of species. |
dateOfBirth | YYYY-MM-DD | Stored as a date. See the warning below. |
gender | Text | Sex and neuter status: Male, Female, Male Neutered or Female Neutered. |
weight | Text with unit | For example 5.8 kg. Not parsed or converted. |
identifier | Text | Microchip or other identification number. |
insurance | Text | Name of the insurance company. |
clientId | UUID | The owner. Set when the patient is created and cannot be changed. |
createdAt, updatedAt | ISO 8601 | updatedAt changes on every update, even one that changes nothing. |
A client has name, email, address, zipCode and phoneNumbers, a list of strings for which E.164 (+46701234567) is recommended. Clients have no timestamps.
Fields cannot be set to null. To blank a text field, send an empty string.
Creating a patient also creates its owner
POST/workspaces/{workspaceId}/patients creates the patient and, every time, a new client from the client object:
curl -X POST https://vetnio.com/api/v2/workspaces/demo-north-clinic/patients \
-H "Authorization: Bearer $VETNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Nala",
"species": "Cat - Maine Coon",
"breed": "Maine Coon",
"dateOfBirth": "2019-06-03",
"gender": "Female Neutered",
"weight": "5.8 kg",
"identifier": "752098100067890",
"insurance": "Agria",
"client": {
"name": "Sam Rivera",
"email": "sam.rivera@example.com",
"address": "8 Orchard Road, Riverside",
"zipCode": "114 51",
"phoneNumbers": ["+46701234567"]
}
}'{
"id": "1c9c1cf7-9796-477d-bac0-c5da7a51432a",
"name": "Nala",
"species": "Cat - Maine Coon",
"breed": "Maine Coon",
"dateOfBirth": "2019-06-03",
"gender": "Female Neutered",
"weight": "5.8 kg",
"identifier": "752098100067890",
"insurance": "Agria",
"clientId": "0128c93b-81ec-4f1a-86ee-734f7e8ede98",
"createdAt": "2026-10-04T16:12:17.522Z",
"updatedAt": "2026-10-04T16:12:17.522Z",
"client": {
"id": "0128c93b-81ec-4f1a-86ee-734f7e8ede98",
"name": "Sam Rivera",
"address": "8 Orchard Road, Riverside",
"zipCode": "114 51",
"phoneNumbers": ["+46701234567"],
"email": "sam.rivera@example.com"
}
}If you leave out client, Vetnio creates an empty placeholder owner: every field is null and phoneNumbers is []. You cannot pass an existing clientId, and you cannot move a patient to another owner afterwards. A client created on its own with POST/workspaces/{workspaceId}/clients therefore cannot be given patients through the API. In practice, create owners together with their patients.
Finding patients
GET/workspaces/{workspaceId}/patients returns one page of patients, each with the owner's name in clientName:
| Parameter | Behavior |
|---|---|
searchQuery | Case-insensitive substring of the patient name, the identifier or the owner's name. Species is not searched. |
speciesFilter | A species name in any language Vetnio supports (Cat, cat, Katze) matches every stored spelling, with or without a breed suffix. |
genderFilter, insuranceFilter | Whole value, ignoring case: Female does not match Female Neutered. |
hasWeightFilter | yes or no. |
sort | date_added (newest first, the default), last_visit (most recent consultation first) or name (A–Z). |
page, pageSize | 1-based page, 1 to 100 per page (default 20). Stop when you have read totalCount patients. |
Because searchQuery matches substrings, a search for a microchip number can also return patients whose identifier merely contains it. Compare identifier yourself before you treat a result as a match. Pagination covers paging in general.
GET/workspaces/{workspaceId}/clients returns every client in one unpaginated response, in no guaranteed order and including empty placeholder owners. There is no client search: to find an owner's patients, search patients by the owner's name and compare clientId.
Linking a patient to a consultation
POST/workspaces/{workspaceId}/consultations/{consultationId}/patient sets the consultation's patient:
curl -X POST https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations/62a25f84-3c4f-4402-b82a-d8f7e6fd9dee/patient \
-H "Authorization: Bearer $VETNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "patientId": "1c9c1cf7-9796-477d-bac0-c5da7a51432a" }'{
"success": true
}- Linking replaces any patient already linked. Repeating the call with the same patient is harmless.
- There is no unlink endpoint. To correct a mistake, link the right patient.
- Archived consultations are rejected with
403and the messageYou cannot modify this consultation. - Only the patient changes. The consultation's own
clientIdis not updated, so read the owner from the patient.
Deleting patients and clients
Both deletes are permanent and need the workspace admin or superadmin role (or organization admin access). Other members get 403, even for an unknown ID. A second delete of the same record returns 404.
| Request | Deleted | Kept |
|---|---|---|
DELETE/workspaces/{workspaceId}/patients/{patientId} | The patient and the files uploaded to its patient record | Its consultations, with recordings, transcripts and notes, now without a patient. The owner. |
DELETE/workspaces/{workspaceId}/clients/{clientId} | The client and every patient it owns | The consultations of those patients, without a patient |
Duplicates and retries
Nothing is unique and neither create endpoint is idempotent: sending the same POST twice creates two patients with two owners. Search before you create, and after a timeout, search again before you retry. Updates and links are safe to repeat.
Clinics that connect a practice-management system to Vetnio, such as Provet Cloud or Vettigo, also get patients created by that integration, and the next sync can overwrite your changes to those patients.
Access
Every member of the workspace can list, read, create and update patients and clients; there is no per-user ownership. Only admins can delete. These endpoints accept personal API keys only: organization and clinic API keys get 403 with This API key cannot access this endpoint. See Authentication.
Unknown or foreign patient and client IDs return 404 with the message Resource not found. An update of a client with an empty body currently fails with 500, so send at least one field.
Next steps
- Sync patients from a practice system: a find-or-create workflow with safe retries.
- Consultations: the visits patients are linked to.
- Use VetsGPT: ask questions with a patient attached as context.
- API reference: Patients and Clients.
Endpoints used in this guide
- GET
/workspaces/{workspaceId}/patientsList patients - POST
/workspaces/{workspaceId}/patientsCreate a patient - GET
/workspaces/{workspaceId}/patients/{patientId}Get patient details - PATCH
/workspaces/{workspaceId}/patients/{patientId}Update a patient - DELETE
/workspaces/{workspaceId}/patients/{patientId}Delete a patient - GET
/workspaces/{workspaceId}/clientsList clients (owners) - POST
/workspaces/{workspaceId}/clientsCreate a client (owner) - GET
/workspaces/{workspaceId}/clients/{clientId}Get client (owner) details - PATCH
/workspaces/{workspaceId}/clients/{clientId}Update a client (owner) - DELETE
/workspaces/{workspaceId}/clients/{clientId}Delete a client (owner) - POST
/workspaces/{workspaceId}/consultations/{consultationId}/patientLink a patient to a consultation
Last reviewed against the API on 2026-10-26.