Get started
Authentication
The three kinds of API key, how to send and check them, what each can reach, and how to rotate, revoke and protect them.
Every request to the Vetnio API carries an API key in the Authorization header. Which key you use decides what the request can do: a personal key acts as you, with everything your account can do, while organization and clinic keys are read-only keys made for reporting. This guide explains the key types, how to check a key, how to replace one without downtime and how to keep keys safe.
Key types
| Personal key | Organization key | Clinic key | |
|---|---|---|---|
| Starts with | sk_live_ | sk_org_ | sk_ws_ |
| Created by | Any user, for themselves | An organization admin | An organization admin |
| Created in | Settings → API Keys | Organization → API | Organization → API, access set to one clinic |
| Acts as | The user who created it, with their role in every clinic and organization | An admin of one organization | An admin of one clinic (Vetnio calls a clinic a workspace) |
| Reads and writes | Both | Read only | Read only |
| Endpoints | Every endpoint in the reference except GET /api-key | GET /api-key, GET /organizations/{organizationId}, GET /organizations/{organizationId}/data-export/usage, GET /openapi.json | Same four |
| Rate limits | None per key | 60 requests per minute, 10,000 per day | Same |
| Lifetime | Until you delete it | Until revoked, or until an expiry date chosen at creation | Same |
| How many | Up to 20 per user | Up to 10 active per organization, organization and clinic keys together | Shared with organization keys |
Each operation in the API reference lists the key types it accepts under Accepts, taken from the x-vetnio-api-key-types field of the OpenAPI document. An organization or clinic key on any other endpoint gets 403:
{
"message": "This API key cannot access this endpoint",
"code": "FORBIDDEN",
"data": {
"code": "FORBIDDEN",
"httpStatus": 403,
"path": "workspaces.listWorkspacesV1",
"zodError": null
}
}Use a personal key for integrations that create or change data, such as a practice system that creates consultations. Use an organization or clinic key for reporting, such as a BI tool that reads usage statistics; Export usage statistics walks through that setup.
Send the key
Put the key in the Authorization header as a Bearer token, separated by exactly one space. A header with only the key, without Bearer , is treated as no key at all.
curl https://vetnio.com/api/v2/user/me \
-H "Authorization: Bearer $VETNIO_API_KEY"The API is built for server-to-server calls. Responses carry no CORS headers, so a browser cannot call the API with a key, and you should never try: anyone who opens the page could read the key.
If a request carries both a Vetnio sign-in session cookie and an Authorization header, for example from a signed-in browser, the session is used and the header is ignored.
Check a key
Make one cheap request before you rely on a new key.
Personal keys: GET/user/me returns the ID of the user the key belongs to.
curl https://vetnio.com/api/v2/user/me \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"id": "c1b0f2a0-f819-5fcc-a2ed-85db0cef66a7"
}Then call GET/workspaces to see the clinics the key can reach and your role in each.
Organization and clinic keys: GET/api-key describes the key itself: its organization, scope, status, limits and request counts. A personal key gets 400 here.
curl https://vetnio.com/api/v2/api-key \
-H "Authorization: Bearer $VETNIO_ORG_KEY"{
"name": "Data warehouse sync",
"organizationId": "83222a0a-688b-413e-9761-146f7a173b58",
"scope": {
"type": "organization",
"id": "83222a0a-688b-413e-9761-146f7a173b58"
},
"status": "active",
"createdAt": "2026-10-04T16:27:25.619Z",
"expiresAt": null,
"lastUsedAt": "2026-10-04T16:27:32.247Z",
"limits": {
"requestsPerMinute": 60,
"requestsPerDay": 10000
},
"usage": {
"requestsToday": 1,
"requestsLast30Days": 1,
"daily": [
{ "day": "2026-10-04", "requests": 1 }
]
}
}A missing, mistyped, deleted, revoked or expired key always gets the same 401. The API does not say which of these it was, so check the key in Vetnio:
{
"message": "This action requires an authenticated user",
"code": "UNAUTHORIZED",
"data": {
"code": "UNAUTHORIZED",
"httpStatus": 401,
"path": "user.meV1",
"zodError": null
}
}Permissions of a personal key
A personal key has exactly the permissions of its user, in every clinic they belong to. Clinic roles are member, admin and superadmin. Some endpoints need more than membership, for example the configuration export needs an admin. Organization admins can also work as an admin in every clinic of their organization, even where they are not a member. VetsGPT is the exception: whatever the role, it needs a membership of the clinic with VetsGPT enabled for the user (see Use VetsGPT).
When the role is not enough, the API returns 403 with a message that says why, such as You do not have access to this workspace or You are not an admin of this workspace. See Errors for the full list.
Manage personal keys
- Open Settings and select the API Keys tab.
- Choose Create API Key, enter a name that says where the key is used, and create it. Vetnio may ask you to confirm with your passkey.
- Copy the key immediately. It is shown only once; Vetnio stores only a hash of it.
The tab lists your keys by name. You can hold up to 20. Personal keys do not expire. To revoke one, delete it in the same tab; requests with it fail with 401 from the next request on. To replace a personal key without downtime, create the new key first, deploy it, then delete the old one.
Manage organization and clinic keys
Organization admins manage these keys under Organization → API.
- Choose Create API key.
- Enter a Name (up to 80 characters), choose Access (Whole organization or one clinic) and Expires (never, 30, 90 or 365 days).
- Copy the key from the dialog. It is shown only once.
The table on the same tab shows each key's access, who created it, Last used, Requests today, Requests 30 days and status (Active, Expiring, Expired or Revoked). Last used is refreshed at most once every five minutes, so it can lag behind the latest request.
A key belongs to the admin who created it and can never do more than that admin. If the admin loses their admin role in the organization (or, for a clinic key, in that clinic), the key stops working with 401. It works again if the role is restored.
Rotate a key without downtime
Choose Replace key in the key's menu. Vetnio creates a new key with the same name, access and expiry date, and the old key keeps working for up to 24 hours (never past its own expiry). The new key belongs to the admin who replaced it. Replacing needs a free slot, because both keys count toward the limit of 10 while the old one is still valid.
During the grace period, GET/api-key shows the old key as expiring with the new cut-off time:
{
"name": "Data warehouse sync",
"status": "expiring",
"createdAt": "2026-10-04T16:27:25.619Z",
"expiresAt": "2026-10-05T16:30:19.549Z"
}Deploy the new key, confirm it with GET /api-key, and either let the old key expire or revoke it.
Revoke a key
Choose Revoke in the key's menu. Revocation takes effect on the next request, which gets 401, and cannot be undone. Keys are checked on every request; there is no cache to wait for.
Mobile app keys
The Vetnio mobile app signs in with a device key that the app gets by scanning a QR code: choose Mobile App in the sidebar or on Settings → API Keys, then scan. Device keys start with sk_live_, act as the user like a personal key, and do not count toward the 20-key limit. The same dialog lists connected devices and revokes them one by one.
POST/user/register-mobile-device is the call the app makes right after pairing to label itself with a device name and platform. It marks the key that made the request as a device key, which moves it out of Settings → API Keys into the device list. Do not call it with a key your server integration uses.
IP allowlists
Vetnio can restrict a clinic or an organization to a list of IP addresses or ranges; contact Vetnio support to set one up. The allowlist applies to every request, whatever the key type. From an address outside the list, the clinic disappears from GET /workspaces and its endpoints return 403 with the message ipAccessDenied. If your integration runs in the cloud, give Vetnio the fixed outbound addresses of your servers.
Security practices
- Keep keys in a secret manager or environment variables, never in source code, browser code, mobile app bundles, tickets or chat.
- Create one key per integration and environment, named after where it is used, so you can revoke one without affecting the others.
- For reporting, use an organization or clinic key instead of a personal key: it is read-only and limited to four endpoints.
- Choose an expiry for organization and clinic keys, and rotate them before it passes.
- If a key leaks, delete or revoke it first, then create a replacement.
- Vetnio never asks for your key. When you contact support, quote the
x-vercel-idresponse header and the time of the request instead.
Next steps
- Errors: the error format and what each status code means.
- Rate limits and other limits: what happens when a key exceeds its quota.
- Export usage statistics: set up an organization key for a BI tool.
- The Users and Organizations and usage reference pages.
Endpoints used in this guide
- GET
/user/meGet the authenticated user - GET
/api-keyCheck the API key you are using - GET
/workspacesList workspaces - GET
/organizations/{organizationId}Get an organization with its clinics, people and templates - GET
/organizations/{organizationId}/data-export/usageExport usage statistics - GET
/openapi.jsonGet the OpenAPI document - POST
/user/register-mobile-deviceRegister the calling device
Last reviewed against the API on 2026-10-26.