Checklist Tasks
A checklist task is one of the steps a template wrote down, running inside a checklist. These routes read a checklist's tasks and do to them what a person does on the checklist page: complete a task or mark it not applicable, assign it, give it a due date, comment on it, snooze it, tag it and read its activity. Every route lives under the checklist, at /v3/checklists/{checklistKey}/tasks/{taskKey}, and a task key that belongs to a different checklist answers 404 exactly as a key that names nothing.
Only the checklist's own tasks are addressable here. A task somebody attached to the checklist afterwards is a standalone task: it is not in the task list, it answers 404 on every route on this page, and you read and change it at /v3/tasks/{taskKey} instead. GET /v3/checklists/{key}/attached-tasks on the Checklists page lists those.
Every write acts as the member the API key acts as (see Who a Key Acts As), is recorded in their name, and is checked against what they may do — Who Can Change a Task sets out the rules. Every write on this page accepts an Idempotency-Key header. Most of them name a state rather than an action, so repeating one is already harmless; the exception is Add a Comment, which says the same thing twice if it is sent twice without a key.
Endpoints
All paths start /v3/checklists/{checklistKey}/tasks.
| Method | Path | Description | MCP tool |
|---|---|---|---|
GET | / | List checklist tasks | list_checklist_tasks |
GET | /{taskKey} | Get a task | get_task |
POST | /{taskKey}/complete | Complete a task | complete_task |
DELETE | /{taskKey}/complete | Uncomplete a task | uncomplete_task |
POST | /{taskKey}/not-applicable | Mark a task not applicable | set_task_not_applicable |
DELETE | /{taskKey}/not-applicable | Clear not applicable | clear_task_not_applicable |
GET | /{taskKey}/assignees | Get task assignees | — |
PUT | /{taskKey}/assignees | Assign a task | set_task_assignees |
DELETE | /{taskKey}/assignees | Unassign a task | clear_task_assignees |
GET | /{taskKey}/due-date | Get the due date | — |
PUT | /{taskKey}/due-date | Set the due date | set_task_due_date |
DELETE | /{taskKey}/due-date | Clear the due date | clear_task_due_date |
GET | /{taskKey}/comments | List comments | — |
POST | /{taskKey}/comments | Add a comment | add_task_comment |
DELETE | /{taskKey}/comments/{commentId} | Delete a comment | remove_task_comment |
GET | /{taskKey}/snooze | Get the snooze | get_task_snooze |
PUT | /{taskKey}/snooze | Snooze a task | set_task_snooze |
DELETE | /{taskKey}/snooze | End a snooze | end_task_snooze |
GET | /{taskKey}/tags | List task tags | — |
POST | /{taskKey}/tags | Tag a task | add_task_tags |
DELETE | /{taskKey}/tags?name= | Untag a task | remove_task_tag |
GET | /{taskKey}/activity | Get task activity | get_task_activity |
The reads marked — have no MCP tool because get_task already returns the assignees, due date, comments and tags. See Task Tools.
Fields, Files and Table Rows
A task's input controls — Short Text, Dropdown, Date & Time, File Upload, Table and the rest (see Control Types) — are its fields in the API. They come back in the fields array of Get a Task, and they have routes of their own under /v3/checklists/{checklistKey}/tasks/{taskKey}/fields: read every field or one field, answer one field or up to 50 in a single call, add and remove the files on a File Upload field at .../fields/{fieldKey}/files, and add rows to, remove rows from and set cells in a Table field at .../fields/{fieldKey}/rows. Answering a field is what satisfies a required control, which is what lets a task be completed. The field object, the value each control type takes and those routes are documented on Task Fields.
Who Can Change a Task
Reading a task — its list entry, detail, assignees, due date, comments, tags, activity, fields, files and table rows — needs permission to see the checklist, the same rule as reading the checklist itself on Checklists. A key that acts as an Administrator or as the workspace may read every checklist's tasks. A key that acts as a member may read them when the member's checklist permission on the template is Run and View or View But Not Run; with any other permission, or none, only when something in the checklist is assigned to them, directly or through a group. Otherwise the read is refused with 403 FORBIDDEN. A checklist in another workspace answers 404 CHECKLIST_NOT_FOUND rather than 403.
A member who may see the checklist may read all of its tasks. An exclusive assignment limits who may change a task, not who may read it.
Writes are checked against the member the key acts as. A key can never act as a Guest.
| Write | Who may make it | Refusal |
|---|---|---|
| Complete, uncomplete, mark or clear not applicable | An Administrator; a member whose checklist permission on the checklist is Run and View or Run and View Assigned To; or a member assigned to a task on the checklist. | 403 FORBIDDEN |
| Assign, unassign, set or clear the due date | Any Administrator or Member. When the task is assigned exclusively, only its assignees and Administrators. A key that acts as the workspace is refused. | 403 FORBIDDEN |
| Add a comment, tag or untag | Any key for the workspace. | — |
| Delete a comment | The comment's author or an Administrator. | 403 FORBIDDEN |
| Snooze, read or end a snooze | A key that acts as a member. | 403 API_KEY_ACTS_AS_WORKSPACE |
Completing a task has three further checks of its own, answered with 409 CONFLICT — see Complete a Task.
An exclusive assignment (isAssignedExclusively) means only the task's assignees — and Administrators — may complete, reassign or re-date it. It has no effect while nobody is assigned: a task assigned exclusively to nobody is open to everybody.
The Task Object
A task is returned in three sizes, each a superset of the one before:
- Task summary — what List Checklist Tasks returns for each task: everything stored on the task's own row.
- Task — the summary plus
assignees,fieldsandcomments. The status routes return this. - Task detail — the task plus
checklistandtags. Get a Task returns this.
| Field | Type | In | Description |
|---|---|---|---|
key | string (GUID) | All | The task key — the taskKey in every route on this page. |
name | string | All | The task's name. |
order | integer | All | Where the task sits on the checklist. The list is already in this order; compare the values rather than counting with them, because they are ascending but not always consecutive, and headings are numbered in the same sequence. |
isHeading | boolean | All | true for a heading — a divider rather than work. A heading has no status, due date, assignees or comments, and the status, assignee, due date and comment writes refuse it. |
status | string | All | Incomplete, Complete or NotApplicable. Absent for a heading. This is the field to branch on — the three states are exclusive. |
isComplete | boolean | All | true only when the task was completed. false for a not-applicable task and for a heading. |
isNotApplicable | boolean | All | true only when the task was marked not applicable. false for a heading. |
isCurrentlyHalted | boolean | All | true while the task sits behind an incomplete halt task. A halted task cannot be completed. |
isCurrentlyHidden | boolean | All | true while a condition is hiding the task. Hidden tasks are returned and flagged rather than left out, so that you choose whether to show them. |
isAssignedExclusively | boolean | All | true when only the assignees may complete, reassign or re-date the task. Kept while nobody is assigned, when it has no effect, because it decides how the next assignment behaves. |
dueDateTime | string (date-time) | All | When the task is due. Absent when it has no due date. |
completedDateTime | string (date-time) | All | When the task was completed. Absent while it is not. |
completedBy | user | All | Who completed it. Absent while nobody has, or when that member has since left the workspace. |
notApplicableDateTime | string (date-time) | All | When the task was marked not applicable. Absent while it is not. |
notApplicableBy | user | All | Who marked it not applicable. Absent while nobody has, or when that member has since left. |
assignees | array of assignee | Task, detail | Who the task is assigned to — groups first, then by name. Empty when nobody is. |
fields | array of field | Task, detail | The task's fields and their current values, leaving out any a condition is currently hiding. See Task Fields for the field object. |
comments | array of comment | Task, detail | The task's comments, oldest first. |
checklist | checklist reference | Detail | The checklist the task belongs to. |
tags | array of string | Detail | The task's own tags, by name, in name order. Tags on the checklist are not included. |
{
"checklist": {
"key": "9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93",
"name": "Invoice Review — INV-2041",
"url": "https://app.checkflow.io/Checklist/Index?checklistKey=9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93",
"template": {
"key": "3f2b8c1e-7a4d-4e5b-9c61-2d8f0a7b6e14",
"name": "Invoice Review",
"url": "https://app.checkflow.io/Template/Index?templateKey=3f2b8c1e-7a4d-4e5b-9c61-2d8f0a7b6e14",
"version": 3
}
},
"tags": ["q3-audit"],
"assignees": [
{ "id": 12, "type": "Group", "name": "Finance Team" },
{ "id": 1043, "type": "TeamMember", "name": "James Okafor" }
],
"fields": [
{
"key": "c5a19e3d-4f72-4b08-9e6a-2d81f0b7c4e9",
"name": "Purchase Order Number",
"type": "ShortText",
"isRequired": true,
"value": "PO-7713"
}
],
"comments": [
{
"id": 88213,
"text": "Totals match the purchase order.",
"html": "<p>Totals match the purchase order.</p>",
"createdBy": { "name": "James Okafor", "email": "james.okafor@acme.example" },
"createdDateTime": "2026-09-29T10:14:22Z",
"mentions": []
}
],
"key": "e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68",
"name": "Match invoice to purchase order",
"order": 3,
"isHeading": false,
"status": "Incomplete",
"isComplete": false,
"isNotApplicable": false,
"isCurrentlyHalted": false,
"isCurrentlyHidden": false,
"isAssignedExclusively": false,
"dueDateTime": "2026-10-02T17:00:00Z"
}
The User Reference
| Field | Type | Description |
|---|---|---|
name | string | The member's full name. |
email | string | The member's email address. |
The Checklist Reference
| Field | Type | Description |
|---|---|---|
key | string (GUID) | The checklist key. |
name | string | The checklist's name. |
url | string | The checklist's page in the app. |
template | object | The template it was run from: key, name, url, version, and description and createdDateTime when the template has them. |
The Assignee Object
An assignee is a team member or a group. The same shape is used for a comment's mentions and for assignedMentioned on Add a Comment.
| Field | Type | Description |
|---|---|---|
id | integer | The member's or group's id. |
type | string | TeamMember or Group. Part of the identity: member 12 and group 12 are different assignees. |
name | string | The member's full name or the group's name. Absent for a member recorded with a surname and no first name. |
{ "id": 1044, "type": "TeamMember", "name": "Priya Patel" }
Naming an Assignee
Wherever a request names somebody — assignees on Assign a Task and mentions on Add a Comment — each entry takes one of two forms:
| Form | Example | Matched against |
|---|---|---|
| Type and id | { "type": "TeamMember", "id": 1044 } | The member or group with that id. type is TeamMember or Group, case-insensitive, and is required with an id. |
| Name | { "name": "priya.patel@acme.example" } | A member's full name, a member's email address, or a group's name, case-insensitively. Ignored when id is given. |
- Only people and groups the workspace can assign match. That is every active Administrator, Member and Guest, and every group — the lists
GET /v3/workspacereturns. Deactivated members do not match. - A name that matches more than one member or group is refused with
400 VALIDATION_ERROR, and the message lists the candidates by type and id so that you can name the one you mean. Nothing is guessed. - Prefer the email address for a person. It is always present and always unique; a member recorded with a surname and no first name has no full name to match at all.
- The types
Unassigned,CurrentUserandChecklistCreatorthat template assignment rules use are not accepted — they are refused with400ontype.
The Comment Object
| Field | Type | Description |
|---|---|---|
id | integer | The comment's id — what Delete a Comment takes. |
text | string | What the comment says, with the markup removed. Paragraphs are separated by a blank line and line breaks by a newline, and a mention reads as the name it was written against. Read this unless you need the markup. Empty for a comment that is only an attachment. |
html | string | The comment as stored and as the checklist page renders it. Absent for a comment that is only an attachment. Comments written before v3 were stored as the browser sent them, so do not re-render this elsewhere without sanitising it. |
createdBy | user | Who wrote it. An author who has since left the workspace keeps their name and loses their email. |
createdDateTime | string (date-time) | When it was written. |
attachment | object | The file attached to the comment: name, contentType and url. Absent when there is none. |
mentions | array of assignee | Everybody the comment mentions, in the order it mentions them, each listed once. name is the name the mention was written against, not necessarily what the member or group is called now. Read from the comment's own markup, so it always agrees with what the comment says. |
An attachment's url is not protected by your API key — anybody holding the address can download the file. Treat it as a secret rather than a link to publish.
{
"id": 88240,
"text": "Over to @Priya Patel for sign-off.",
"html": "<p>Over to <span contenteditable=\"false\"><a class=\"mention-link\" data-id=\"1044\" data-assignable-type=\"1\">@Priya Patel</a></span> for sign-off.</p>",
"createdBy": { "name": "Sarah Chen", "email": "sarah.chen@acme.example" },
"createdDateTime": "2026-09-29T11:02:07Z",
"attachment": {
"name": "INV-2041.pdf",
"contentType": "application/pdf",
"url": "https://storage.example/attachments/5b7e0c1d/INV-2041.pdf"
},
"mentions": [
{ "id": 1044, "type": "TeamMember", "name": "Priya Patel" }
]
}
Comments cannot be edited, through the API or in the app. A comment is written once and either stays or is deleted whole.
List Checklist Tasks
Returns every task on a checklist, in the order the checklist page lays them out, headings included. Use it to see what is left to do: it reads the whole checklist in two queries, where Get a Task and GET /v3/checklists/{key} also load each task's fields, assignees and comments.
GET /v3/checklists/{checklistKey}/tasks
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
status | query | string | No | Comma-separated statuses to return: Incomplete, Complete, NotApplicable. Case, spaces, hyphens and underscores are ignored, so not-applicable works. Omit it for every task, headings included; because a heading has no status, any status filter leaves headings out. Any other value, or an empty status=, is refused. |
The response is not paged: a checklist has as many tasks as its template gave it, and they all come back at once. For tasks across many checklists — what is assigned to you, what is overdue — use the Tasks grid.
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"tasks": [
{
"key": "5a0f3d92-8e61-4c7b-9f24-1d6b8e3a7c05",
"name": "Verification",
"order": 1,
"isHeading": true,
"isComplete": false,
"isNotApplicable": false,
"isCurrentlyHalted": false,
"isCurrentlyHidden": false,
"isAssignedExclusively": false
},
{
"key": "b81c55e0-2f4a-4d6b-a1e9-7c3d0f2e8a46",
"name": "Check supplier details",
"order": 2,
"isHeading": false,
"status": "Complete",
"isComplete": true,
"isNotApplicable": false,
"isCurrentlyHalted": false,
"isCurrentlyHidden": false,
"isAssignedExclusively": false,
"completedDateTime": "2026-09-28T15:41:09Z",
"completedBy": { "name": "James Okafor", "email": "james.okafor@acme.example" }
},
{
"key": "e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68",
"name": "Match invoice to purchase order",
"order": 3,
"isHeading": false,
"status": "Incomplete",
"isComplete": false,
"isNotApplicable": false,
"isCurrentlyHalted": false,
"isCurrentlyHidden": false,
"isAssignedExclusively": false,
"dueDateTime": "2026-10-02T17:00:00Z"
},
{
"key": "71f8b3c6-0d2e-4a95-8b17-c4e6a9d2f053",
"name": "Approve payment",
"order": 4,
"isHeading": false,
"status": "Incomplete",
"isComplete": false,
"isNotApplicable": false,
"isCurrentlyHalted": true,
"isCurrentlyHidden": false,
"isAssignedExclusively": true
}
]
}
Each entry is a task summary.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The checklist's tasks. |
400 | VALIDATION_ERROR | checklistKey is not a GUID, or status names something other than the three statuses (field is status). |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND | No checklist with that key in your workspace. |
Get a Task
Returns one task in full: its state, assignees, fields and their values, comments, tags and the checklist it belongs to.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
The body is a task detail, as in the example under The Task Object.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task. |
400 | VALIDATION_ERROR | checklistKey or taskKey is not a GUID. |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND | No checklist with that key in your workspace. |
404 | TASK_NOT_FOUND | No task with that key on this checklist — including a standalone task attached to it. |
Complete a Task
Marks a task complete. Use this rather than Mark a Task Not Applicable when the work was done: a completed task is credited to the member the key acts as.
POST /v3/checklists/{checklistKey}/tasks/{taskKey}/complete
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
This endpoint takes no request body.
Example
POST https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/complete
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"assignees": [
{ "id": 12, "type": "Group", "name": "Finance Team" },
{ "id": 1043, "type": "TeamMember", "name": "James Okafor" }
],
"fields": [
{
"key": "c5a19e3d-4f72-4b08-9e6a-2d81f0b7c4e9",
"name": "Purchase Order Number",
"type": "ShortText",
"isRequired": true,
"value": "PO-7713"
}
],
"comments": [],
"key": "e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68",
"name": "Match invoice to purchase order",
"order": 3,
"isHeading": false,
"status": "Complete",
"isComplete": true,
"isNotApplicable": false,
"isCurrentlyHalted": false,
"isCurrentlyHidden": false,
"isAssignedExclusively": false,
"dueDateTime": "2026-10-02T17:00:00Z",
"completedDateTime": "2026-09-30T09:12:45Z",
"completedBy": { "name": "James Okafor", "email": "james.okafor@acme.example" }
}
The body is the task as it now stands, read back after the change.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is complete — including when it already was, in which case nothing is written. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The member the key acts as may not change this checklist's tasks. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
409 | CONFLICT | The task cannot be completed yet — see below. The message says which reason applies. |
When Completion Is Refused
A task is checked in this order, and the first failure is returned as 409 CONFLICT:
- It is halted. The task sits behind an incomplete halt task (
isCurrentlyHaltedistrue). Complete the halt task first. The halt task itself is never halted. - It is assigned exclusively to somebody else. Only its assignees and Administrators may complete it.
- A required field is empty. Answer it through Task Fields and try again.
What counts as an empty required field depends on the control. Fields a condition is currently hiding are skipped.
| Control | Holds the task open when |
|---|---|
| Short Text, Long Text, E-Mail, Website | It is required and empty. |
| Date & Time | It is required and has no value. |
| Dropdown, Multi-Choice | It is required and nothing is selected. |
| Members | It is required and nobody is selected. |
| Sub-Tasks | It is required and any sub-task is unticked. |
| File Upload | It holds fewer files than its minimum, or more than its maximum. |
| Mail-To | It is set to be sent from the task and has not been sent. |
A required Table does not hold a task open.
Notes
- Completing a task does everything completing it in the app does. It fires the
task_completedwebhook, records an activity entry, notifies Administrators and the task's assignees (not the member who completed it), releases tasks halted behind it, re-evaluates dynamic due dates across the checklist, and marks the checklist complete — notifying Administrators and the checklist's assignees — when this was the last task outstanding. - Repeating it is harmless. Completing a task that is already complete writes nothing, fires nothing and notifies nobody, and still answers
200. - The response reflects any change the conditions engine made to this task as a result. Other tasks may have been released or hidden too; list the tasks again to see them.
Uncomplete a Task
Returns a completed task to Incomplete, and reopens the checklist if completing this task had finished it.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/complete
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/complete
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
The body is the task as it now stands, with status Incomplete and no completedDateTime or completedBy.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is not complete — including when it was not complete to begin with. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The member the key acts as may not change this checklist's tasks. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- This clears completion and nothing else. A task marked not applicable is left not applicable and the call still answers
200— use Clear Not Applicable for that. Each state has one route back toIncomplete, so neither can undo the other by accident. - Uncompleting is never refused for halts, exclusive assignment or required fields; those checks apply only to completing.
- It records an activity entry and notifies Administrators and the task's assignees, as completing does, and re-evaluates halts and due dates across the checklist.
Mark a Task Not Applicable
Marks a task as not needing to be done. A not-applicable task stops holding the checklist open and releases any tasks halted behind it, exactly as completing it would, but it reads as NotApplicable and nobody is credited with doing it.
POST /v3/checklists/{checklistKey}/tasks/{taskKey}/not-applicable
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
This endpoint takes no request body.
Example
POST https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/71f8b3c6-0d2e-4a95-8b17-c4e6a9d2f053/not-applicable
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
The body is the task as it now stands, with status NotApplicable, isNotApplicable true and notApplicableDateTime and notApplicableBy filled in.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is not applicable — including when it already was. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The member the key acts as may not change this checklist's tasks. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- It is never refused for empty required fields, a halt or an exclusive assignment — only the permission check in Who Can Change a Task applies.
- Marking a completed task not applicable replaces the completion.
- It records an activity entry, notifies Administrators and the task's assignees, re-evaluates halts and due dates, and completes the checklist if this was the last task outstanding. It does not fire the
task_completedwebhook.
Clear Not Applicable
Returns a not-applicable task to Incomplete.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/not-applicable
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/71f8b3c6-0d2e-4a95-8b17-c4e6a9d2f053/not-applicable
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
The body is the task as it now stands, with status Incomplete.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is not marked not applicable — including when it was not to begin with. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The member the key acts as may not change this checklist's tasks. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- A completed task is left completed. This route clears not applicable and nothing else; use Uncomplete a Task to clear a completion.
Get Task Assignees
Returns who a task is assigned to and whether the assignment is exclusive. The same assignees are on Get a Task; this is the smaller read.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/assignees
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/assignees
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"assignees": [
{ "id": 12, "type": "Group", "name": "Finance Team" },
{ "id": 1043, "type": "TeamMember", "name": "James Okafor" }
],
"isAssignedExclusively": false
}
| Field | Type | Description |
|---|---|---|
assignees | array of assignee | Everybody the task is assigned to — groups first, then by name, then by id, so two reads of an unchanged task answer identically. Empty when nobody is. |
isAssignedExclusively | boolean | true when only these assignees (and Administrators) may complete, reassign or re-date the task. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | Who the task is assigned to. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Assign a Task
Sets who a task is assigned to. The list replaces the task's assignees: anybody not in it is unassigned. To add somebody, read the current assignees and send them back with the new one.
PUT /v3/checklists/{checklistKey}/tasks/{taskKey}/assignees
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
{
"assignees": [
{ "type": "Group", "id": 12 },
{ "name": "priya.patel@acme.example" }
],
"isAssignedExclusively": false
}
| Field | Type | Required | Description |
|---|---|---|---|
assignees | array | No | Who the task is assigned to afterwards. Each entry is { "type", "id" } or { "name" } — see Naming an Assignee. An empty or missing list unassigns the task. Naming the same assignee twice is not an error. |
isAssignedExclusively | boolean | No | true to let only the assignees (and Administrators) complete, reassign or re-date the task. Defaults to false, and it is written on every call — send the current value back if you mean to keep it. |
Example
PUT https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/assignees
X-API-KEY: your-api-key-here
Content-Type: application/json
{
"assignees": [
{ "type": "Group", "id": 12 },
{ "name": "priya.patel@acme.example" }
],
"isAssignedExclusively": false
}
HTTP/1.1 200 OK
{
"assignees": [
{ "id": 12, "type": "Group", "name": "Finance Team" },
{ "id": 1044, "type": "TeamMember", "name": "Priya Patel" }
],
"isAssignedExclusively": false
}
The body has the same shape as Get Task Assignees.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is assigned as the body says — including when it already was. |
400 | VALIDATION_ERROR | A key is not a GUID; the task is a heading (field is checklistTaskId); an entry names nobody (assignees[0]), gives an id without a type or an unknown type (assignees[0].type), or gives a name that matches nobody or more than one assignee (assignees[0].name); or an id is not somebody this workspace can assign (assignees). |
403 | FORBIDDEN | The key acts as the workspace, or the task is assigned exclusively and the member the key acts as is neither an assignee nor an Administrator. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Newly assigned people are notified, as they are when assigned in the app. Anybody already on the task is not notified again, so sending the same body twice writes nothing and tells nobody.
- Nobody is told they have been unassigned.
- An assignee a dynamic assignment put on the task stays linked to it when you send them back in the list.
Unassign a Task
Assigns a task to nobody — the same write as Assign a Task with an empty list, without composing a body.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/assignees
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/assignees
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"assignees": [],
"isAssignedExclusively": true
}
Responses
| Status | Code | When |
|---|---|---|
200 | — | Nobody is assigned — including when nobody was. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The key acts as the workspace, or the task is assigned exclusively and the member the key acts as is neither an assignee nor an Administrator. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
isAssignedExclusivelyis kept as it was, unlike aPUTwith an empty list, which sets it to whatever the body says. It has no effect while nobody is assigned, and keeping it means the next assignment starts on the same terms as the last.- Nobody is notified.
Get the Due Date
Returns when a task is due, and whether the template works the date out for itself. The date is also on every read of the task; isRuleGoverned is only here.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/due-date
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/due-date
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"dueDateTime": "2026-10-02T17:00:00Z",
"isRuleGoverned": false
}
| Field | Type | Description |
|---|---|---|
dueDateTime | string (date-time) | When the task is due, in UTC. Absent when it has no due date. |
isRuleGoverned | boolean | true when a dynamic due date rule on the template dates this task. A date you set still applies, but only until the rule is next evaluated — for example when the task it counts from is completed. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | When the task is due. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Set the Due Date
Says when a task is due.
PUT /v3/checklists/{checklistKey}/tasks/{taskKey}/due-date
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
{
"dueDateTime": "2026-10-02T17:00:00Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
dueDateTime | string (date-time) | No | When the task is due. A date without an offset is read as UTC — see Dates and Times. A date in the past is accepted and makes the task overdue. null, or leaving the field out, clears the due date — the same as Clear the Due Date. |
Example
PUT https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/due-date
X-API-KEY: your-api-key-here
Content-Type: application/json
{
"dueDateTime": "2026-10-02T17:00:00Z"
}
HTTP/1.1 200 OK
{
"dueDateTime": "2026-10-02T17:00:00Z",
"isRuleGoverned": false
}
The body has the same shape as Get the Due Date.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is due when the body says — including when it already was. |
400 | VALIDATION_ERROR | A key is not a GUID; the body is missing or is not valid JSON; the task is a heading (field is checklistTaskId); or the date is 0001-01-01T00:00:00Z, which cannot be told apart from no date (field is dueDate). |
403 | FORBIDDEN | The key acts as the workspace, or the task is assigned exclusively and the member the key acts as is neither an assignee nor an Administrator. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Setting the date the task already has writes nothing. That matters because every change reschedules the task's due date reminders.
- A rule-governed task is dated anyway. Naming one task is an override, as it is in the app, and the response says
isRuleGoverned: trueso that you know the date lasts only until the rule next runs. - Nobody is notified.
Clear the Due Date
Says a task is not due by any particular time. The same write as sending "dueDateTime": null.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/due-date
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/due-date
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"isRuleGoverned": false
}
dueDateTime is absent because the task no longer has one.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task has no due date — including when it had none. |
400 | VALIDATION_ERROR | A key is not a GUID, or the task is a heading (field is checklistTaskId). |
403 | FORBIDDEN | The key acts as the workspace, or the task is assigned exclusively and the member the key acts as is neither an assignee nor an Administrator. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Reminders scheduled against the old date stop. Nobody is notified.
List Comments
Returns a task's comments, oldest first. The same comments are on Get a Task.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/comments
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/comments
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"comments": [
{
"id": 88213,
"text": "Totals match the purchase order.",
"html": "<p>Totals match the purchase order.</p>",
"createdBy": { "name": "James Okafor", "email": "james.okafor@acme.example" },
"createdDateTime": "2026-09-29T10:14:22Z",
"mentions": []
}
]
}
comments is an array of comment objects. It is not paged. A heading answers with an empty list.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task's comments. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Add a Comment
Adds a comment to a task, written as the member the key acts as, optionally mentioning people and carrying a file.
POST /v3/checklists/{checklistKey}/tasks/{taskKey}/comments
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
{
"text": "Over to Priya Patel for sign-off.\n\nThe invoice is attached.",
"mentions": [
{ "name": "priya.patel@acme.example" }
],
"attachment": {
"name": "INV-2041.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjcKJeLjz9MK..."
}
}
| Field | Type | Required | Description |
|---|---|---|---|
text | string | No | What to say, as plain text. Send text or html, not both. |
html | string | No | What to say, as HTML. Send html or text, not both. |
mentions | array | No | People and groups to mention, each named as in Naming an Assignee. |
assignMentioned | boolean | No | Whether mentioning somebody on an exclusively assigned task also assigns them to it. Default true. |
attachment | object | No | A file to attach. |
attachment.name | string | With attachment | The file name to record. |
attachment.content | string | With attachment | The file's bytes, base64 encoded. At most 32 MB. |
attachment.contentType | string | No | The file's media type. Recorded as application/octet-stream when you leave it out. |
A comment needs something in it: text, html, at least one mention, or an attachment. One with none of these is refused.
Text and HTML
text is plain text. It is escaped and wrapped into paragraphs: a blank line starts a new paragraph, a single newline is a line break, and anything that looks like markup is shown as typed rather than obeyed. Markdown is not rendered — **bold** is stored as the characters you sent. Use text unless you have HTML.
html is filtered through an allow-list. Elements not on the list are unwrapped — the markup goes and the words inside it are kept. Attributes not on the list are dropped.
| Allowed | Elements | Attributes kept |
|---|---|---|
| Blocks | p, div, blockquote, pre, h1–h6, br | align on div |
| Lists and tables | ul, ol, li, table, thead, tbody, tfoot, tr, td, th | — |
| Inline | b, strong, i, em, u, s, strike, sub, sup, code, span | class and contenteditable on span |
| Links | a | href, class, data-id, data-assignable-type |
- A link's
hrefsurvives only when it is relative or its scheme ishttp,httpsormailto. Any other scheme, such asjavascript:, loses itshref. script,style,iframe,object,embed,noscript,svg,math,template,head,title,link,metaandbaseare removed together with their contents, and HTML comments are removed.- HTML that is nothing but markup — for example only a
scriptelement — is refused rather than stored as an empty comment.
Mentions
A mention notifies the person or group it names. There are two ways to write one.
Name them in mentions (recommended). Each entry is resolved against the workspace and turned into a mention where the comment already says the name: the first place the comment's text reads Priya Patel or @Priya Patel (case-insensitively) becomes the mention, written in the workspace's own spelling of the name. A mention whose name does not appear in the comment is added on a line of its own at the end. A comment can be nothing but mentions.
Write the anchor in html. A mention is this exact markup, which the allow-list keeps:
<a class="mention-link" data-id="1044" data-assignable-type="1">@Priya Patel</a>
data-id is the member or group id and data-assignable-type is 1 for a member or 2 for a group. The class must be exactly mention-link. If mentions names somebody the markup already mentions, they are mentioned once.
What a mention does:
- Everybody mentioned is emailed and notified in Slack, however the task is assigned.
- On a task assigned exclusively, anybody mentioned who is not already an assignee — other than an Administrator — is added to the assignees, so that they can open the task. The response lists them in
assignedMentioned. Send"assignMentioned": falsewhen you are telling somebody rather than asking them: they are still notified but not assigned. - On a task that is not assigned exclusively, or that nobody is assigned to, nobody is assigned.
Example
POST https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/comments
X-API-KEY: your-api-key-here
Content-Type: application/json
Idempotency-Key: 6a9c2e4f-comment-inv-2041
{
"text": "Over to Priya Patel for sign-off.",
"mentions": [
{ "name": "priya.patel@acme.example" }
]
}
HTTP/1.1 201 Created
{
"comment": {
"id": 88240,
"text": "Over to @Priya Patel for sign-off.",
"html": "<p>Over to <span contenteditable=\"false\"><a class=\"mention-link\" data-id=\"1044\" data-assignable-type=\"1\">@Priya Patel</a></span> for sign-off.</p>",
"createdBy": { "name": "Sarah Chen", "email": "sarah.chen@acme.example" },
"createdDateTime": "2026-09-29T11:02:07Z",
"mentions": [
{ "id": 1044, "type": "TeamMember", "name": "Priya Patel" }
]
},
"assignedMentioned": []
}
| Field | Type | Description |
|---|---|---|
comment | comment | The comment as stored, with its id. |
assignedMentioned | array of assignee | Anybody the comment's mentions added to the task's assignees. Empty unless the task is assigned exclusively and assignMentioned was not false. This is not the list of who was mentioned or notified — that is comment.mentions. |
Responses
| Status | Code | When |
|---|---|---|
201 | — | The comment was added. |
400 | VALIDATION_ERROR | A key is not a GUID; the body is missing or not valid JSON; both text and html were sent (html); the comment is empty (text), or its html was all removed by the allow-list (html); a mention names nobody, gives an id without a type, gives an id or name the workspace does not have, or a name that matches more than one assignee (mentions[0], mentions[0].type, mentions[0].name); the attachment has no name (attachment.name), is not base64 or is over 32 MB (attachment.content); or the task is a heading (taskKey). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Everybody assigned to the task is emailed and notified in Slack, as they are for a comment left in the app, as well as everybody mentioned.
- This write is not idempotent on its own — sending it twice posts two comments. Send an
Idempotency-Keyif you may retry. - The MCP tool
add_task_commenttakestext,html,mentionsandassignMentioned, but not an attachment.
Delete a Comment
Deletes one comment, and its attachment with it.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/comments/{commentId}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
commentId | path | integer | Yes | The comment's id, from List Comments or Get a Task. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/comments/88240
X-API-KEY: your-api-key-here
Responds 204 No Content with no body.
Responses
| Status | Code | When |
|---|---|---|
204 | — | The comment and any attachment were deleted. |
400 | VALIDATION_ERROR | A key is not a GUID, or commentId is not a positive whole number (commentId). |
403 | FORBIDDEN | The member the key acts as did not write the comment and is not an Administrator. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
404 | COMMENT_NOT_FOUND | No comment with that id on this task — including one that has already been deleted, or one on a different task. |
Deleting a comment is permanent. The comment and its attached file cannot be recovered, and there is no edit to use instead.
Get the Snooze
Says whether the task is snoozed for the member the key acts as, and until when. A snooze is personal: it hides the task from one person's Tasks grid and changes nothing anybody else sees, so two keys acting as different members can get different answers for the same task.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/snooze
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/snooze
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"isSnoozed": true,
"snoozedUntil": "2026-10-05T08:00:00Z"
}
| Field | Type | Description |
|---|---|---|
isSnoozed | boolean | Whether the task is hidden from this member's Tasks grid right now. A snooze whose date has passed reads as false. |
snoozedUntil | string (date-time) | When the snooze runs out, in UTC. Still reported after it has passed, until the expired snooze is cleaned up, so that "snoozed and ran out" can be told apart from "never snoozed". Absent when this member has not snoozed the task. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | The snooze state for the acting member. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | API_KEY_ACTS_AS_WORKSPACE | The key acts as the workspace, which has nobody to snooze a task for (field is X-API-KEY). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Snooze a Task
Hides the task from the Tasks grid of the member the key acts as until a date you choose. To snooze many tasks at once, see bulk snooze.
PUT /v3/checklists/{checklistKey}/tasks/{taskKey}/snooze
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
{
"snoozedUntil": "2026-10-05T08:00:00Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
snoozedUntil | string (date-time) | Yes | When the snooze runs out. Must be in the future. A date without an offset is read as UTC. null does not clear a snooze — use End a Snooze. |
Example
PUT https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/snooze
X-API-KEY: your-api-key-here
Content-Type: application/json
{
"snoozedUntil": "2026-10-05T08:00:00Z"
}
HTTP/1.1 200 OK
{
"isSnoozed": true,
"snoozedUntil": "2026-10-05T08:00:00Z"
}
snoozedUntil is the value stored, in UTC — a date sent with an offset comes back converted.
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is snoozed until the date given. Sending the same date again stores it again and still answers 200. |
400 | VALIDATION_ERROR | A key is not a GUID; the body is missing or not valid JSON; or snoozedUntil is missing, null or not in the future (snoozedUntil). |
403 | API_KEY_ACTS_AS_WORKSPACE | The key acts as the workspace (field is X-API-KEY). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Nobody else is affected. No activity entry is recorded, nobody is notified, no webhook fires, and the task goes on appearing on everybody else's Tasks grid.
End a Snooze
Returns the task to the Tasks grid of the member the key acts as.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/snooze
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/snooze
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"isSnoozed": false
}
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task is not snoozed for this member — including when it was not snoozed, or its snooze had already run out. The response is the same in every case. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | API_KEY_ACTS_AS_WORKSPACE | The key acts as the workspace (field is X-API-KEY). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Nobody else is affected and nothing is announced.
List Task Tags
Returns the tags on a task, by name, in name order. A task's tags are its own: tagging a checklist does not tag its tasks, and this returns none of the checklist's tags — those are on the Checklists routes.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/tags
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/tags
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"tags": ["q3-audit", "urgent"]
}
Responses
| Status | Code | When |
|---|---|---|
200 | — | The task's tags. |
400 | VALIDATION_ERROR | A key is not a GUID. |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Tag a Task
Puts one or more tags on a task, by name. The rules for tag names are the same as on a checklist — see Tags.
POST /v3/checklists/{checklistKey}/tasks/{taskKey}/tags
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
Request Body
{
"tags": ["urgent", "q3-audit"]
}
| Field | Type | Required | Description |
|---|---|---|---|
tags | array of string | Yes | The tag names. At least one and at most 25, counted after blanks are dropped, names are trimmed and duplicates are collapsed case-insensitively. Each at most 100 characters. |
Example
POST https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/tags
X-API-KEY: your-api-key-here
Content-Type: application/json
{
"tags": ["urgent", "q3-audit"]
}
HTTP/1.1 200 OK
{
"created": [],
"tags": ["q3-audit", "urgent"]
}
| Field | Type | Description |
|---|---|---|
created | array of string | Tags that did not exist anywhere in the workspace until this call created them. Usually empty. |
tags | array of string | Every tag now on the task, in name order. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | The tags are on the task — including any it already carried, which are not written again. |
400 | VALIDATION_ERROR | A key is not a GUID; the body is missing or not valid JSON; or tags names no tag, more than 25, or one longer than 100 characters (tags). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
A name the workspace has not used before creates a new tag — there is no separate step for creating one. A misspelling therefore succeeds and adds a tag; check created to catch it, or read the existing names from GET /v3/workspace first. Matching is case-insensitive, so Urgent and urgent are one tag.
Untag a Task
Takes one tag off a task. The name goes in the name query parameter rather than the path, because a tag name may contain any character, including a slash.
DELETE /v3/checklists/{checklistKey}/tasks/{taskKey}/tags?name={name}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
name | query | string | Yes | The tag to remove, URL-encoded. Matched case-insensitively. At most 100 characters. |
Example
DELETE https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/e27c9a14-6b3d-4f8e-a5c1-9d0b2f7e4a68/tags?name=urgent
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"tagDeleted": false,
"tags": ["q3-audit"]
}
| Field | Type | Description |
|---|---|---|
tagDeleted | boolean | true when that was the tag's last use anywhere in the workspace, so the workspace no longer has the tag at all. false when the tag was not on the task. |
tags | array of string | The tags left on the task, in name order. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | The tag is not on the task — including when it was not there to begin with, in which case nothing is written. |
400 | VALIDATION_ERROR | A key is not a GUID, or name is missing, blank or longer than 100 characters (name). |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Tags are created by being used and removed when they stop being used. Removing a tag from the last thing carrying it removes it from the workspace, and
tagDeletedsays so.
Get Task Activity
Returns what has happened to one task, most recent first: the checklist's activity feed narrowed to this task, in the same shape.
GET /v3/checklists/{checklistKey}/tasks/{taskKey}/activity
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
checklistKey | path | string (GUID) | Yes | The checklist key. |
taskKey | path | string (GUID) | Yes | The task key. |
sort | query | string | No | occurredAt, occurredAt:asc or occurredAt:desc. Default occurredAt:desc, most recent first. |
pageSize | query | integer | No | Entries per page, 1–100. Default 50. A value outside the range, or one that is not a number, is replaced by 50 rather than refused. You can change it between pages without losing your place. |
after | query | string | No | The nextCursor from the previous page. Send the same sort it was issued under. A cursor from a different order, or from the checklist's own feed, is refused. |
Example
GET https://api.checkflow.io/v3/checklists/9d4e2b71-3c8a-4f15-b6d2-0e7a1c5f8b93/tasks/b81c55e0-2f4a-4d6b-a1e9-7c3d0f2e8a46/activity?pageSize=1
X-API-KEY: your-api-key-here
HTTP/1.1 200 OK
{
"items": [
{
"occurredAt": "2026-09-28T15:41:09Z",
"actor": { "name": "James Okafor", "email": "james.okafor@acme.example" },
"description": "Completed task 'Check supplier details'",
"taskKey": "b81c55e0-2f4a-4d6b-a1e9-7c3d0f2e8a46",
"taskName": "Check supplier details"
}
],
"nextCursor": "eyJ2IjoxLCJzIjoib2NjdXJyZWRBdDpkZXNjIn0",
"hasMore": true,
"total": 7
}
The response is paged; total counts the task's whole feed, not the page.
| Field | Type | Description |
|---|---|---|
occurredAt | string (date-time) | When it happened. |
actor | user | Who did it. API Service and Scheduler Service are not team members and carry no email. A member who has since left reads as Unknown User. |
description | string | What happened, as a sentence with the task and field names filled in. Dates in it are written in the time zone described in Time Zones. |
taskKey | string (GUID) | The task the entry is about. |
taskName | string | The task's current name. Absent when the task has been deleted. |
fieldKey | string (GUID) | The field the entry is about. Absent when it is not about a field. |
fieldName | string | The field's current label. Absent when the field has been deleted. |
dateTimeValue | string (date-time) | The value a Date & Time field was set to, for entries that record one. |
Responses
| Status | Code | When |
|---|---|---|
200 | — | A page of the task's activity. |
400 | VALIDATION_ERROR | A key is not a GUID; sort is not one of the three values (sort); or after is unreadable, was issued under a different sort or for a different feed (after). |
403 | FORBIDDEN | The member the key acts as may not see this checklist. See Who Can Change a Task. |
404 | CHECKLIST_NOT_FOUND / TASK_NOT_FOUND | No such checklist, or no such task on it. |
Notes
- Activity is written a second or two after the event, so this is not the way to confirm a write you have just made — the response to the write is.
- There is no event type. Names are resolved when the feed is read, so a renamed task reads under its current name throughout its history, and an entry about a deleted field says
(deleted).
Related Pages
- Task Fields — read and answer a task's fields, and manage its files and table rows.
- Checklists — the checklist itself, its tags, its activity feed and its attached tasks.
- Standalone Tasks — tasks that are not part of a checklist's template, including those attached to a checklist.
- My Work — the Tasks grid across every checklist, saved views and bulk snooze.
- Task Tools — the MCP tools for the same operations.