---
title: "Search Link customers"
method: GET
path: "/workspaces/{workspaceId}/link/customers"
tags: ["link"]
---

# Search Link customers

`GET /workspaces/{workspaceId}/link/customers`

## Request

- Base URL: `https://vetnio.com/api/v2`
- URL: `https://vetnio.com/api/v2/workspaces/{workspaceId}/link/customers`
- Auth: HTTP bearer

Searches active (not removed) customers in the caller's Link tenant. Use exactly one search mode per request, otherwise the request fails with `400 BAD_REQUEST`:

- `name` — Link's own partial match on first or last name.
- `identifier` — exact match on the customer identifier (for example a Swedish personal identity number). Vetnio also tries the common spellings with and without century digits and hyphen, and merges the results.
- `firstName` and/or `lastName` — at least one with two or more characters. Vetnio queries Link with the longer term and keeps only customers whose first and last names contain the supplied values (case-insensitive).

Results are paginated with `page` (default 1) and `perPage` (1–100, default 100). `total` and `sourceTotal` count upstream Link rows, not filtered matches: the final field-aware match count is known only after all source pages are scanned, so keep requesting pages while `hasNextPage` is `true` to see every match.

## Path parameters

- `workspaceId` string, required: Identifier of the clinic (workspace), as returned by `GET /workspaces`. The key's user must be a member of the clinic, or an admin of the organization it belongs to.

## Query parameters

- `name` string: Legacy search: partial, case-insensitive match on the customer's first or last name, performed by Link. Use exactly one search mode: `name`, `identifier`, or `firstName`/`lastName`.
- `identifier` string: Exact customer identifier, typically a Swedish personal identity number. Vetnio also tries the common spellings (with or without century digits and hyphen) and merges the results.
- `firstName` string: Case-insensitive substring of the customer's first name. Combine with `lastName`; at least one of the two must have two or more characters.
- `lastName` string: Case-insensitive substring of the customer's last name.
- `page` integer: 1-based page of Link results.
- `perPage` integer: Results per page, from 1 to 100.

## Response `200`

Paginated customer search results.

- object: One page of Link customer search results.
  - `customers` object[], required: Matching customers from this page of Link results. In `firstName`/`lastName` mode the page is filtered after it is fetched, so it can hold fewer than `perPage` rows (or none) while `hasNextPage` is still `true`.
    - `id` integer, required: Link customer id. Pass it as `customerId` to the animal and export endpoints.
    - `name` string, nullable, required: Full display name from Link, or `null`.
    - `firstName` string, nullable, required: First name from Link, or `null` (for example for companies).
    - `lastName` string, nullable, required: Last name from Link, or `null`.
    - `identifier` string, nullable, required: Customer identifier in Link, typically a Swedish personal identity number or organisation number. `null` when not recorded.
    - `primaryEmail` string, nullable, required: The customer's email address marked primary in Link, or `null`.
    - `primaryPhone` string, nullable, required: The customer's phone number marked primary in Link, or `null`.
  - `total` integer, required: Same value as `sourceTotal`, kept for older clients. It is not the number of matches after Vetnio's own filtering.
  - `sourceTotal` integer, required: Number of customers Link reported for the upstream query. In `identifier` mode it is the sum over all identifier spellings searched.
  - `page` integer, required: The page that was returned (1-based).
  - `perPage` integer, required: Page size used for the upstream Link query.
  - `scannedCount` integer, required: How many upstream Link rows have been covered up to and including this page.
  - `hasNextPage` boolean, required: `true` when Link has more rows for this query. Request `page + 1` to continue; a filtered page can be empty while this is `true`.

## Other responses

- `400`: Invalid input data
- `401`: Authorization not provided
- `403`: Insufficient access
- `404`: Not found
- `500`: Internal server error

---

[API](https://skmtc.dev/vetnio/apis/vetnio-api.md) - [All operations](https://skmtc.dev/vetnio/apis/vetnio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/vetnio/apis/vetnio-api/revisions/d004afd5617d?raw)
