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.
Schema
Section titled “Schema”Authoritative schemas live in the live Swagger UI. The fields below are a representative subset for orientation.
| Field | Type | Notes |
|---|---|---|
id | UUID | Server-assigned identifier. |
clinicId | UUID | Clinic the task was created at. |
name | string | Short title shown in the UI list. |
description | string | Rich-text body (HTML). |
dateDue | ISO 8601 | When the task is due (UTC). Required on create. |
taskEntryPriorityStatusId | UUID | Priority (low / normal / high / urgent). See Lookups. |
taskEntryStatusId | UUID | Status (pending / in progress / completed). See Lookups. |
clientId | UUID | Client context, optional. |
patientId | UUID | Patient context, optional. Must belong to clientId if both are set. |
taskAssignedToUsers | array | Users the task is assigned to. Mutually exclusive with team assignment. |
taskAssignedToTeams | array | Teams the task is assigned to. Mutually exclusive with user assignment. |
taskNotes | array | Free-text notes attached to the task (see notes endpoint below). |
completedByUserId | UUID | User who marked the task complete, if any. |
isDeleted | boolean | Soft-delete flag. |
dateCreated | ISO 8601 | Server-assigned creation timestamp (UTC). |
dateUpdated | ISO 8601 | Last server-side mutation (UTC). |
List tasks
Section titled “List tasks”/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.
Example
Section titled “Example”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"}'import os, requests
resp = requests.post( "https://open-api.shepherd.vet/pav2/open-api-task-entries", headers={ "Content-Type": "application/json", "X-Integration-Public-Key": os.environ["SHEPHERD_PUBLIC_KEY"], "X-Integration-Private-Key": os.environ["SHEPHERD_PRIVATE_KEY"], "X-Clinic-Id": os.environ["SHEPHERD_CLINIC_ID"], }, json={ "page": 1, "rpp": 50, "sort": "dateDue|asc", "embed": "taskEntryPriorityStatus,taskEntryStatus", "isDeleted": False, "dueDateFrom": "2026-05-28T00:00:00Z", "dueDateTo": "2026-06-04T00:00:00Z", }, timeout=30,)resp.raise_for_status()for t in resp.json()["item"]: print(t["dateDue"], t["name"], t["taskEntryStatus"]["name"])using System.Net.Http.Json;
using var http = new HttpClient();http.DefaultRequestHeaders.Add("X-Integration-Public-Key", publicKey);http.DefaultRequestHeaders.Add("X-Integration-Private-Key", privateKey);http.DefaultRequestHeaders.Add("X-Clinic-Id", clinicId);
var body = JsonContent.Create(new { page = 1, rpp = 50, sort = "dateDue|asc", embed = "taskEntryPriorityStatus,taskEntryStatus", isDeleted = false, dueDateFrom = "2026-05-28T00:00:00Z", dueDateTo = "2026-06-04T00:00:00Z",});var resp = await http.PostAsync( "https://open-api.shepherd.vet/pav2/open-api-task-entries", body);resp.EnsureSuccessStatusCode();Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php$ch = curl_init('https://open-api.shepherd.vet/pav2/open-api-task-entries');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'X-Integration-Public-Key: ' . getenv('SHEPHERD_PUBLIC_KEY'), 'X-Integration-Private-Key: ' . getenv('SHEPHERD_PRIVATE_KEY'), 'X-Clinic-Id: ' . getenv('SHEPHERD_CLINIC_ID'), ], CURLOPT_POSTFIELDS => json_encode([ 'page' => 1, 'rpp' => 50, 'sort' => 'dateDue|asc', 'embed' => 'taskEntryPriorityStatus,taskEntryStatus', 'isDeleted' => false, 'dueDateFrom' => '2026-05-28T00:00:00Z', 'dueDateTo' => '2026-06-04T00:00:00Z', ]),]);$response = curl_exec($ch);curl_close($ch);echo $response;const resp = await fetch( 'https://open-api.shepherd.vet/pav2/open-api-task-entries', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Integration-Public-Key': process.env.SHEPHERD_PUBLIC_KEY, 'X-Integration-Private-Key': process.env.SHEPHERD_PRIVATE_KEY, 'X-Clinic-Id': process.env.SHEPHERD_CLINIC_ID, }, body: JSON.stringify({ page: 1, rpp: 50, sort: 'dateDue|asc', embed: 'taskEntryPriorityStatus,taskEntryStatus', isDeleted: false, dueDateFrom: '2026-05-28T00:00:00Z', dueDateTo: '2026-06-04T00:00:00Z', }), },);if (!resp.ok) throw new Error(`Shepherd ${resp.status}: ${await resp.text()}`);const page = await resp.json();for (const t of page.item) console.log(t.dateDue, t.name, t.taskEntryStatus.name);Response
Section titled “Response”{ "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": []}Create a task
Section titled “Create a task”/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.
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.
Update a task
Section titled “Update a task”/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 omitted | Cleared when omitted |
|---|---|
taskEntryPriorityStatusId, taskEntryStatusId, dateDue | name, 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:
- Read it:
POST /pav2/open-api-task-entrieswith{"ids": "<TASK_GUID>", "rpp": 1, "embed": "taskAssignedToUsers,taskAssignedToTeams"}. - Build the update body from that record:
name,description,clientId,patientId,dateDue,taskEntryPriorityStatusId,taskEntryStatusId, plusassignedToUsersIdsfromtaskAssignedToUsers[].user.idorassignedToTeamsIdsfromtaskAssignedToTeams[].team.id. - 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.
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.
Task notes
Section titled “Task notes”/pav2/open-api-task-notes /pav2/open-api-task-notes/write /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.
Priority lookup
Section titled “Priority lookup”/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.
See also
Section titled “See also”- 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.