Get started
Pagination
The pagination styles Vetnio list endpoints use, their defaults and maximums, how to iterate safely, and how to filter by text and date.
Vetnio's list endpoints grew with the product, so they do not all paginate the same way. Some take a page number, one family takes a cursor, and many return everything in one response. This guide lists each style, the endpoints that use it, their defaults and maximums, and how to read every item exactly once.
At a glance
| Style | Request parameters | Response fields | Endpoints |
|---|---|---|---|
| Page number | page (from 1), pageSize | totalCount (patients), count or totalRows with totalPages (exports) | Patients, clinical data export list, usage export |
| Legacy page number | currentPage (from 1), consultationsPerPage | count, itemsPerPage, totalPages | Consultation list |
| Cursor | cursor, limit | nextCursor | Configuration export inventories and template versions |
| Practice-system pages | page (from 1), perPage | hasNextPage | Link customer and animal search |
| None | The whole list | Everything else that returns a list |
Parameters go in the query string. Defaults and maximums per endpoint:
| Endpoint | Size parameter: default, maximum | Order |
|---|---|---|
GET/workspaces/{workspaceId}/patients | pageSize: 20, 100 | sort: date_added (newest first, the default), last_visit or name |
GET/workspaces/{workspaceId}/data-export/consultations | pageSize: 10, 50 | Newest first |
GET/organizations/{organizationId}/data-export/usage | pageSize: 1,000, 5,000; only with grain=consultation | Oldest first |
GET/workspaces/{workspaceId}/consultations | consultationsPerPage: 10, no maximum | Newest first |
Configuration export inventories, such as GET/workspaces/{workspaceId}/data-export/templates | limit: 20, 50 | Ascending template ID |
Template version lists, such as GET/workspaces/{workspaceId}/data-export/templates/versions | Fixed at 50 | Newest first |
GET/workspaces/{workspaceId}/link/customers, GET/workspaces/{workspaceId}/link/customers/{customerId}/animals/page | perPage: 100, 100 | As returned by Link |
A value outside the allowed range returns 400 with the problem in issues; see Errors.
Page number
Ask for page=1, then page=2 and so on. The patient list returns the matching total in totalCount; a page past the end is an empty list, not an error.
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/patients?page=1&pageSize=2&sort=name" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"patients": [
{
"id": "4abb3048-6693-41d0-bf7d-7d6b09556c09",
"name": "Bella",
"species": "Dog - Labrador Retriever",
"clientName": "Alex Morgan (docs example)",
"createdAt": "2026-10-04T16:17:01.870Z",
"…": "…"
},
{
"id": "e8d11510-1181-42a2-9f68-7fdf015fb7f4",
"name": "Bella",
"species": "Dog",
"clientName": "Alex Morgan",
"createdAt": "2026-10-04T16:07:19.313Z",
"…": "…"
}
],
"totalCount": 6
}Stop when a page has fewer items than pageSize, or when page × pageSize reaches totalCount.
The clinical data export list (GET/workspaces/{workspaceId}/data-export/consultations) works the same way but reports count, page, pageSize and totalPages. Stop when page equals totalPages. Each item carries download links that expire after one hour (expiresAt), so download a page's files before you request the next pages, or request the page again for fresh links.
The usage export only paginates with grain=consultation; the other grains always return one page with page and totalPages set to 1. It refuses pages that start past row 50,000, so split long date ranges into shorter requests. Export usage statistics shows the loop.
Consultation list
GET/workspaces/{workspaceId}/consultations is an older endpoint with its own parameter names. It lists only consultations that the key's user created, newest first, without deleted ones.
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations?currentPage=1&consultationsPerPage=2" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"consultations": [
{
"id": "4b2730b1-3e78-4d82-9114-030a055e8581",
"name": "Bella - lameness left hind",
"createdAt": "2026-10-04T16:15:36.818Z",
"externalId": "pims-appt-58213",
"…": "…"
},
{
"id": "71476b24-7171-496a-bf4d-23ad157a0e09",
"name": "Bella - vaccination",
"createdAt": "2026-10-04T16:02:21.208Z",
"externalId": "pims-visit-10482",
"…": "…"
}
],
"count": 6,
"itemsPerPage": 2,
"totalPages": 3
}Two things differ from the other page-number endpoints:
- Consultations that are linked into one timeline count as a single item. A page can therefore hold more consultations than
consultationsPerPage, andcountcounts timelines, not consultations. currentPagemust be 1 or higher. Lower values currently fail with500instead of400.
consultationsPerPage has no maximum, but each consultation on the page costs extra lookups, so keep pages at 50 or fewer. To read every consultation in a clinic, not just your own, use the clinical data export list instead; it needs a clinic admin.
Cursor
The configuration export endpoints use cursors. Request the first page without cursor; if nextCursor is not null, pass it back as cursor with the same other parameters.
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/data-export/templates?limit=2" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"nextCursor": "65f1cc73-507d-4804-aeeb-b5b334861f00",
"expiresInSeconds": 3600,
"expiresAt": "2026-10-04T17:25:40.489Z",
"items": [
{ "id": "3ae1a5c2-04b7-43cb-9c1f-d3bcb4a4596a", "name": "Vaccination visit", "…": "…" },
{ "id": "65f1cc73-507d-4804-aeeb-b5b334861f00", "name": "Vaccination visit", "…": "…" }
]
}curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/data-export/templates?limit=2&cursor=65f1cc73-507d-4804-aeeb-b5b334861f00" \
-H "Authorization: Bearer $VETNIO_API_KEY"Inventory cursors are template IDs and pages are ordered by ID, so a template created while you page appears in a later page or not at all, but never twice.
Template version lists use an opaque cursor with a fixed page size of 50. A page can hold fewer than 50 versions, even none, while nextCursor is still set; keep going until nextCursor is null. Cursors and version IDs can contain +, / and =, so URL-encode them.
Practice-system pages
The Link search endpoints page through results from the Link practice system. Use page and perPage, and request page + 1 while hasNextPage is true. When you search by first or last name, Vetnio filters each page after Link returns it, so a page can be empty while hasNextPage is still true. Do not stop at the first empty page. Practice systems covers these endpoints.
Lists without pagination
These endpoints return the complete list in one response:
| Endpoint | Returns |
|---|---|
GET/workspaces | Clinics the user is a direct member of |
GET/workspaces/{workspaceId}/clients | Every client (animal owner) in the clinic, in no guaranteed order |
GET/workspaces/{workspaceId}/templates and GET /workspaces/{workspaceId}/json-templates | The clinic's templates and structured templates |
GET/workspaces/{workspaceId}/consultations/{consultationId}/records/versions | Every retained version of one record, newest first |
| Uploaded files, partial transcripts, VetsGPT chats, messages and attachments | Everything for the consultation or chat |
GET /organizations/{organizationId} | The organization's clinics, people and templates |
| Vettigo client search | Up to the first 50 matches |
For these, sort and filter on your side if you need a stable order.
Filtering and date windows
| Endpoint | Filters |
|---|---|
| Patients | searchQuery matches patient name, patient identifier or client name (case-insensitive, partial). speciesFilter, genderFilter, insuranceFilter and hasWeightFilter narrow further. |
| Consultation list | searchQuery matches the consultation name, externalId, the linked patient's name or identifier, and the text of the clinical note. |
| Clinical data export list | searchQuery as above, plus createdAtFrom (inclusive) and createdAtBefore (exclusive), both ISO-8601 timestamps such as 2026-09-01T00:00:00Z. |
| Usage export | days (a rolling window ending now), or startDate and endDate (YYYY-MM-DD, UTC, inclusive). endDate is ignored without startDate. At most 366 days per request. |
| VetsGPT chats | searchQuery |
Iterating safely
Page-number pagination reads a moving list. If consultations or patients are created or deleted while you page, items shift between pages, and you can see one twice or miss one. To get a consistent export:
- Fix the window. On the clinical data export list, set
createdAtBeforeto the time you start, so new consultations do not shift the pages. Pick up later ones in your next run withcreatedAtFrom. - Deduplicate by ID when you store results, and treat each run as an upsert.
- Page sequentially. Fetch page 2 after page 1 has been stored. Parallel page requests multiply the chance of a shifted list and, for organization and clinic keys, use up the per-minute rate limit faster.
- Re-read recent days. Usage figures for recent days can still change, so overlap each run with the previous one.
A small helper for page-number endpoints, here for the clinical data export list:
const BASE = "https://vetnio.com/api/v2";
const headers = { Authorization: `Bearer ${process.env.VETNIO_API_KEY}` };
async function* exportConsultations(workspaceId, createdAtBefore) {
for (let page = 1; ; page++) {
const params = new URLSearchParams({ page: String(page), pageSize: "50", createdAtBefore });
const res = await fetch(`${BASE}/workspaces/${workspaceId}/data-export/consultations?${params}`, { headers });
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).message}`);
const body = await res.json();
yield* body.consultations;
if (page >= body.totalPages) return;
}
}
const startedAt = new Date().toISOString();
for await (const consultation of exportConsultations("demo-north-clinic", startedAt)) {
console.log(consultation.id, consultation.name);
}Next steps
- Export clinical data: the clinical data export list in a full workflow.
- Export configuration: cursor pagination end to end.
- Limits: rate limits that apply while you page with an organization or clinic key.
Endpoints used in this guide
- GET
/workspaces/{workspaceId}/patientsList patients - GET
/workspaces/{workspaceId}/data-export/consultationsList consultations with export URLs - GET
/organizations/{organizationId}/data-export/usageExport usage statistics - GET
/workspaces/{workspaceId}/consultationsGet a page of consultations - GET
/workspaces/{workspaceId}/data-export/templatesExport a workspace's note templates - GET
/workspaces/{workspaceId}/data-export/templates/versionsList retained versions of a workspace note template - GET
/workspaces/{workspaceId}/link/customersSearch Link customers - GET
/workspaces/{workspaceId}/link/customers/{customerId}/animals/pageList a page of animals for a Link customer - GET
/workspacesList workspaces - GET
/workspaces/{workspaceId}/clientsList clients (owners) - GET
/workspaces/{workspaceId}/templatesList templates - GET
/workspaces/{workspaceId}/consultations/{consultationId}/records/versionsList retained record versions
Last reviewed against the API on 2026-10-26.