Tasks
Read and write your organization's tasks, the work items people, automations and agents share, with the app's own rules, dry runs and idempotency keys.
TL;DRAI summary
Tasks are records of work to do, whether for a person, an automated agent, or a Cypress integration. This chapter explains how to create, update, and manage tasks, ensuring they are always linked to something relevant in your organization and assigned to an active team member.
A task is something someone said they would do: call a buyer back, chase a title, prepare a car for its sale window. In Cypress the same task list serves people, automations and agents, so an agent your organization connects can be given work, report it done, and hand work to a person. Since 1.5.0.
Every write goes through the same task commands the app uses, so the rules are the app's rules whoever calls:
- A task belongs to something of your organization: a contact, a company,
a deal, a vehicle, a sell goal, window or lot, a buy target, or the
conversation it was made from. A task about
nothing is refused (
422 INVALID), and a record of another organization answers404 NOT_FOUNDexactly as an unknown one does. - It is given only to an active member of your organization, people and
agents alike (
422 INVALID, "That person cannot be given this task."). - It says who made it and from where. An agent's task is its own
(
source: AGENT, with itsplayKey); an app acting for a person makes the person's (PERSON); an API key has no person behind it, so its task reads as an automation's (AUTOMATION), made by nobody and unassigned unless the request names someone.
| Scope | Grants |
|---|---|
tasks:read | GET /api/v1/tasks, GET /api/v1/tasks/{id}, and the TASK.* webhooks |
tasks:write | Everything tasks:read grants, plus every write below |
Both an API key and a Connect Cypress token are accepted.
The task
{
"id": "clx…",
"title": "Call the buyer back about the RAV4",
"notes": null,
"status": "OPEN",
"dueDate": "2026-11-02T15:00:00.000Z",
"channel": "PHONE",
"source": "AGENT",
"playKey": "follow-up",
"assignee": { "id": "clx…", "name": "Scout", "kind": "AGENT" },
"createdBy": { "id": "clx…", "name": "Scout", "kind": "AGENT" },
"completedBy": null,
"completedAt": null,
"links": {
"contactId": "clx…", "dealId": null, "businessId": null, "vehicleId": "clx…",
"planningGoalId": null, "saleWindowKey": null, "lotKey": null, "buyTargetId": null, "plan": null,
"conversation": null,
"app": "https://app.getcypress.ai/go/task/clx…"
},
"createdOn": "2026-10-15T14:00:00.000Z",
"updatedOn": "2026-10-15T14:00:00.000Z",
"href": "/api/v1/tasks/clx…"
}People are named and marked PERSON or AGENT, never emailed: tasks:read
is not members:read. saleWindowKey is a sale window's lineage
(2026W44-2026W45), which outlives the plan's versions. plan is a quarter's plan as a whole,
{ "side": "SELL", "periodKey": "2026-Q4" } ("get Q4 approved"): send it on
create to put a task there (Cypress's own book has no plan, so it is refused
there). The plan's Tasks tab in the app lists these beside the tasks on its
goals, windows, lots and targets. conversation is the conversation a task
was made from, or null (see below).
A task from a conversation
Since 1.9.0. A task made from a message ("retake the Tahoe photos") can
belong to the conversation it came from: a Huddle room and, when it came from
one message, that message. Send conversation on create, alone or beside any
other link:
{ "title": "Retake the Tahoe photos", "conversation": { "roomId": "room_8f2k", "messageId": "msg_41xq" } }roomIdis required;messageIdis optional (nullfor the room as a whole). A message id without its room is refused (422).- Each id is 1 to 64 letters, digits, dashes or underscores. They are Huddle's ids: Cypress keeps them as given and cannot check them.
- The task reads it back as
links.conversation,{ "roomId": "room_8f2k", "messageId": "msg_41xq" }, and the app shows the task with a link that opens the conversation in Huddle (Cypress's own, the same rooms Grove shows). PATCHtakesconversationtoo, to link a task to a conversation later ornullto unlink it. Unlinking a task that belongs to nothing else is refused (422 INVALID).GET /api/v1/tasks?conversationRoomId=room_8f2klists the tasks made from one conversation, and a webhook subscription whoseentityIdslists a room id gets theTASK.*events of that room's tasks.
List and read
GET /api/v1/tasks returns your organization's tasks, soonest due first and
undated last, 25 to a page (limit up to 100, offset, nextHref). Filters
combine:
| Filter | Example |
|---|---|
status | OPEN,DONE (OPEN, DONE, CANCELLED) |
source | AGENT (PERSON, AUTOMATION, AGENT) |
assignee | a member's id, me (the person or agent your token acts as) or none |
dueAfter, dueBefore | 2026-11-01T00:00:00Z |
contactId, dealId, businessId, vehicleId, planningGoalId, saleWindowKey, lotKey, buyTargetId, playKey | the tasks about one record, or of one play |
conversationRoomId | the tasks made from one conversation (its Huddle room's id). Since 1.9.0. |
An unknown filter is refused with 422, so a typo never returns everything.
assignee=me needs a token: an API key acts as nobody (422).
curl "$BASE/api/v1/tasks?assignee=me&status=OPEN" -H "authorization: Bearer $TOKEN"GET /api/v1/tasks/{id} returns one task.
Write
| Request | Does |
|---|---|
POST /api/v1/tasks | Creates a task (201). Left out, assigneeUserId is the caller when it is a person or an agent |
POST /api/v1/tasks/bulk | Up to 100 at once, each matched by your own ids: see Your own ids. Since 1.5.0. |
PATCH /api/v1/tasks/{id} | Changes the title, notes, due date, channel, status, assignee, company or (since 1.9.0) conversation; at least one field |
POST /api/v1/tasks/{id}/complete | Marks it done and records who finished it |
POST /api/v1/tasks/{id}/reassign | { "assigneeUserId": "…" } gives it to an active member, or (since 1.9.0) to the organization's own Cypress Manager; null to nobody |
DELETE /api/v1/tasks/{id} | Removes it (204) |
curl -X POST "$BASE/api/v1/tasks" \
-H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
-H "Idempotency-Key: follow-up-con_123-2026-11-02" \
-d '{
"title": "Call the buyer back about the RAV4",
"contactId": "clx…",
"vehicleId": "clx…",
"dueDate": "2026-11-02T15:00:00Z",
"channel": "PHONE",
"playKey": "follow-up"
}'Dry runs. Every write takes ?dryRun=true: the rules are checked and the
answer is { "dryRun": true, "changes": { … } }, the fields it would set,
with nothing written and no event sent.
Idempotency keys. Send Idempotency-Key (up to 200 characters) and a
retry with the same key and body gets the first answer, with
Idempotent-Replayed: true, instead of a second task. The same key with a
different body is 422 IDEMPOTENCY_KEY_REUSED.
Writes send the task events:
TASK.CREATED, TASK.ASSIGNED when a task is handed to someone other than
the caller, TASK.COMPLETED and TASK.CANCELLED. Editing, reopening and
removing send nothing.
Your own ids
Push and look up vehicles, listings, contacts, businesses, deals and tasks by the ids your own systems use, so a bridge keeps no mapping table of its own.
Huddle
Read and post in your organization's conversations (the huddle, channels, threads and the Inbox) as the person or agent your app acts for.