Skip to content

Tasks

Tasks (called task entries in the data model) are the to-do items clinic staff use to track follow-ups: “call the owner about lab results”, “verify the controlled-substance log”, “prep for tomorrow’s surgery”. A task has a due date, a priority, an assignee (a user or a team), and an optional client and patient context. Integrations create tasks when their workflow needs a human handoff inside Shepherd.

Tasks are clinic-scoped even in a multi-site group: they’re created at one clinic and stay there. In a group with sharing enabled, they can be read and updated from any clinic in the group.

Authoritative schemas live in the live Swagger UI. The fields below are a representative subset for orientation.

FieldTypeNotes
idUUIDServer-assigned identifier.
clinicIdUUIDClinic the task was created at.
namestringShort title shown in the UI list.
descriptionstringRich-text body (HTML).
dateDueISO 8601When the task is due (UTC). Required on create.
taskEntryPriorityStatusIdUUIDPriority (low / normal / high / urgent). See Lookups.
taskEntryStatusIdUUIDStatus (pending / in progress / completed). See Lookups.
clientIdUUIDClient context, optional.
patientIdUUIDPatient context, optional. Must belong to clientId if both are set.
taskAssignedToUsersarrayUsers the task is assigned to. Mutually exclusive with team assignment.
taskAssignedToTeamsarrayTeams the task is assigned to. Mutually exclusive with user assignment.
taskNotesarrayFree-text notes attached to the task (see notes endpoint below).
completedByUserIdUUIDUser who marked the task complete, if any.
isDeletedbooleanSoft-delete flag.
dateCreatedISO 8601Server-assigned creation timestamp (UTC).
dateUpdatedISO 8601Last server-side mutation (UTC).
POST /pav2/open-api-task-entries

Returns tasks at the clinic identified by X-Clinic-Id. Common filters: searchQuery (matches name, description, attached client and patient names), assignedToUserIds, taskEntryStatusIds, taskEntryPriorityStatusIds, clientIds, patientIds, and dueDateFrom / dueDateTo. In a group with sharing enabled, clinicIds widens to other clinics.

Use embed=taskEntryPriorityStatus,taskEntryStatus to inline the lookup objects on each task, saving a follow-up round trip.

Bound every list: a due-date or dateUpdated window of one calendar month or less, or an id filter such as assignedToUserIds or clientIds. Deleted tasks are included unless you send "isDeleted": false. The example below lists tasks due in the coming week.

Terminal window
curl -X POST https://open-api.shepherd.vet/pav2/open-api-task-entries \
-H "Content-Type: application/json" \
-H "X-Integration-Public-Key: $SHEPHERD_PUBLIC_KEY" \
-H "X-Integration-Private-Key: $SHEPHERD_PRIVATE_KEY" \
-H "X-Clinic-Id: $SHEPHERD_CLINIC_ID" \
-d '{"page":1,"rpp":50,"sort":"dateDue|asc","embed":"taskEntryPriorityStatus,taskEntryStatus","isDeleted":false,"dueDateFrom":"2026-05-28T00:00:00Z","dueDateTo":"2026-06-04T00:00:00Z"}'
{
"item": [
{
"id": "e8a1d2c3-...",
"clinicId": "f2a4c6e8-...",
"name": "Call owner about lab results",
"description": "<p>Follow up on the CBC from yesterday's visit.</p>",
"dateDue": "2026-05-29T17:00:00Z",
"clientId": "a1b2c3d4-...",
"patientId": "8c7d6e5f-...",
"taskEntryPriorityStatusId": "9c8d7e6f-...",
"taskEntryStatusId": "f6e5d4c3-...",
"taskAssignedToUsers": [
{ "user": { "firstName": "Alex", "lastName": "Rivera" } }
],
"taskAssignedToTeams": [],
"taskNotes": [],
"completedByUserId": null,
"isDeleted": false,
"dateCreated": "2026-05-28T13:21:09Z",
"dateUpdated": "2026-05-28T13:21:09Z"
}
],
"totalRecords": 1,
"page": 1,
"recordsPerPage": 50,
"sort": "dateDue|asc",
"searchQuery": null,
"embed": "taskEntryPriorityStatus,taskEntryStatus",
"links": []
}
POST /pav2/open-api-task-entries/write

