Skip to content

Overview

The Shepherd API is a JSON REST API. Two environments are available: a sandbox for development and a production environment for live clinic data.

EnvironmentBase URL
Productionhttps://open-api.shepherd.vet/pav2/
Sandboxhttps://demo-open-api.shepherd.vet/pav2/

Both environments speak the same protocol; switch by changing the base URL. Sandbox credentials and production credentials are issued separately. If you don’t have sandbox keys yet, contact your Shepherd account manager.

All requests and responses use application/json. Always send Content-Type: application/json on the request, and send a JSON body even when you have no filters to apply (an empty object {} is fine).

Every endpoint except the five updates below, including reads, accepts POST with a JSON request body. There are no GET, PATCH, or DELETE verbs in the public surface. Filters, pagination, embedding, and sort options all travel in the request body.

For consistency, the API uses POST across the board so request shape is uniform regardless of the operation. If you are used to REST APIs that mix verbs, this trips up many developers on day one; the cure is to never reach for GET here. If a call returns 405 Method Not Allowed, you almost certainly used the wrong verb. Always use https: plain http is redirected, and most HTTP clients turn a redirected POST into a GET.

The one exception is updating an existing record. A handful of resources expose a PUT update endpoint alongside their POST create endpoint:

Update endpointResource
PUT /pav2/open-api-clients/{id}/updateClients
PUT /pav2/open-api-patients/{id}/updatePatients
PUT /pav2/open-api-appointments/{id}/updateAppointments
PUT /pav2/open-api-task-entries/update/{id}Tasks
PUT /pav2/open-api-task-notes/update/{id}Tasks

These are true PUT operations, which means they are full replacements: any editable field you leave out of the body is cleared, not left alone (a few fields per resource are the exception). Note that the task routes put update before the id. Read Updating records before you call one; sending a partial body is the single most common cause of accidental data loss against the Shepherd API.

Any HTTP client that can send a JSON body with custom headers will work. A few notes from clinics shipping in production:

  • Always set an explicit timeout. 30 seconds is a reasonable upper bound for most endpoints. If a request needs longer, make it cheaper (a shorter date window, a smaller page, fewer embeds) rather than raising the timeout.
  • Reuse a single client instance. Most languages benefit from keep-alive connection pooling; cold sockets dominate latency on chatty integrations. Accept gzip (Accept-Encoding: gzip); JSON responses compress well.
  • Read the response body on every status. Error bodies are not a single consistent envelope (a JSON string, a JSON object, plain text, or empty); see Errors for how to read them.
  • Retry selectively. After a 429, wait until the next UTC minute; retry 502 and 503 with capped exponential backoff and jitter. Do not retry timeouts, 4xx responses, or creates. See Rate limits.
  • Authentication for the header model and a working “hello world”.
  • Conventions for pagination, embedding, sorting, and date filtering.