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, 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.

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

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. 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; long embed chains on busy clinics can run longer, so size to the workload.
  • Reuse a single client instance. Most languages benefit from keep-alive connection pooling; cold sockets dominate latency on chatty integrations.
  • Read the response body on every status. Error bodies are JSON, but they are not a single consistent envelope; see Errors for the two shapes you will encounter.
  • Implement retries with backoff and jitter. Rate-limit responses (HTTP 429) and transient 5xx errors should be retried; see Rate limits.
  • Authentication for the header model and a working “hello world”.
  • Conventions for pagination, embedding, sorting, and date filtering.