Plan · Tasks
Create, read, update, move, archive and restore tasks, one at a time or in bulk, plus relations, labels, participants and subscriptions. Part of the Dailybot Plan API (Beta).
On this page
Beta
Plan is in beta. Everything under /plan in the web app, the CLI and agent skill commands for projects, goals, boards and tasks, and the /v1/plan/ public API may change before general availability. Want to try it with your team? Write to [email protected].
List tasks on one board (alias of `GET /v1/plan/tasks/?board=`)
Convenience alias for clients that nest under the board URL. Same paginated Task envelope and shared filter grammar as GET /v1/plan/tasks/?board={board_id}. The path board_id wins over a conflicting board= query parameter.
Prefer this or ?board= for flat lists; use GET …/boards/{id}/board/ for the denser snapshot UI.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| board_id | string | Required | The board's uuid. |
Query parameters
Pagination
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | 1-based page number. |
| page_size | integer | Optional | Rows per page. Default 50, maximum 100. Out-of-range values are clamped, never rejected: asking for 500 returns 100. |
| limit | integer | Optional | Alias for page_size, translated server-side. |
| offset | integer | Optional | Alias translated to page server-side. |
Filters
| Name | Type | Required | Description |
|---|---|---|---|
| search | string | Optional | Matches title and key. Longer than 256 characters is 400 search_query_too_long, not truncated. q is an alias. |
| key_prefix | string | Optional | Select the tasks of every board a key has ever named, retired keys included: ?key_prefix=ENG. An unknown prefix returns an empty list. |
| state | array | Optional | Repeatable; values are OR-ed. Each value is either a workflow-state uuid or one of two lifecycle tokens:
- open - the state categories that are not terminal: backlog, todo, in_progress.
- done - the terminal categories: done, canceled.
The tokens are decided by state.category alone and never consult completed_at, so a client that classifies rows by the category on the state chip agrees with this filter by construction.
Mixing is allowed: a uuid and a token in the same request are OR-ed like any other repeated value. Any other value is 400 invalid_filter_value with extra.parameter: "state" - including overdue, which is not a lifecycle state. Overdue is a due-date question: see due_before. |
| category | array | Optional | The five fixed state categories. There is no blocked category — blocked-ness is a relation; use blocked=true. |
| owner | array | Optional | A user uuid, me, or unowned. Repeatable; values are OR-ed, tokens included: owner=me&owner=unowned returns your tasks and the unowned ones. me with an agent or organization key is 400 actor_required. |
| label | array | Optional | Label uuids — v4 only, at most 50, matching the shared label filter's existing cap. A non-v4 value is 400 invalid_label_filter. |
| priority | array | Optional | 1=urgent, 2=high, 3=medium, 4=low, 5=none. Repeatable. |
| parent | string | Optional | A parent task uuid, or none for top-level tasks only. parent_task is accepted as an alias of this parameter (same value). Sending both with conflicting values is 400 invalid_filter_value. |
| parent_task | string | Optional | Alias of parent — preferred by some Web clients. Same grammar (uuid or none). Do not send both with different values. |
| blocked | boolean | Optional | Derived from relations, not from a status. This is the query the product answers with a link rather than a state.
blocked=true means a live blocker: a blocks relation whose source task is neither archived nor in a terminal category. A blocker that is itself done or canceled blocks nothing and does not match.
Orthogonal to lifecycle. A finished task can still carry a live blocker, so blocked=true alone returns terminal rows too. Work a person can act on is blocked=true&state=open — that combination is what reproduces the blocked tile on GET /v1/plan/pulse/. |
| goal | string | Optional | Repeatable. Matches a task's own goal, or the goal it inherits from its project when it has none, the same rule every progress roll-up uses. |
| team | string | Optional | Repeatable. The board's team. It narrows what you see and never widens it. |
| participant | string | Optional | Repeatable. Somebody on the card, owner or not. |
| created_by | string | Optional | Repeatable. Who opened the card. |
| estimate_min | integer | Optional | Minimum estimate, inclusive, in the units stored on the task (no conversion from the board's scale). |
| estimate_max | integer | Optional | Maximum estimate, inclusive, in the units stored on the task (no conversion from the board's scale). |
Dates
| Name | Type | Required | Description |
|---|---|---|---|
| due_before | string | Optional | Inclusive. Alone, this means overdue or due by that date - it does not exclude work that is already finished.
Overdue is spelled due_before=<today>&state=open. That pairing is the supported spelling, it is what reproduces the overdue tile on GET /v1/plan/pulse/, and there is deliberately no state=overdue sugar: state is a lifecycle dimension and overdue is a date one, so a single spelling keeps the two from drifting. state=overdue answers 400 invalid_filter_value, which is evidence about that spelling and not about the capability. |
| due_after | string | Optional | Inclusive. |
| start_after | string | Optional | A date (YYYY-MM-DD): tasks whose start_date is on or after it, inclusive. A bad value is 400 invalid_filter_value. |
| start_before | string | Optional | A date (YYYY-MM-DD): tasks whose start_date is on or before it, inclusive. A bad value is 400 invalid_filter_value. |
| completed_after | string | Optional | A date (YYYY-MM-DD): tasks completed on or after it, inclusive (the date of completed_at). A bad value is 400 invalid_filter_value. |
| completed_before | string | Optional | A date (YYYY-MM-DD): tasks completed on or before it, inclusive (the date of completed_at). A bad value is 400 invalid_filter_value. |
| has_due_date | boolean | Optional | false is the planner's first question: what is not scheduled. |
| has_start_date | boolean | Optional | true keeps tasks with a start_date; false keeps tasks without one. |
| has_dates | boolean | Optional | Both scheduling edges at once. has_dates=false means neither a start date nor a due date (the unscheduled tray). has_dates=true means at least one, which is not the same as has_due_date=true. |
| updated_since | string | Optional | A timestamp filter on this paginated list: it returns {count, next, previous, results}, never a cursor. For a change feed use the board delta endpoint. |
| start_date | string | Optional | Created-at window start. What the CLI's --since produces. |
| end_date | string | Optional | Created-at window end. What the CLI's --until produces. |
Archived rows
| Name | Type | Required | Description |
|---|---|---|---|
| is_archived | boolean | Optional | true returns only archived rows; false (the default) only live ones. Archive is the delete, so archived rows stay readable. |
| include_archived | boolean | Optional | Include archived rows alongside live ones. Distinct from is_archived, which selects one set or the other: include_archived=true is the union. Lists return live rows unless you opt in. |
Sorting & expansion
| Name | Type | Required | Description |
|---|---|---|---|
| sort | string | Optional | One field, optionally --prefixed. Every ordering appends a stable internal tiebreak so a row cannot appear on two pages. An unsupported value is 400 invalid_sort, never a silent fallback. |
Task object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| key | string | Required | Human-readable key KEY-n, for example ENG-142. Retired keys keep resolving. |
| title | string | Required | The task's title. Max 255 characters. |
| description | string | null | Optional | Free-form description. |
| board | uuid | Optional | The board. |
| state | WorkflowState | Required | The task's workflow state (its column). See WorkflowState. |
| priority | integer | Optional | 1 urgent, 2 high, 3 medium, 4 low, 5 none. From 1 to 5. |
| estimate | integer | null | Optional | Estimate on the board's scale. |
| owner | UserRef | null | Optional | The person accountable for the task. See UserRef. |
| executor | ActorRef | null | Optional | The actor doing the work, when different from the owner (for example an agent). See ActorRef. |
| executors | object[] | Optional | Every agent that has executed a write on this task on someone's behalf, newest first: {uuid, name, username, avatar, first_at, last_at}. Separate from executor, which stays the current ball-holder. Only on task detail and single-task write responses; omitted on list rows. |
| participant_count | integer | Optional | Number of participants. |
| start_date | date | null | Optional | Planned start date. |
| due_date | date | null | Optional | Due date. |
| milestone | null | {uuid, name, date} | Optional | The milestone this task counts toward. All fields are always present. |
| parent_task | null | {uuid, key, title} | Optional | The parent task, for a sub-task. One level of nesting only. All fields are always present. |
| subtask_count | integer | Optional | Number of sub-tasks. |
| subtask_done_count | integer | Optional | Number of finished sub-tasks. |
| attachment_count | integer | Optional | Number of attachments. |
| open_blocker_count | integer | Optional | Number of live blockers. |
| labels | array<Label> | Optional | Organization labels on the task. See Label. |
| rank | string | null | Optional | Opaque order within the column. Never compute it: move with after / before. |
| blocked | boolean | Optional | Tasks with a live blocker. |
| blocked_since | date-time | null | Optional | When the task became blocked. |
| completed_at | date-time | null | Optional | When it was completed, or null. |
| is_archived | boolean | Required | Whether the row is archived. Archive is the delete: archived rows stay readable and restorable. |
| subscribed | boolean | Optional | Whether you watch this task. |
| version | integer | Required | Increments on every write. Send it back as If-Match to refuse a stale update. |
| created_by | ActorRef | null | Optional | Who created the row. See ActorRef. |
| created_at | date-time | Optional | When the row was created. |
| updated_at | date-time | Optional | When the row last changed. |
WorkflowState object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| name | string | Required | Display name. Max 48 characters. |
| category | enum | Required | One of the five fixed categories. It never changes after create. One of backlog, todo, in_progress, done, canceled. |
| position | integer | Required | Column position, left to right. Minimum 0. |
| color | string | Optional | Display color (hex). |
| is_default | boolean | Optional | Whether new tasks land in this state by default. |
| is_archived | boolean | Optional | Whether the row is archived. Archive is the delete: archived rows stay readable and restorable. |
| task_count | integer | Optional | Number of live tasks. |
UserRef object
ActorRef object
Label object
Response
| Name | Type | Required | Description |
|---|---|---|---|
| count | integer | Required | Total number of rows. |
| next | uri | Required | URL of the next page, or null. |
| previous | uri | Required | URL of the previous page, or null. |
| results | array<Task> | Required | The rows on this page. See Task. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS "https://api.dailybot.com/v1/plan/boards/00000000-0000-4000-8000-000000000002/tasks/?state=open" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan board tasks 00000000-0000-4000-8000-000000000002 --page 2{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000005",
"key": "ENG-142",
"title": "Ship the delta feed",
"description": null,
"board": "00000000-0000-4000-8000-000000000002",
"state": {
"uuid": "00000000-0000-4000-8000-000000000003",
"name": "In Progress",
"category": "in_progress",
"position": 2
},
"priority": 2,
"estimate": 3,
"owner": {
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executor": null,
"participant_count": 1,
"start_date": "2026-09-28",
"due_date": "2026-10-15",
"milestone": null,
"parent_task": null,
"subtask_count": 1,
"subtask_done_count": 1,
"attachment_count": 1,
"open_blocker_count": 1,
"labels": [],
"rank": "aU",
"blocked": false,
"blocked_since": null,
"completed_at": null,
"is_archived": false,
"subscribed": true,
"version": 7,
"created_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"created_at": "2026-09-25T10:14:02Z",
"updated_at": "2026-09-25T10:14:02Z"
}
]
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Create a task on this board (alias of `POST /v1/plan/tasks/`)
Same create semantics as POST /v1/plan/tasks/ with the board taken from the path (board in the body is optional and overridden).
Idempotency-Key is optional and recommended.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| board_id | string | Required | The board's uuid. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| milestone | uuid | null | Optional | Not accepted on create yet (501 not_implemented): set the milestone with PATCH after creating the task. |
| title | string | Required | The task's title. Max 255 characters. |
| description | string | null | Optional | Free-form description. Max 50000 characters. |
| priority | integer | Optional | 1 urgent, 2 high, 3 medium, 4 low, 5 none. From 1 to 5. |
| estimate | integer | null | Optional | Estimate on the board's scale. |
| owner | string | null | Optional | The owner's user uuid. The person must already be able to see the board (400 participant_cannot_access_board otherwise). |
| start_date | date | null | Optional | Planned start date. |
| due_date | date | null | Optional | Due date. |
| parent_task | uuid | null | Optional | The parent task, for a sub-task. One level of nesting only. |
| label_uuids | array | Optional | Label uuids to set on the task. Items: uuid. |
| after | uuid | null | Optional | Place the pin just below this pin. |
| before | uuid | null | Optional | Place the pin just above this pin. |
| version | integer | Optional | The version you loaded. A stale value is 409 version_conflict. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 409 | Conflict. The response `code` says which (for example `version_conflict`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/boards/00000000-0000-4000-8000-000000000002/tasks/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"title": "Ship the delta feed",
"priority": 2
}'dailybot plan task create -t "Ship the delta feed" -b 00000000-0000-4000-8000-000000000002Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
List tasks with the shared filter grammar
Multi-value semantics are OR within a parameter and AND across parameters. An unknown parameter is ignored; an unparseable value of a known parameter is 400 invalid_filter_value.
Query parameters
Pagination
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | 1-based page number. |
| page_size | integer | Optional | Rows per page. Default 50, maximum 100. Out-of-range values are clamped, never rejected: asking for 500 returns 100. |
| limit | integer | Optional | Alias for page_size, translated server-side. |
| offset | integer | Optional | Alias translated to page server-side. |
Filters
| Name | Type | Required | Description |
|---|---|---|---|
| search | string | Optional | Matches title and key. Longer than 256 characters is 400 search_query_too_long, not truncated. q is an alias. |
| board | array | Optional | Board uuids or board keys (ENG). Repeatable; values are OR-ed. Keys resolve within your organization only; a key that names no board of yours contributes nothing and never returns a 404. Retired keys keep resolving. |
| key_prefix | string | Optional | Select the tasks of every board a key has ever named, retired keys included: ?key_prefix=ENG. An unknown prefix returns an empty list. |
| project | array | Optional | Project uuids. Repeatable; values are OR-ed. |
| state | array | Optional | Repeatable; values are OR-ed. Each value is either a workflow-state uuid or one of two lifecycle tokens:
- open - the state categories that are not terminal: backlog, todo, in_progress.
- done - the terminal categories: done, canceled.
The tokens are decided by state.category alone and never consult completed_at, so a client that classifies rows by the category on the state chip agrees with this filter by construction.
Mixing is allowed: a uuid and a token in the same request are OR-ed like any other repeated value. Any other value is 400 invalid_filter_value with extra.parameter: "state" - including overdue, which is not a lifecycle state. Overdue is a due-date question: see due_before. |
| category | array | Optional | The five fixed state categories. There is no blocked category — blocked-ness is a relation; use blocked=true. |
| owner | array | Optional | A user uuid, me, or unowned. Repeatable; values are OR-ed, tokens included: owner=me&owner=unowned returns your tasks and the unowned ones. me with an agent or organization key is 400 actor_required. |
| label | array | Optional | Label uuids — v4 only, at most 50, matching the shared label filter's existing cap. A non-v4 value is 400 invalid_label_filter. |
| priority | array | Optional | 1=urgent, 2=high, 3=medium, 4=low, 5=none. Repeatable. |
| parent | string | Optional | A parent task uuid, or none for top-level tasks only. parent_task is accepted as an alias of this parameter (same value). Sending both with conflicting values is 400 invalid_filter_value. |
| parent_task | string | Optional | Alias of parent — preferred by some Web clients. Same grammar (uuid or none). Do not send both with different values. |
| blocked | boolean | Optional | Derived from relations, not from a status. This is the query the product answers with a link rather than a state.
blocked=true means a live blocker: a blocks relation whose source task is neither archived nor in a terminal category. A blocker that is itself done or canceled blocks nothing and does not match.
Orthogonal to lifecycle. A finished task can still carry a live blocker, so blocked=true alone returns terminal rows too. Work a person can act on is blocked=true&state=open — that combination is what reproduces the blocked tile on GET /v1/plan/pulse/. |
| goal | string | Optional | Repeatable. Matches a task's own goal, or the goal it inherits from its project when it has none, the same rule every progress roll-up uses. |
| team | string | Optional | Repeatable. The board's team. It narrows what you see and never widens it. |
| participant | string | Optional | Repeatable. Somebody on the card, owner or not. |
| created_by | string | Optional | Repeatable. Who opened the card. |
| estimate_min | integer | Optional | Minimum estimate, inclusive, in the units stored on the task (no conversion from the board's scale). |
| estimate_max | integer | Optional | Maximum estimate, inclusive, in the units stored on the task (no conversion from the board's scale). |
Dates
| Name | Type | Required | Description |
|---|---|---|---|
| due_before | string | Optional | Inclusive. Alone, this means overdue or due by that date - it does not exclude work that is already finished.
Overdue is spelled due_before=<today>&state=open. That pairing is the supported spelling, it is what reproduces the overdue tile on GET /v1/plan/pulse/, and there is deliberately no state=overdue sugar: state is a lifecycle dimension and overdue is a date one, so a single spelling keeps the two from drifting. state=overdue answers 400 invalid_filter_value, which is evidence about that spelling and not about the capability. |
| due_after | string | Optional | Inclusive. |
| start_after | string | Optional | A date (YYYY-MM-DD): tasks whose start_date is on or after it, inclusive. A bad value is 400 invalid_filter_value. |
| start_before | string | Optional | A date (YYYY-MM-DD): tasks whose start_date is on or before it, inclusive. A bad value is 400 invalid_filter_value. |
| completed_after | string | Optional | A date (YYYY-MM-DD): tasks completed on or after it, inclusive (the date of completed_at). A bad value is 400 invalid_filter_value. |
| completed_before | string | Optional | A date (YYYY-MM-DD): tasks completed on or before it, inclusive (the date of completed_at). A bad value is 400 invalid_filter_value. |
| has_due_date | boolean | Optional | false is the planner's first question: what is not scheduled. |
| has_start_date | boolean | Optional | true keeps tasks with a start_date; false keeps tasks without one. |
| has_dates | boolean | Optional | Both scheduling edges at once. has_dates=false means neither a start date nor a due date (the unscheduled tray). has_dates=true means at least one, which is not the same as has_due_date=true. |
| updated_since | string | Optional | A timestamp filter on this paginated list: it returns {count, next, previous, results}, never a cursor. For a change feed use the board delta endpoint. |
| start_date | string | Optional | Created-at window start. What the CLI's --since produces. |
| end_date | string | Optional | Created-at window end. What the CLI's --until produces. |
Archived rows
| Name | Type | Required | Description |
|---|---|---|---|
| is_archived | boolean | Optional | true returns only archived rows; false (the default) only live ones. Archive is the delete, so archived rows stay readable. |
| include_archived | boolean | Optional | Include archived rows alongside live ones. Distinct from is_archived, which selects one set or the other: include_archived=true is the union. Lists return live rows unless you opt in. |
Sorting & expansion
| Name | Type | Required | Description |
|---|---|---|---|
| sort | string | Optional | One field, optionally --prefixed. Every ordering appends a stable internal tiebreak so a row cannot appear on two pages. An unsupported value is 400 invalid_sort, never a silent fallback. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| count | integer | Required | Total number of rows. |
| next | uri | Required | URL of the next page, or null. |
| previous | uri | Required | URL of the previous page, or null. |
| results | array<Task> | Required | The rows on this page. See Task. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
curl -sS "https://api.dailybot.com/v1/plan/tasks/?board=ENG&state=open&owner=me" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task list --board ENG --state open --owner me --jsonTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Create a task
The key (ENG-143) is allocated from the board's counter and never reused, even after archive.
When owner is set, that person must already be able to see the board; otherwise the call is refused with 400 participant_cannot_access_board and nothing is written.
Placement is relative: after or before names a visible task in the target column (at most one of them); omit both to append at the end. Raw rank is never accepted.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| board | uuid | Required | The board: its uuid or its key (ENG). |
| milestone | uuid | null | Optional | Not accepted on create yet (501 not_implemented): set the milestone with PATCH after creating the task. |
| title | string | Required | The task's title. Max 255 characters. |
| description | string | null | Optional | Free-form description. Max 50000 characters. |
| priority | integer | Optional | 1 urgent, 2 high, 3 medium, 4 low, 5 none. From 1 to 5. |
| estimate | integer | null | Optional | Estimate on the board's scale. |
| owner | string | null | Optional | The owner's user uuid. The person must already be able to see the board (400 participant_cannot_access_board otherwise). |
| start_date | date | null | Optional | Planned start date. |
| due_date | date | null | Optional | Due date. |
| parent_task | uuid | null | Optional | The parent task, for a sub-task. One level of nesting only. |
| label_uuids | array | Optional | Label uuids to set on the task. Items: uuid. |
| after | uuid | null | Optional | Place the pin just below this pin. |
| before | uuid | null | Optional | Place the pin just above this pin. |
| version | integer | Optional | The version you loaded. A stale value is 409 version_conflict. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 409 | Conflict. The response `code` says which (for example `version_conflict`). |
| 422 | The request could not be applied (`column_too_large`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"board": "00000000-0000-4000-8000-000000000002",
"title": "Ship the delta feed",
"priority": 2,
"due_date": "2026-10-15"
}'dailybot plan task create -t "Ship the delta feed" -b 00000000-0000-4000-8000-000000000002 --owner me --priority 2Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Create, or apply one operation to, up to 100 tasks
Registered BEFORE the {task_id} detail route, or bulk parses as an identifier. Atomicity is per item, not per batch: the response reports each item separately and the HTTP status describes whether the batch was accepted, not whether every item succeeded. Idempotency-Key is required — a bulk move that half-applies twice is a corrupted board.
The restore operation is the batch form of POST .../tasks/{task_id}/restore/ and obeys the same rules.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| dry_run | boolean | Optional | Run the call and roll it back. Answers {operation, dry_run, reversible, consequence, affects{tasks}, items[{index, task, key, changes{field:{from,to}}}], refused[{index, code, detail}]}. No Idempotency-Key needed. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Required | Required on bulk: a batch that half-applies twice is a corrupted board. Missing is 400 idempotency_key_required. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| operation | enum | Required | The operation to apply. One of move, update, archive, restore, create, set_labels. Aliases: set_owner, set_priority, set_due_date, set_parent (→ update); delete (→ archive). |
| board | uuid | Optional | The board. Required when operation is create. |
| items | array (max 100): mutate items {task (uuid or KEY-n, required), state, after, before, owner, priority 1-5, due_date, version, label_uuids (or labels), parent_task}; create items {title (≤512, required), description, state, owner, priority, estimate, start_date, due_date, external_id} | Required | Up to 100 items. |
| position | enum | Optional | create only: where the new tasks land in each column. start puts them at the top, in item order; end at the bottom. One of start, end. Default end. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
BulkResponse object
| Name | Type | Required | Description |
|---|---|---|---|
| succeeded | integer | Required | Items that succeeded. |
| failed | integer | Required | Items that failed. |
| results | array | Required | The rows on this page. Always present: task, status. Items: {task: string, status: string, version: integer|null, code: string|null, detail: string|null, extra: object, external_id?: string, key?: string}. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | BulkResponse | Required | A BulkResponse object. |
Errors
| Status | When |
|---|---|
| 400 | Missing `Idempotency-Key` (`idempotency_key_required`), more than 100 items (`too_many_items`), or an invalid payload. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 409 | The same `Idempotency-Key` is still running (`idempotency_in_progress`) or was used with a different body (`idempotency_key_payload_mismatch`). |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/bulk/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"operation": "create",
"board": "00000000-0000-4000-8000-000000000002",
"items": [
{
"title": "Write the migration guide",
"external_id": "row-1"
},
{
"title": "Record the demo",
"external_id": "row-2"
}
]
}'dailybot plan task bulk --operation create --board 00000000-0000-4000-8000-000000000002 -f tasks.json --dry-run
dailybot plan task bulk --operation create --board 00000000-0000-4000-8000-000000000002 -f tasks.json{
"succeeded": 1,
"failed": 1,
"results": [
{
"task": "ENG-142",
"status": "ok",
"version": 8
},
{
"task": "ENG-9",
"status": "error",
"code": "version_conflict",
"detail": "This task changed since you loaded it.",
"extra": {
"current_version": 4
}
}
]
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 30 bulk calls per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Retrieve a task by uuid or by KEY-n
Address the task by uuid or by key. An archived task stays readable by anyone who can see its board; no include_archived is needed on a direct read. The ETag carries the task's version.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | Optional | Comma-separated embed tokens on task detail. Allowed: children, relations, participants, attachments, comment_count, activity, comments.
Each collection embed is the first page of the matching list endpoint (activity matches /tasks/{id}/activity/; comments matches /tasks/{id}/comments/).
Unknown tokens return 400 invalid_filter_value. An empty value (?include=) is treated as no embeds (200). Embeds do not change the task ETag (version-only). |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| If-None-Match | string | Optional | The ETag from your previous read. A match answers 304. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 304 | Not modified: the `If-None-Match` ETag you sent still matches. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS "https://api.dailybot.com/v1/plan/tasks/ENG-142/?include=relations,participants" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task get ENG-142 --jsonTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Update a task
Send If-Match with the version you loaded to detect a lost update. Without it the write is last-write-wins and still returns the new version.
Unknown body fields return 400 (never a silent 200). is_archived is not accepted on PATCH — use POST …/archive/ or POST …/restore/.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| If-Match | string | Optional | The version you loaded, as a quoted validator (or send it as the body field version). A stale value is 409 version_conflict with extra.current_version; sending both with different values is 400 version_precondition_ambiguous. Omitting it is last-write-wins. |
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| board | uuid | Optional | The board. |
| milestone | uuid | null | Optional | The milestone this task counts toward. |
| title | string | Optional | The task's title. Max 255 characters. |
| description | string | null | Optional | Free-form description. Max 50000 characters. |
| priority | integer | Optional | 1 urgent, 2 high, 3 medium, 4 low, 5 none. From 1 to 5. |
| estimate | integer | null | Optional | Estimate on the board's scale. |
| owner | string | null | Optional | The owner's user uuid. The person must already be able to see the board (400 participant_cannot_access_board otherwise). |
| start_date | date | null | Optional | Planned start date. |
| due_date | date | null | Optional | Due date. |
| parent_task | uuid | null | Optional | The parent task, for a sub-task. One level of nesting only. |
| label_uuids | array | Optional | Label uuids to set on the task. Items: uuid. |
| after | uuid | null | Optional | Place the pin just below this pin. |
| before | uuid | null | Optional | Place the pin just above this pin. |
| version | integer | Optional | The version you loaded. A stale value is 409 version_conflict. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | The task changed since you loaded it (`version_conflict`); `extra.current_version` carries the new version. |
curl -sS -X PATCH "https://api.dailybot.com/v1/plan/tasks/ENG-142/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H 'If-Match: "7"' \
-H "Content-Type: application/json" \
-d '{
"owner": "00000000-0000-4000-8000-00000000000c",
"due_date": "2026-10-22"
}'dailybot plan task update ENG-142 --priority 1 --due 2026-10-01
dailybot plan task set-owner ENG-142 meTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Archive a task (DELETE alias)
DELETE is an alias for archive — the task and its sub-tasks are archived (204). Already-archived tasks return 204 idempotently. Prefer POST …/archive/ when you need the archived body echoed. Concurrency (If-Match) is not applied on this alias; use PATCH for versioned updates before archiving if needed.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/tasks/ENG-142/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task delete ENG-142 --yes # archives the taskTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
List direct sub-tasks of a task
Paginated task cards (same shape as the task list / board snapshot). Default order is created_at (rank is column-scoped, so children in different states are not sibling-ranked). Pass ?sort=rank or ?ordering=rank when all children share a column. Unsupported sort values are 400 invalid_sort (never silently ignored). Sibling drag uses POST …/move/ with after / before. One nesting level only — grandchildren refused on write with subtask_depth_exceeded.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | 1-based page number. |
| page_size | integer | Optional | Rows per page. Default 50, maximum 100. Out-of-range values are clamped, never rejected: asking for 500 returns 100. |
| sort | string | Optional | One field, optionally --prefixed. Every ordering appends a stable internal tiebreak so a row cannot appear on two pages. An unsupported value is 400 invalid_sort, never a silent fallback. |
| ordering | string | Optional | Web alias for sort on the children list. Same allow-list and refusal semantics — unsupported values are 400 invalid_sort, never silently ignored. Do not send both parameters with conflicting values. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| count | integer | Required | Total number of rows. |
| next | uri | Required | URL of the next page, or null. |
| previous | uri | Required | URL of the previous page, or null. |
| results | array<Task> | Required | The rows on this page. See Task. |
Errors
| Status | When |
|---|---|
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS "https://api.dailybot.com/v1/plan/tasks/ENG-142/children/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task children ENG-142Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Archive a task and its sub-tasks
Archiving nulls the task's rank, so it leaves every board ordering without leaving the table. Relations and participants are kept.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| dry_run | boolean | Optional | Preview the consequence without performing it. The response has the same shape, {operation, dry_run, reversible, restore_path, consequence, affects}, but nothing is written and no event is emitted. Show consequence to a person before acting. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
DryRunPreview object
What the call answers with ?dry_run=true: the consequence, without performing it. Nothing is written and no event is emitted.
| Name | Type | Required | Description |
|---|---|---|---|
| operation | string | Required | The operation that would run. |
| dry_run | boolean | Required | Always true. |
| reversible | boolean | Required | Whether the operation can be undone. |
| restore_path | string | null | Required | The path that would undo it, or null when there is none. |
| consequence | string | Required | A sentence to show a person before acting. It states the cascade rather than summarising it. |
| affects | object | Required | What the operation would touch, as counts (integers) by kind. |
| would_refuse | boolean | Optional | Workflow state archive only: true when the real call would be refused. |
| refusal_code | string | Optional | Workflow state archive only: the error code the real call would answer with. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | DryRunPreview | Required | A Task object. With ?dry_run=true, a DryRunPreview object instead. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | Conflict. The response `code` says which (for example `version_conflict`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/archive/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task archive ENG-142 --dry-run
dailybot plan task archive ENG-142 --yesTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Duplicate a task on the same board
Creates a new task in the same column. Default include copies title, description, and labels. Emits task.created.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| include | array | Optional | What to copy. Default: title, description, labels. Items: enum title|description|labels|priority|estimate|owner|start_date|due_date. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 403 | The task is archived (`task_delete_forbidden`): restore it before duplicating it. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/duplicate/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"include": [
"title",
"description",
"labels"
]
}'dailybot plan task duplicate ENG-142 --include title --include descriptionTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Move a task to another board
Body requires board (target board uuid). Target column resolution: explicit state, or state_map from source column uuid → target column uuid, or same category on the target board. Emits task.moved (with from_board_uuid when crossing boards). Invalid mappings return 400 move_board_state_invalid.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| If-Match | string | Optional | The version you loaded, as a quoted validator (or send it as the body field version). A stale value is 409 version_conflict with extra.current_version; sending both with different values is 400 version_precondition_ambiguous. Omitting it is last-write-wins. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| board | uuid | Required | The board. |
| state | uuid | Optional | The task's workflow state (its column). |
| state_map | object | Optional | Source column uuid → target column uuid. |
| version | integer | Optional | The version you loaded. A stale value is 409 version_conflict. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | The task changed since you loaded it (`version_conflict`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/move-board/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"board": "00000000-0000-4000-8000-000000000012"
}'dailybot plan task move ENG-142 --board 00000000-0000-4000-8000-000000000012Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Move a task to a state and a position, relatively
The only way to change a task's state. The position is a neighbour, not a number, so two people dragging the same card at once both produce a valid order. At most one of after / before may be set; both null appends to the end of the column. One write, one task.moved event. Send If-Match (or version) to refuse a stale move.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| If-Match | string | Optional | The version you loaded, as a quoted validator (or send it as the body field version). A stale value is 409 version_conflict with extra.current_version; sending both with different values is 400 version_precondition_ambiguous. Omitting it is last-write-wins. |
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| state | uuid | Required | The task's workflow state (its column). |
| board | uuid | null | Optional | The board. |
| after | uuid | null | Optional | Place the pin just below this pin. |
| before | uuid | null | Optional | Place the pin just above this pin. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | The task changed since you loaded it (`version_conflict`), or a named neighbour moved away (`rank_neighbor_missing`). The response names the column's current head and tail so you can retry. |
| 422 | The request could not be applied (`column_too_large`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/move/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"state": "00000000-0000-4000-8000-000000000004",
"after": null,
"before": null
}'dailybot plan task move ENG-142 --state doneTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
A task's relations, both directions
blocked_by is not stored — it is the inverse read of blocks, so there is exactly one row per fact and the two directions cannot disagree. The direction field tells you which side you are on.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
TaskRelation object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| relation_type | enum | Required | blocks, relates_to or duplicates. New types may be added: ignore ones you do not recognise. One of blocks, relates_to, duplicates. |
| direction | enum | null | Required | outgoing when this task is the source, incoming when it is the target. One of outgoing, incoming. |
| other_task | object | Required | The task on the other side. Shape: {uuid, key, title, state_category}. |
| created_at | date-time | Optional | When the row was created. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| count | integer | Required | Total number of rows. |
| next | uri | Required | URL of the next page, or null. |
| previous | uri | Required | URL of the previous page, or null. |
| results | array<TaskRelation> | Required | The rows on this page. See TaskRelation. |
Errors
| Status | When |
|---|---|
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS "https://api.dailybot.com/v1/plan/tasks/ENG-142/relations/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task relations ENG-142 --json{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-00000000000a",
"relation_type": "blocks",
"direction": "outgoing",
"other_task": {},
"created_at": "2026-09-25T10:14:02Z"
}
]
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Link two tasks
Links this task to another one. Send relation_type (blocks, relates_to or duplicates) and target_task, a task uuid or a key like ENG-142; a task you cannot see is 404. kind and target are deprecated aliases of those two fields: sending an alias and its field with different values is 400. A link that already exists or would create a cycle is 409.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| relation_type | enum | Required | blocks, relates_to or duplicates. New types may be added: ignore ones you do not recognise. Required, or its deprecated alias kind. One of blocks, relates_to, duplicates. |
| target_task | string | Required | The other task: its uuid or a key like ENG-142. A task you cannot see is 404. Required, or its deprecated alias target. |
| kind | enum | Optional | Deprecated alias of relation_type, kept for older clients. Send relation_type instead; both with different values is 400. One of blocks, relates_to, duplicates. |
| target | string | Optional | Deprecated alias of target_task, kept for older clients. Send target_task instead; both with different values is 400. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskRelation | Required | A TaskRelation object. |
Errors
| Status | When |
|---|---|
| 400 | Missing type or target, an alias that disagrees with its field, or an invalid value. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | The link already exists (`relation_exists`) or would create a cycle (`relation_cycle`). |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/relations/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"relation_type": "blocks",
"target_task": "ENG-150"
}'dailybot plan task link ENG-142 ENG-150 --type blocksTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Unlink two tasks
Emits task.unrelated on the task event stream (not relation_removed). Activity enrichment maps it to changes[{field: related, from: …, to: null}].
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
| relation_id | string | Required | The relation's uuid. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/tasks/ENG-142/relations/00000000-0000-4000-8000-00000000000a/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task unlink ENG-142 00000000-0000-4000-8000-00000000000a --yesTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Attach, detach or replace a task's labels
Labels are the organization-wide taxonomy shared with forms and check-ins; there is no plan-only label vocabulary. At most 50 labels per task.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| mode | enum | Required | add, remove or replace. One of add, remove, replace. |
| label_uuids | array | Required | Label uuids to set on the task. Items: uuid. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| labels | array<Label> | Required | Organization labels on the task. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed, or a filter, sort or `include` value was not recognised. The response `code` says which. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/labels/batch/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "add",
"label_uuids": [
"00000000-0000-4000-8000-00000000000b"
]
}'dailybot plan task labels ENG-142 --mode add --label 00000000-0000-4000-8000-00000000000b{
"labels": [
{
"uuid": "00000000-0000-4000-8000-00000000000b",
"name": "backend",
"color": "#2563eb"
}
]
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Subscribe to task notifications (watcher role)
The only way to set the task's subscribed field (sending subscribed in a task PATCH is 400). Returns {"subscribed": true}, so no re-read is needed.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| subscribed | boolean | Required | Whether you watch this task. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/subscription/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan task watch ENG-142{
"subscribed": true
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Needs a person: call it with a login session, a CLI user token or a personal API key. An agent or organization key gets `403 insufficient_scope`.
Remove a watcher subscription
Clears the caller's watcher subscription. Returns 204 (empty body). Re-GET the task for subscribed: false, or update client state locally.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/tasks/ENG-142/subscription/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan task unwatch ENG-142Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Needs a person: call it with a login session, a CLI user token or a personal API key. An agent or organization key gets `403 insufficient_scope`.
Restore an archived task
The mirror of archive: same scope, same credentials, same idempotency. The task returns at the end of its column, because its old neighbours are gone. Restoring a live task is a no-op 200.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Task | Required | A Task object. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
| 409 | The task's board or state was archived meanwhile (`state_in_use`). The response names the state so you can pick a target. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/restore/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan task restore ENG-142Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
Who is on this card
Participants and watchers, oldest first — the order the card's people strip renders. Visible to anyone who can see the task. Participation is not an access lever: this list never widens what its members can see.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | 1-based page number. |
| page_size | integer | Optional | Rows per page. Default 50, maximum 100. Out-of-range values are clamped, never rejected: asking for 500 returns 100. |
TaskParticipant object
| Name | Type | Required | Description |
|---|---|---|---|
| member | ActorRef | Required | The person. See ActorRef. |
| role | enum | Required | Participant role. One of participant, watcher. |
| source | enum | Required | How the person came to be on the card. One of manual, creator, owner, commented, mentioned, sync. |
| is_muted | boolean | Required | Stay on the card without notifications. |
| added_by | ActorRef | null | Optional | Who added the person. See ActorRef. |
| created_at | date-time | Required | When the row was created. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| count | integer | Required | Total number of rows. |
| next | uri | Required | URL of the next page, or null. |
| previous | uri | Required | URL of the previous page, or null. |
| results | array<TaskParticipant> | Required | The rows on this page. See TaskParticipant. |
Errors
| Status | When |
|---|---|
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS "https://api.dailybot.com/v1/plan/tasks/ENG-142/participants/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan task participants list ENG-142{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"member": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"role": "participant",
"source": "manual",
"is_muted": false,
"added_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"created_at": "2026-09-25T10:14:02Z"
}
]
}Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:read`.
- Rate limit: 120 reads per minute per actor.
- Needs a person: call it with a login session, a CLI user token or a personal API key. An agent or organization key gets `403 insufficient_scope`.
Put someone on this card
Adds a participant or watcher. Adding someone already on the card returns 200 with the existing row. Adding or removing a participant emits task.participant_added with actor_is_self, so "someone added me" and "I joined" can be told apart. A watcher change emits nothing: following a task is a private preference. Muting (is_muted) keeps the person on the card.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | Optional | A key you generate for this intent. A replay with the same key and body returns the first response without a second side effect and carries Idempotency-Replayed: true. Keys are kept for 24 hours. The same key with a different body is 409 idempotency_key_payload_mismatch; a repeat while the first call is still running gets 409 idempotency_in_progress for up to 120 seconds. |
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| user_uuid | uuid | Required | The person's user uuid. |
| role | enum | Optional | Participant role. One of participant, watcher. Default participant. |
| is_muted | boolean | Optional | Stay on the card without notifications. Default false. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskParticipant | Required | A TaskParticipant object. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 403 | Authenticated but not allowed: missing scope (`insufficient_scope`, which is also what an agent or organization key gets on an operation that needs a person, and what a personal key gets when its explicit Plan scopes do not cover the endpoint) or a guest account (`guest_not_allowed`). |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/ENG-142/participants/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_uuid": "00000000-0000-4000-8000-00000000000c",
"role": "participant"
}'dailybot plan task participants add ENG-142 --user 00000000-0000-4000-8000-00000000000c --role participant
dailybot plan task mute ENG-142
dailybot plan task unmute ENG-142Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Needs a person: call it with a login session, a CLI user token or a personal API key. An agent or organization key gets `403 insufficient_scope`.
Take someone off this card
Removes the person from the card and emits task.participant_removed. Leaving is not muting: to stop notifications but stay on the card, set is_muted through the add endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
| user_uuid | string | Required | The participant's user uuid. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Errors
| Status | When |
|---|---|
| 400 | The agent name is invalid (`invalid_agent_attribution`). |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 403 | Authenticated but not allowed: missing scope (`insufficient_scope`, which is also what an agent or organization key gets on an operation that needs a person, and what a personal key gets when its explicit Plan scopes do not cover the endpoint) or a guest account (`guest_not_allowed`). |
| 404 | Not found, or not visible to you. Both cases return the same body. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/tasks/ENG-142/participants/00000000-0000-4000-8000-00000000000c/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan task participants remove ENG-142 00000000-0000-4000-8000-00000000000c --yesTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Needs a person: call it with a login session, a CLI user token or a personal API key. An agent or organization key gets `403 insufficient_scope`.
Rename a task attachment
Changes the display file name; the stored bytes do not change. Anyone who may write to the parent can rename its attachments.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| task_id | string | Required | A task uuid or its key, such as ENG-142, including a key retired by a board rename. Resolution is scoped to your organization first, so another organization's key is a 404 identical to a missing one. Numeric ids are never accepted. |
| attachment_id | uuid | Required | The attachment's uuid. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| X-Dailybot-Agent-Name | string | Optional | The name of the agent that executed this write on the person's behalf. Use it on multipart and body-less writes (DELETE, archive, restore); on JSON writes send the body field agent_name instead, which wins if both are present. Percent-encode the value as UTF-8. Control characters are stripped; a blank value means no agent. More than 128 characters, or a value that cannot be decoded, is 400 invalid_agent_attribution (never truncated). An agent-type key, which is not bound to a person, gets 400 invalid_agent_attribution if it sends it. The stamp never changes a permission answer. See Agent attribution. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| filename | string | Required | The new file name (1–255 characters). The stored bytes do not change. |
| agent_name | string | Optional | The name of the agent that executed this write on the person's behalf (max 128 characters, blank means no agent). Takes priority over the X-Dailybot-Agent-Name header. See Agent attribution. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
Errors
| Status | When |
|---|---|
| 400 | Validation failed; the response `code` says which field. `invalid_agent_attribution` means the agent name is invalid. |
| 401 | Missing, expired or malformed credential (`credential_absent`, `credential_expired`, `credential_malformed`). |
| 402 | Plan is not enabled for your organization yet (`plan_upgrade_required`). Expected during the Beta: write to [email protected]. |
| 403 | You may not write here (`insufficient_scope`), or you are a guest (`guest_not_allowed`). |
| 404 | The parent or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X PATCH "https://api.dailybot.com/v1/plan/tasks/ENG-142/attachments/00000000-0000-4000-8000-000000000009/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "spec-v2.pdf"
}'dailybot plan task attachments rename ENG-142 00000000-0000-4000-8000-000000000009 spec-v2.pdfTry it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Scope: `tasks:write`.
- Rate limit: 60 writes per minute per actor.
- Works with a login session, a CLI user token, a personal API key, or an agent or organization key. A personal key sees what its person sees; an agent or organization key acts as a system actor and sees organization-visible boards only.
This page is the reference for Plan · Tasks. Every endpoint lives under https://api.dailybot.com/v1/plan/ and answers JSON.
Authenticate with a login session or a CLI user token (Authorization: Bearer …), or with an API key (X-API-KEY). A personal API key acts as its person and can do everything that person can do in Dailybot; an agent or organization key never acts as a person and is refused on the endpoints that need one. On an endpoint, the API key badge means an agent or organization key is accepted too. See Authentication for Plan, Authentication and Errors for the rules shared by every Dailybot API.
New to Plan? Read the overview for the model: projects, boards, workflow states, keys, ordering, versions and archive.