Public REST API for integrations and scripts. Base URL:
https://taskid.app/v1/api
Plugging in an AI assistant (Claude, ChatGPT)? MCP connector → is easier and doesn't require crafting HTTP requests by hand.
The API accepts and returns JSON. Request bodies use
application/json; charset=utf-8.
Dates are strings in ISO-8601 UTC, without milliseconds:
2026-04-18T12:34:56Z.
Identifiers are UUID v4 strings in canonical form.
The API works in tandem with client-side background sync. A task created through the API appears in the iOS/web interface after the next sync cycle (usually within a couple of seconds).
Every request requires the header:
Authorization: Bearer tkd_xxxxxxxxxxxxxxxxxxxxTokens are created on the API tokens page.
GET requests are allowed.GET and
POST for tasks,
notes, lists and groups.When creating a token you can restrict it to specific lists - then requests to other lists return 403.
Errors return standard HTTP codes and a JSON body like:
{ "message": "list is not accessible by this token" } | Code | When |
|---|---|
| 400 | Malformed request body (missing title, invalid date). |
| 401 | No Authorization header, or token not found / revoked / expired. |
| 403 | Missing scope (write for POST) or list not accessible to the token. |
| 404 | List does not exist or has been deleted. |
| 429 | Rate limit exceeded (applies to notification sending). The Retry-After and X-RateLimit-* headers indicate how many seconds to wait before retrying. |
| 500 | Server error - retry later. |
/v1/api/groupsA group is a container for regular lists. It contains no tasks or records itself, but lets you bundle several lists under one umbrella. Tokens with limited access only see groups that contain at least one of their allowed lists.
curl -H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/groups { "groups": Group[] }/v1/api/groups| Field | Type | Description |
|---|---|---|
| name | string * | Group name. Required, non-empty. |
| color | string | null | HEX color or theme token name. Optional. |
| icon | string | null | Icon name (SF Symbol). Optional. |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Work", "icon": "briefcase" }' \
https://taskid.app/v1/api/groups { "group": Group }/v1/api/groups/:id{ "group": Group }/v1/api/groups/:id| Field | Type | Description |
|---|---|---|
| name | string | New name. Empty string is not allowed. |
| color | string | null | HEX or theme token name. null clears it. |
| icon | string | null | Icon name (SF Symbol). null clears it. |
| archived | boolean | Archive / unarchive. |
curl -X PATCH \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Work projects" }' \
https://taskid.app/v1/api/groups/GROUP_ID { "group": Group }/v1/api/groups/:idSoft delete. Lists that belonged to the group remain - after sync they appear at the root (parent_id still points to the deleted group). Requires scope=write (all_lists).
/v1/api/listsReturns all lists the token has access to. Archived lists are included too - see the archived flag.
curl -H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/lists {
"lists": [
{
"id": "6f8a6f4e-9b0e-4a82-9f6b-2a3f1e4a5d1a",
"parent_id": null,
"name": "Work",
"color": "#0a84ff",
"icon": "briefcase",
"archived": false,
"is_owner": true,
"is_shared": false
}
]
}Lists can be shared (the "Share" button on the site). The response contains both your own and shared ones; two boolean fields help tell them apart:
is_owner - true: you own the list; false: you're a member of someone else's. Only the owner can edit the list itself (name, color, icon, archive, delete, attach to a group) - a member attempt returns 403. The contents (tasks and notes) can be edited by both.is_shared - true: the list has members (shared), regardless of your role; false: strictly personal.In shared lists, the completed_user_id / deleted_user_id fields on tasks show who actually closed/deleted the record (not its owner).
/v1/api/listsCreates a new list for the token owner.
| Field | Type | Description |
|---|---|---|
| name | string * | List name. Required. |
| color | string | null | HEX color or theme token name. |
| icon | string | null | Icon name (SF Symbol). |
| parent_id | UUID | null | UUID of the group to place the list into immediately. Groups are created via /v1/api/groups. |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Shopping", "color": "#0a84ff" }' \
https://taskid.app/v1/api/lists {
"list": {
"id": "6f8a6f4e-...",
"parent_id": null,
"name": "Shopping",
"color": "#0a84ff",
"icon": null,
"archived": false
}
}/v1/api/lists/:idReturns a single list by its identifier.
curl -H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/lists/LIST_ID { "list": List }/v1/api/lists/:idPartial update: include only the fields you want to change.
| Field | Type | Description |
|---|---|---|
| name | string | New name. Empty string is not allowed. |
| color | string | null | HEX or theme token name. null clears it. |
| icon | string | null | Icon name (SF Symbol). null clears it. |
| archived | boolean | Archive / unarchive. |
POST /v1/api/lists/:id/attach.curl -X PATCH \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Weekly shopping" }' \
https://taskid.app/v1/api/lists/LIST_ID { "list": List }/v1/api/lists/:id/attachAttaches an existing list to a group, or detaches it. In the URL - the list id, in the body - only parent_id. The list itself is not edited - only its group membership changes.
{
"parent_id": UUID | null // null - move to root
}curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "parent_id": "GROUP_ID" }' \
https://taskid.app/v1/api/lists/LIST_ID/attach curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "parent_id": null }' \
https://taskid.app/v1/api/lists/LIST_ID/attach { "list": List }/v1/api/lists/:idSoft delete of a list (deleted_at = now). Tasks in the list also stop showing on clients after sync.
curl -X DELETE \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/lists/LIST_ID /v1/api/lists/:id/tasksReturns tasks from a specific list.
| Parameter | Default | Values |
|---|---|---|
| completed | 0 | 0 - hide completed, 1 - only completed, all - everything. |
| limit | 100 | 1..500 |
| offset | 0 | ≥ 0 |
curl -H "Authorization: Bearer tkd_xxx" \
"https://taskid.app/v1/api/lists/6f8a6f4e-.../tasks?completed=0&limit=50" {
"list": { "id": "...", "name": "Work" },
"total": 42,
"limit": 50,
"offset": 0,
"tasks": [ Task, Task, ... ]
} total is the number of tasks matching the filter before applying limit/offset.
Every task (as well as every note and notification) has a files array - attachments. If nothing is attached the array is empty.
"files": [
{
"id": "9f1c...",
"name": "contract.pdf",
"size": 184320, // bytes
"url": "https://taskid.app/files/aa/bb/cc/9f1c....pdf",
"source": "upload" // 'upload' | 'link'
},
{
"id": "1a2b...",
"name": "Status page",
"size": 0, // 0 if HEAD didn't return Content-Length
"url": "https://status.example.com/incidents/42",
"source": "link"
}
] source: "upload" - a file actually uploaded to our storage. url points to taskid.app and downloads via a plain GET without headers (capability token is baked into the path). Counts against the user's file quota.source: "link" - an external HTTPS URL (our server doesn't download or store anything). url points to the third-party resource as-is. Doesn't count against the quota; size may be 0 if the resource server didn't return Content-Length in the HEAD response on attach./v1/api/lists/:id/tasksCreates a task in the given list.
| Field | Type | Description |
|---|---|---|
| title | string * | Task title. Required. |
| note | string | null | Note (multi-line text). |
| due_at | string | null | ISO-8601 UTC, the deadline timestamp. |
| due_has_time | boolean | "Date has time" flag. If false, only the date is shown in the UI. |
| flagged | boolean | "Important" flag. Defaults to false. |
| priority | integer | 0 (none), 1 (low), 2 (med), 3 (high). Defaults to 0. |
| parent_id | UUID | null | UUID of a parent task - the new task is then created as its subtask. The parent must be in the same list and must not itself be a subtask (single-level hierarchy). To attach an already existing task to another, see POST /v1/api/tasks/:id/attach. |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Call the doctor",
"due_at": "2026-04-20T08:00:00Z",
"due_has_time": true,
"flagged": true,
"priority": 2
}' \
https://taskid.app/v1/api/lists/LIST_ID/tasks curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "title": "Buy milk", "parent_id": "PARENT_TASK_UUID" }' \
https://taskid.app/v1/api/lists/LIST_ID/tasks {
"task": {
"id": "3c6b...-...-...",
"list_id": "6f8a6f4e-...",
"title": "Call the doctor",
"note": null,
"due_at": "2026-04-20T08:00:00Z",
"due_has_time": true,
"completed_at": null,
"flagged": true,
"priority": 2,
"sort_order": 12000,
"files": [],
"version": "2026-04-18T12:34:56Z",
"updated_at": "2026-04-18T12:34:56Z"
}
}POST /v1/api/lists/:id/tasks doesn't attach files. Do it in two steps: 1) create the task, 2) upload files via POST /v1/api/files and attach them with POST /v1/api/tasks/:id/files./v1/api/tasks/:idReturns a single task by its identifier.
curl -H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/tasks/TASK_ID { "task": Task }404 if the task is not found or belongs to a list inaccessible to the token.
/v1/api/tasks/:idPartial update: only the fields you want to change need to be present. The rest of the task fields stay as they are.
client_updated_at wins.| Field | Type | Description |
|---|---|---|
| title | string | Title. Empty string is not allowed. |
| note | string | null | Note. null clears it. |
| due_at | string | null | ISO-8601 UTC or null to clear the date. |
| due_has_time | boolean | Whether to take the time into account. |
| completed | boolean | true → completed_at = now, false → clear. |
| flagged | boolean | "Important" flag. |
| priority | integer | 0, 1, 2 or 3. |
| in_my_day | boolean | true adds the task to "My Day" for today, false removes it. |
curl -X PATCH \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "title": "New name", "flagged": true }' \
https://taskid.app/v1/api/tasks/TASK_ID /v1/api/tasks/:idSoft delete: the task stays in the database with deleted_at set - this is required for correct sync with clients. For the user, the task disappears from every view.
curl -X DELETE \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/tasks/TASK_ID /v1/api/tasks/:id/completeA convenient alias for the common case: sets completed_at = now. No request body needed. Idempotent: an already-completed task stays as it is.
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/tasks/TASK_ID/complete { "task": Task }/v1/api/tasks/:id/reopenClears the completion flag: completed_at = null. Idempotent.
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/tasks/TASK_ID/reopen { "task": Task }/v1/api/tasks/:id/attachMakes the existing task :id a subtask of the task identified by parent_id, or - if parent_id: null - detaches it from its parent (back to a top-level task). The task stays in the same list.
{
"parent_id": UUID | null // null - detach
}:id must not have subtasks of its own;curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "parent_id": "PARENT_TASK_ID" }' \
https://taskid.app/v1/api/tasks/CHILD_TASK_ID/attach curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "parent_id": null }' \
https://taskid.app/v1/api/tasks/CHILD_TASK_ID/attach { "task": Task }/v1/api/tasks/:id/filesAttaches (a) previously uploaded files by id and/or (b) external HTTPS links to a task. At least one of the two arrays must be non-empty; you can send both at once.
Files: upload them to the server first - see "Upload a file" - and save the resulting id. The server pulls the name/size/download URL from the database. Links: just an external URL (image, dashboard, log) - our server doesn't download or cache anything, the size/MIME is best-effort via a HEAD request.
| Field | Type | Description |
|---|---|---|
| file_ids | UUID[] | Array of previously uploaded file ids. Each id is the result of POST /v1/api/files. The files must belong to the calling user. Optional if links is provided. |
| links | {url, name?}[] | Array of external links. Each has a required url field (http/https) and an optional name. If the name isn't provided the server takes it from the Content-Disposition HEAD response or from the last URL segment. Optional if file_ids is provided. |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{
"file_ids": ["9f1c-...", "5b2e-..."],
"links": [
{ "url": "https://grafana.example.com/d/api", "name": "Dashboard" },
{ "url": "https://status.example.com/incidents/42" }
]
}' \
https://taskid.app/v1/api/tasks/TASK_ID/files The full updated task with the attached files and links already in the files array (see "Data types" - one unified format with a source marker):
{
"task": {
"id": "TASK_ID",
"title": "Contractor agreement",
"note": null,
"files": [
{
"id": "9f1c-...",
"name": "contract.pdf",
"size": 184320,
"url": "https://taskid.app/files/aa/bb/cc/9f1c....pdf",
"source": "upload"
},
{
"id": "1a2b-...",
"name": "Dashboard",
"size": 0,
"url": "https://grafana.example.com/d/api",
"source": "link"
}
],
... // remaining task fields - see "Data types"
}
}Idempotent over file_ids - if the file is already attached, calling again leaves it as is. For links there's no url deduplication: you can intentionally attach the same URL twice with different names, each link gets its own id.
Both arrays empty - 400. At least one must contain elements.
Links don't count against the file quota - they have no uploaded content. Only source: "upload" files do.
/v1/api/tasks/:id/files/:fileIdRemoves a file or link from the task's files array. :fileId is the value of the attachment's id field (the same for upload and link, distinguished by source).
If the detached source: "upload" file was uploaded by you, it's also marked for deletion and physically removed shortly after - the quota is freed immediately. If another participant in a shared list uploaded the file, for you it simply disappears from the task; the original owner stays. For source: "link" nothing is physically deleted - the link just stops being attached.
curl -X DELETE \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/tasks/TASK_ID/files/FILE_ID The full updated task - the file is no longer in the files array:
{
"task": {
"id": "TASK_ID",
"title": "Contractor agreement",
"files": [], // or an array with the remaining files
...
}
} If no such file is attached to the task (or it was already detached) - 404 is returned.
/v1/api/lists/:id/infoNotes are a separate entity inside a list: title and text only, no date, importance or completion status. They don't show up in task endpoints or system views.
limit - 1..500, default 100offset - which note to start from, default 0curl -H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/lists/LIST_ID/info {
"list": { "id": UUID, "name": string },
"total": number,
"limit": number,
"offset": number,
"records": InfoRecord[]
}Notes have the same files array as tasks: id, name, size, url (absolute, no Authorization required). Detached/deleted files are not returned. To attach/detach a file - see "Attach files to a note" and "Detach a file from a note".
/v1/api/lists/:id/info| Field | Type | Description |
|---|---|---|
| title | string * | Note title. Required, non-empty. |
| note | string | null | Multi-line note text. Optional. This is the only content field besides the title - notes have no content, type, date, importance or completion status fields. |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{ "title": "Wi-Fi password", "note": "Secret1234" }' \
https://taskid.app/v1/api/lists/LIST_ID/info {
"record": {
"id": "INFO_ID",
"list_id": "LIST_ID",
"title": "Wi-Fi password",
"note": "Secret1234",
"sort_order": 12000,
"files": [],
"version": "2026-04-18T12:34:56Z",
"updated_at": "2026-04-18T12:34:56Z"
}
}POST /v1/api/lists/:id/info doesn't attach files. Do it in two steps: 1) create the note, 2) upload files via POST /v1/api/files and attach them with POST /v1/api/info/:id/files./v1/api/info/:id{ "record": InfoRecord }/v1/api/info/:id| Field | Type | Description |
|---|---|---|
| title | string | New title. Empty string is not allowed. |
| note | string | null | Note text. null clears it. |
{ "record": InfoRecord } // the full note after the changes The field structure is in the "Data types" section.
/v1/api/info/:idSoft delete - same semantics as for tasks.
/v1/api/info/:id/filesAttaches uploaded files and/or external HTTPS links to a note. Semantics and contract are identical to "Attach files and links to a task": takes file_ids and links (at least one non-empty), responds with the updated note with the files field.
{
"file_ids": ["UUID", ...], // optional
"links": [{ "url": "...", "name": "..." }, ...] // optional
}curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{
"file_ids": ["9f1c-..."],
"links": [{ "url": "https://wiki.example.com/wifi", "name": "Wiki" }]
}' \
https://taskid.app/v1/api/info/INFO_ID/files The full updated note - the attached files and links are already visible in the files array:
{
"record": {
"id": "INFO_ID",
"title": "Wi-Fi password",
"note": "Secret1234",
"files": [
{
"id": "9f1c-...",
"name": "router-photo.jpg",
"size": 92210,
"url": "https://taskid.app/files/aa/bb/cc/9f1c....jpg",
"source": "upload"
},
{
"id": "1a2b-...",
"name": "Wiki",
"size": 0,
"url": "https://wiki.example.com/wifi",
"source": "link"
}
],
...
}
}/v1/api/info/:id/files/:fileIdRemoves a file or link from the note's files array. Behavior and conditions - see "Detach a file/link from a task": for source: "upload" the quota is freed, for source: "link" nothing is physically removed.
curl -X DELETE \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/info/INFO_ID/files/FILE_ID The full updated note - this file is no longer in the files array:
{
"record": {
"id": "INFO_ID",
"title": "Wi-Fi password",
"files": [], // or the remaining files
...
}
} If no such file is attached to the note - 404 is returned.
/v1/api/notificationsCreates a "notification" record and sends a visible push banner with the title and text to the user's devices. A drop-in replacement for a Telegram bot when delivering monitoring alerts, server events and any other external messages that need to land on a phone quickly.
The notification is physically stored in the same table as tasks and notes but has its own type (kind=2). On the client it shows up in the system "Notifications" list as well as in the specified user list. Any notification can be turned into a task with a single tap.
| Header | Description |
|---|---|
| Authorization | Bearer tkd_... with scope=write_notifications. |
| Content-Type | application/json |
| Idempotency-Key | Optional. If the integration retries on network failures, pass the same key - a repeated request will return the already-created notification with status 200, without a duplicate. The key is kept for 24 hours. |
| Field | Type | Description |
|---|---|---|
| title | string * | Notification title. Required, non-empty. Shown as the bold line in the push banner and in the list. |
| message | string | null | Notification text. Any URLs inside are rendered clickable by the client - you can drop links to a dashboard, ticket or log here. Optional. |
| list_id | string (uuid) | null | UUID of the list to attach the notification to. If omitted, the notification goes to "Inbox" (no list). For tokens with restricted list access this field is required. |
| priority | integer 0..3 | Severity. The client uses it for the icon/color: 0=info, 1=low, 2=warn, 3=error. Defaults to 0. |
| file_ids | UUID[] | Optional. Attach previously uploaded files to the created notification. See "Upload a file". Requires the token to also have scope=write (over files), but this specific POST is also accepted with scope=write_notifications when the array is empty/missing. |
| links | {url, name?}[] | Optional. Attach external HTTPS links (dashboard, log, screenshot). Don't count against the file quota. Format same as in "Attach files and links to a task". |
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: alert-12345" \
-d '{
"title": "Prod is down",
"message": "503 on api.example.com",
"priority": 3,
"links": [
{ "url": "https://grafana.example.com/d/api", "name": "Dashboard" },
{ "url": "https://status.example.com/incidents/42" }
]
}' \
https://taskid.app/v1/api/notifications {
"notification": {
"id": "NOTIF_ID",
"list_id": null,
"title": "Prod is down",
"note": "503 on api.example.com",
"priority": 3,
"completed_at": null,
"sort_order": 12000,
"files": [
{
"id": "1a2b-...",
"name": "Dashboard",
"size": 0,
"url": "https://grafana.example.com/d/api",
"source": "link"
}
],
"version": "2026-04-18T12:34:56Z",
"updated_at": "2026-04-18T12:34:56Z",
"date_create": "2026-04-18T12:34:56Z"
}
} HTTP 201 on creation. If the request is repeated with the same Idempotency-Key - HTTP 200 with the same body (no new record is created).
Retry-After header - integrate exponential backoff. The limit protects against a flood (a broken monitor → thousands of alerts a minute)./v1/api/notifications/:id/filesAdds files and/or external links to an already-existing notification. Useful when the integration sends an alert with the first request (the text arrives on the phone instantly) and uploads screenshots/dumps/dashboard links right after, without waiting for the upload to finish.
Semantics and request body are identical to "Attach files and links to a task". Returns the updated notification (a notification object, not task).
Not to be confused with write_notifications - that one only allows creating notifications (POST /notifications). Attaching files needs full write.
{
"file_ids": ["UUID", ...], // optional
"links": [{ "url": "...", "name": "..." }, ...] // optional
}curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-H "Content-Type: application/json" \
-d '{
"links": [
{ "url": "https://logs.example.com/alert/12345", "name": "Incident logs" }
]
}' \
https://taskid.app/v1/api/notifications/NOTIF_ID/files /v1/api/notifications/:id/files/:fileIdRemoves a file or link from the notification's files array. Behavior and conditions - see "Detach a file/link from a task": for source: "upload" the quota is freed, for source: "link" nothing is physically removed.
curl -X DELETE \
-H "Authorization: Bearer tkd_xxx" \
https://taskid.app/v1/api/notifications/NOTIF_ID/files/FILE_ID /v1/api/filesUploads one or more files to the server. The endpoint doesn't attach anything to tasks/notes/notifications on its own - it only returns an id that you can later use to attach the file via /v1/api/tasks/:id/files, /v1/api/info/:id/files or /v1/api/notifications/:id/files.
If your content is already available via an HTTPS URL (an image on a CDN, a dashboard link, a screenshot in S3) you don't need to upload it to us. Use the links field in the attach endpoints - the URL is stored as-is and the file quota is not touched.
multipart/form-data. The form field is files (multiple values allowed) or file (a single one). Both are accepted.
curl -X POST \
-H "Authorization: Bearer tkd_xxx" \
-F "files=@/path/to/contract.pdf" \
-F "files=@/path/to/photo.jpg" \
https://taskid.app/v1/api/files {
"files": [
{ "id": "9f1c-...", "name": "contract.pdf", "size": 184320 },
{ "id": "5b2e-...", "name": "photo.jpg", "size": 92210 }
]
} No download URL is returned at this step - you'll only need it once the file is attached to a task or note; there it comes back as an absolute URL inside the files array.
400 - body is not multipart or no files / empty file.413 - maximum request or single-file size exceeded.507 - user's storage quota exceeded.{
"id": UUID,
"parent_id": UUID | null, // UUID of the group this list belongs to
"name": string,
"color": string | null, // HEX or theme token name
"icon": string | null, // SF Symbol
"archived": boolean,
"is_owner": boolean, // you own the list
"is_shared": boolean // the list has members
} {
"id": UUID,
"name": string,
"color": string | null,
"icon": string | null,
"archived": boolean
}{
"id": UUID,
"list_id": UUID | null,
"parent_id": UUID | null, // for subtasks
"title": string,
"note": string | null,
"due_at": string | null, // ISO-8601 UTC
"due_has_time": boolean,
"completed_at": string | null, // ISO-8601 UTC
"flagged": boolean,
"priority": 0 | 1 | 2 | 3,
"rrule_freq": 0 | 1 | 2 | 3 | 4 | 5, // 0=none, HOURLY/DAILY/WEEKLY/MONTHLY/YEARLY
"rrule_interval": number, // >=1
"rrule_byday": number, // bitmask Mon=1..Sun=64
"rrule_bymonth": number, // bitmask Jan=1..Dec=2048
"rrule_bysetpos": number, // 1..4 or -1, 0=unset
"rrule_end_kind": 0 | 1 | 2, // 0=never, 1=until date, 2=after N
"rrule_until": string | null, // ISO-8601 UTC
"rrule_count": number,
"rrule_done": number,
"rrule_anchor": 0 | 1, // 0=schedule, 1=completion
"in_my_day": boolean,
"in_my_day_date": string | null, // YYYY-MM-DD
"sort_order": number,
"collapsed": 0 | 1, // 1 = subtasks collapsed
"files": FileRef[], // see "Attached files"
"version": string, // ISO-8601 UTC, server-updated
"updated_at": string, // ISO-8601 UTC
"date_create": string, // ISO-8601 UTC
"completed_user_id": UUID | null, // who closed it (relevant for shared lists)
"deleted_user_id": UUID | null // who deleted it
}{
"id": UUID,
"list_id": UUID, // always attached to a specific list
"title": string,
"note": string | null,
"sort_order": number,
"files": FileRef[], // see "Attached files"
"version": string, // ISO-8601 UTC
"updated_at": string // ISO-8601 UTC
} {
"id": UUID,
"name": string, // original file name
"size": number, // size in bytes
"url": string // absolute URL (https://taskid.app/files/...)
} content, type, deadline, completion status, flags, priority or "My Day" fields - by design. The content lives only in title and note. Notes don't show up in task endpoints or system views.