Creates a new task. name, dateDue, and taskEntryPriorityStatusId are required. A task may be assigned to either users or teams, not both: send assignedToUsersIds or assignedToTeamsIds, not the two together. If you set patientId, you must also set clientId, and the patient must belong to that client.

Terminal window
curl -X POST https://open-api.shepherd.vet/pav2/open-api-task-entries/write \
-H "Content-Type: application/json" \
-H "X-Integration-Public-Key: $SHEPHERD_PUBLIC_KEY" \
-H "X-Integration-Private-Key: $SHEPHERD_PRIVATE_KEY" \
-H "X-Clinic-Id: $SHEPHERD_CLINIC_ID" \
-d '{
"name": "Call owner about lab results",
"description": "<p>Follow up on the CBC from yesterday's visit.</p>",
"dateDue": "2026-05-29T17:00:00Z",
"taskEntryPriorityStatusId": "<PRIORITY_GUID>",
"clientId": "<CLIENT_GUID>",
"patientId": "<PATIENT_GUID>",
"assignedToUsersIds": ["<USER_GUID>"]
}'

The server returns the created task as the response body, with id populated. Creates are not idempotent: a retried create makes a second task, so never retry one automatically after a timeout or a 5xx.

PUT /pav2/open-api-task-entries/update/{id}

This is not a partial update, even though a few fields survive omission. What happens to each field you leave out of the body:

Kept when omittedCleared when omitted
taskEntryPriorityStatusId, taskEntryStatusId, dateDuename, description, clientId, patientId, assignedToUsersIds, assignedToTeamsIds

So a body that only changes the status wipes the task’s title, description, client and patient context, and assignees. To change one thing, read the task first, embedding its assignments, and resend everything:

  1. Read it: POST /pav2/open-api-task-entries with {"ids": "<TASK_GUID>", "rpp": 1, "embed": "taskAssignedToUsers,taskAssignedToTeams"}.
  2. Build the update body from that record: name, description, clientId, patientId, dateDue, taskEntryPriorityStatusId, taskEntryStatusId, plus assignedToUsersIds from taskAssignedToUsers[].user.id or assignedToTeamsIds from taskAssignedToTeams[].team.id.
  3. Apply your change and send the whole body.

To mark a task complete, set taskEntryStatusId to the completed status from the status lookup. The same assignment rule applies on update: users or teams, not both. Note the route puts update before the id.

Terminal window
curl -X PUT https://open-api.shepherd.vet/pav2/open-api-task-entries/update/<TASK_GUID> \
-H "Content-Type: application/json" \
-H "X-Integration-Public-Key: $SHEPHERD_PUBLIC_KEY" \
-H "X-Integration-Private-Key: $SHEPHERD_PRIVATE_KEY" \
-H "X-Clinic-Id: $SHEPHERD_CLINIC_ID" \
-d '{
"name": "Call owner about lab results",
"description": "<p>Follow up on the CBC from yesterday's visit.</p>",
"dateDue": "2026-05-29T17:00:00Z",
"taskEntryPriorityStatusId": "<PRIORITY_GUID>",
"taskEntryStatusId": "<COMPLETED_STATUS_GUID>",
"clientId": "<CLIENT_GUID>",
"patientId": "<PATIENT_GUID>",
"assignedToUsersIds": ["<USER_GUID>"]
}'

Returns 200 OK with an empty body. There is no concurrency check: if someone edits the task between your read and your write, your write wins.

POST /pav2/open-api-task-notes
POST /pav2/open-api-task-notes/write
PUT /pav2/open-api-task-notes/update/{id}

Task notes are free-text comments attached to a task. List them by the standard search-filter pattern, create with /write, update with /update/{id}. The note carries a taskEntryId linking back to its parent. On update, only note can change; send it in full. The note update returns 204 No Content.

POST /pav2/open-api-task-entry-priority-statuses

Returns the priority catalog (low / normal / high / urgent) with the ids you pass to taskEntryPriorityStatusId. Also discoverable through Lookups.

  • Users for the assignee ids that go into assignedToUsersIds.
  • Clients and Patients for the context ids on a task.
  • Conventions for pagination, embedding, sorting, and date filters.
  • Errors for the error body shapes.