Plan · Projects
Projects group boards and carry health, status notes, milestones, members and saved views. 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 projects
The projects you can see, as a page. Search with search, filter by dates with start_date / end_date, and bring archived projects with include_archived. include adds optional blocks to each row.
Query parameters
Sorting & expansion
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | Optional | Comma-separated roll-ups to embed. progress is the only token. Absent by default because it is an aggregate; when asked for, it is computed over the returned page. An unknown token is 400 invalid_filter_value; an empty value is a no-op. |
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. |
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. |
Dates
| Name | Type | Required | Description |
|---|---|---|---|
| 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. |
Project object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| name | string | Required | Display name. Max 120 characters. |
| slug | string | Optional | URL-friendly name. Max 48 characters. |
| description | string | null | Optional | Free-form description. |
| lead | UserRef | null | Optional | The project's lead. See UserRef. |
| goals | array | Optional | Goals this project points at. A project can serve several goals. Always present: uuid. Items: {uuid, name}. |
| goal | object | Optional | The goal, when there is exactly one. Shape: {uuid, name}|null. |
| board_count | integer | Optional | Number of live boards in the project. |
| health | enum | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| start_date | date | null | Optional | Planned start date. |
| target_date | date | null | Optional | Planned end date. |
| progress | ProjectProgress | null | Optional | Progress roll-up over the tasks you can see. See ProjectProgress. |
| is_archived | boolean | Required | Whether the row is archived. Archive is the delete: archived rows stay readable and restorable. |
| archived_at | date-time | null | Optional | When the row was archived. |
| created_at | date-time | Optional | When the row was created. |
| updated_at | date-time | Optional | When the row last changed. |
| viewer | object | Optional | What you can do with this row. Shape: {can_see_content: boolean, can_manage: boolean} (both required). |
UserRef object
ProjectProgress object
| Name | Type | Required | Description |
|---|---|---|---|
| total | integer | Required | All tasks counted. |
| completed | integer | Required | Tasks in a done or canceled state. |
| open | integer | Optional | Tasks in a backlog, todo or in_progress state. |
| blocked | integer | Optional | Tasks with a live blocker. |
| overdue | integer | Optional | Open tasks past their due date. |
| percent_complete | integer | Required | completed as a percentage of total. |
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<Project> | Required | The rows on this page. See Project. |
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]. |
| 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`). |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS "https://api.dailybot.com/v1/plan/projects/?include=progress" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project list --include progress --json{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000001",
"name": "Platform",
"slug": "platform",
"description": null,
"lead": {
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"goals": [],
"goal": {},
"board_count": 1,
"health": "on_track",
"start_date": "2026-09-28",
"target_date": "2026-10-15",
"progress": {
"total": 10,
"completed": 4,
"percent_complete": 40
},
"is_archived": false,
"archived_at": null,
"created_at": "2026-09-25T10:14:02Z",
"updated_at": "2026-09-25T10:14:02Z",
"viewer": {}
}
]
}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 project
Creates a project, the container that groups boards. Every non-guest member can call it (with a login session or a personal API key); an agent or organization key cannot. Send an Idempotency-Key to retry safely; the plan's project limit answers 402 task_projects_limit_reached.
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 |
|---|---|---|---|
| visibility | enum | Optional | org (everyone in the organization — shared workspace) or members (explicit grants only; invite with POST …/members/). Creating as members grants you. One of org, members. Default org. |
| name | string | Required | Display name. Max 120 characters. |
| description | string | null | Optional | Free-form description. Max 2000 characters. |
| lead | uuid | null | Optional | The project's lead. |
| health | enum | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| start_date | date | null | Optional | Planned start date. |
| target_date | date | null | Optional | Planned end 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) | Project | Required | A Project 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`), or the plan's project ceiling is reached (`task_projects_limit_reached`). |
| 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`). |
| 409 | Conflict. The response `code` says which (for example `version_conflict`). |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 Roadmap",
"visibility": "org",
"health": "on_track",
"target_date": "2026-12-18"
}'dailybot plan project create -n "Q4 Roadmap" --target-date 2026-12-18Try 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
Retrieve a project
One project by uuid. A project you cannot see answers 404, the same as one that does not exist.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Project | Required | A Project object. |
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/projects/00000000-0000-4000-8000-000000000001/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project get 00000000-0000-4000-8000-000000000001 --include progressTry 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 project
Changes a project's fields. Send only the fields you change. Every non-guest member can call it (with a login session or a personal API key); an agent or organization key cannot. Setting visibility to members privatizes the project and auto-grants the actor who privatizes.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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 |
|---|---|---|---|
| visibility | enum | Optional | org (everyone in the organization) or members (explicit members only). Changing org → members auto-grants the actor who privatizes. One of org, members. |
| name | string | Optional | Display name. Max 120 characters. |
| description | string | null | Optional | Free-form description. Max 2000 characters. |
| lead | uuid | null | Optional | The project's lead. |
| health | enum | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| start_date | date | null | Optional | Planned start date. |
| target_date | date | null | Optional | Planned end 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) | Project | Required | A Project 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]. |
| 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 PATCH "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"health": "at_risk"
}'dailybot plan project update 00000000-0000-4000-8000-000000000001 --health at_riskTry 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
The newest updates across every project the caller can see
The batched form of the per-project updates list, for a home screen that would otherwise call it once per project.
Returns the newest per_project updates for each visible project as one flat, paginated list; each row carries its project, so group by that field. Ordered by project name, then newest first. It is a teaser, not a history: for a full thread or an archived project, use GET /v1/plan/projects/{project_id}/updates/.
projects narrows to named projects. A project you cannot see is silently omitted rather than refused, and archived projects are excluded even when named. body_html is rendered and sanitized server-side.
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. |
| projects | array | Optional | Project uuids to narrow to. Repeatable; values are OR-ed. A project the caller cannot see, or one that is archived, contributes nothing rather than raising. More than the published maximum is 400 too_many_filter_values. |
| per_project | integer | Optional | How many updates each project contributes. Clamped to the published maximum rather than refused - this is a teaser size, not an identifier, and a home screen asking for too many should get a full page rather than an error. |
ProjectUpdate object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| project | uuid | null | Required | The project. |
| body | string | Required | Markdown as typed. Mention someone with <@DB@{uuid}>, using a uuid from the mentionables list. |
| body_html | string | Required | body rendered and sanitized by the server. Client HTML is never accepted. |
| mentions | array<ActorRef> | Optional | The people mentioned. Read them from here, never by parsing body. See ActorRef. |
| health | enum | null | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| created_by | ActorRef | null | Optional | Who created the row. See ActorRef. |
| created_at | date-time | Required | When the row was created. |
| updated_at | date-time | Optional | When the row last changed. |
| executed_by_agent | object | null | Optional | The agent that executed this person's post, beside created_by, or null for a plain human post: {uuid, name, username, avatar}. |
| provenance | enum | Optional | How the text reached us: typed, agent_authored or retrieved. A note posted through an API key, or stamped with an agent, is agent_authored. |
| edited_at | date-time | null | Optional | Null until the first edit. |
| attachments | array<TaskAttachment> | Optional | READY attachments, ordered by position, inline. Upload them with POST …/updates/{update_id}/attachments/. |
ActorRef 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<ProjectUpdate> | Required | The rows on this page. See ProjectUpdate. |
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/projects/updates/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project updates --json{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-00000000000e",
"project": "00000000-0000-4000-8000-000000000001",
"body": "Staging is green; rolling out Friday.",
"body_html": "<p>Staging is green; rolling out Friday.</p>",
"mentions": [],
"health": "on_track",
"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.
Status notes on a project, newest first
The narrative half of a roadmap: why the health is what it is, with a name and a date on it. body is the markdown as typed; body_html is rendered server-side through the same sanitizer comments use, so no client-supplied HTML is ever trusted.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
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. |
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<ProjectUpdate> | Required | The rows on this page. See ProjectUpdate. |
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]. |
| 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 "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project updates 00000000-0000-4000-8000-000000000001 --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.
Post a status note
Send body as markdown. A body_html is NOT accepted — the server renders and sanitizes it, so the allow-list is ours and there is one of them. health records what the author claimed that day and does not change Project.health.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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 |
|---|---|---|---|
| body | string | Required | Markdown. Mention someone with <@DB@{uuid}>, using a uuid from the mentionables list. |
| health | enum | null | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| 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) | ProjectUpdate | Required | A ProjectUpdate 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]. |
| 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/projects/00000000-0000-4000-8000-000000000001/updates/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Staging is green; rolling out Friday. <@DB@00000000-0000-4000-8000-00000000000c> owns the release.",
"health": "on_track"
}'dailybot plan project update-post 00000000-0000-4000-8000-000000000001 "Staging is green; rolling out Friday." --health on_trackTry 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.
Dated commitments inside a project, in date order
Each row carries task_count, annotated in the same query — a roadmap draws every marker at once, so a count per marker would be a query per row.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
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. |
| 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. |
ProjectMilestone object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| name | string | Required | Display name. |
| description | string | null | Optional | Free-form description. |
| date | date | Required | The milestone date. |
| task_count | integer | Optional | Number of live tasks. |
| attachment_count | integer | Optional | READY attachments on this milestone. Reference them from description with attachment:{uuid} markers and list them at …/milestones/{milestone_id}/attachments/. |
| is_archived | boolean | Optional | Whether the row is archived. Archive is the delete: archived rows stay readable and restorable. |
| completed_at | date-time | null | Optional | When it was completed, or null. |
| created_at | date-time | Optional | When the row was created. |
| updated_at | date-time | Optional | When the row last changed. |
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<ProjectMilestone> | Required | The rows on this page. See ProjectMilestone. |
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]. |
| 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 "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project milestones 00000000-0000-4000-8000-000000000001{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000007",
"name": "Beta launch",
"description": null,
"date": "2026-09-28",
"task_count": 12,
"is_archived": false,
"completed_at": null,
"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.
Commit to a dated moment
Adds a milestone to a project: a name, a date and an optional description. Complete it later with the complete endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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 |
|---|---|---|---|
| name | string | Required | Display name. |
| date | date | Required | The milestone date. |
| description | string | null | Optional | Free-form description. |
| 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) | ProjectMilestone | Required | A ProjectMilestone 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]. |
| 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/projects/00000000-0000-4000-8000-000000000001/milestones/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Beta launch",
"date": "2026-10-15"
}'dailybot plan project milestone-create 00000000-0000-4000-8000-000000000001 -n "Beta launch" --date 2026-10-15Try 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 or rename a milestone
Renames a milestone, moves its date or edits its description. Send only the fields you change.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone'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 |
|---|---|---|---|
| name | string | Optional | Display name. |
| date | date | Optional | The milestone date. |
| description | string | null | Optional | Free-form description. |
| 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) | ProjectMilestone | Required | A ProjectMilestone 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]. |
| 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 PATCH "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"date": "2026-10-22"
}'dailybot plan project milestone-update 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000007 --date 2026-10-22Try 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.
Retire a milestone (archives; tasks keep pointing at it)
Archives rather than hard-deletes, so tasks keep pointing at the milestone and the association is never lost. The change is recorded in the activity feed as project.milestone_deleted — read it as "retired". It is not a webhook event.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone'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]. |
| 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/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project milestone-delete 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000007 --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.
Mark a milestone complete
Completing with open tasks is allowed. Those tasks stay open; the response reports open_task_count. Reversible via …/reopen/.
?dry_run=true returns the consequence without writing.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
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) | ProjectMilestone | DryRunPreview | Required | A ProjectMilestone object. With ?dry_run=true, a DryRunPreview object instead. |
| open_task_count | integer | Optional | Tasks still open in the milestone. Completing with open tasks is allowed. |
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/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/complete/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project milestone-complete 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000007 --dry-run{
"uuid": "00000000-0000-4000-8000-000000000007",
"name": "Beta launch",
"description": null,
"date": "2026-09-28",
"task_count": 12,
"is_archived": false,
"completed_at": null,
"created_at": "2026-09-25T10:14:02Z",
"updated_at": "2026-09-25T10:14:02Z",
"open_task_count": 2
}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.
Clear milestone completion
Clears a milestone's completion, so it counts as open again.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone'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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | ProjectMilestone | Required | A ProjectMilestone 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/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/reopen/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project milestone-reopen 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000007Try 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 project, cascading to its boards and their tasks
Archive is the delete. Nothing in this API hard-deletes a project; the rows survive so identifiers, links and events keep resolving.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Project | DryRunPreview | Required | A Project 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]. |
| 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/projects/00000000-0000-4000-8000-000000000001/archive/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project archive 00000000-0000-4000-8000-000000000001 --dry-runTry 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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 project
Inverse of archive, and the reason archiving a project is no longer the one act in Plan a person cannot undo. Boards and tasks that cascaded on archive stay archived: restore walks back up, never down, because "restore everything archived at the time" cannot tell the cascade apart from a board somebody archived on purpose beforehand. Bring those back with POST …/boards/{board_id}/restore/. Restore consumes one project-creation entitlement slot (archive frees one) and answers 402 when the plan has none to give.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | Project | Required | A Project 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`), or no project slot is free (`task_projects_limit_reached`). |
| 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/projects/00000000-0000-4000-8000-000000000001/restore/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project restore 00000000-0000-4000-8000-000000000001Try 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
Every milestone the viewer may see, across projects
Every milestone you may see across projects, in one call, for a roadmap's markers. Visibility follows the projects you can open. project__in narrows that set and never widens it: an unknown uuid and another organization's uuid both return an empty result. Rows carry project as a reference.
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. |
| project__in | string | Optional | Comma-separated project uuids; at most 50. Narrows the visible set, never widens it. |
| include_archived | string | Optional | Include retired milestones alongside live ones. |
OrganizationMilestone object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string | Required | Stable public identifier. |
| name | string | Required | Display name. |
| description | string | null | Optional | Free-form description. |
| date | string | Required | The milestone date. |
| task_count | integer | Optional | Number of live tasks. |
| attachment_count | integer | Optional | READY attachments on this milestone. Reference them from description with attachment:{uuid} markers and list them at …/milestones/{milestone_id}/attachments/. |
| is_archived | boolean | Optional | Whether the row is archived. Archive is the delete: archived rows stay readable and restorable. |
| project | object | Required | The project. A reference object. |
| created_at | string | Optional | When the row was created. |
| updated_at | string | Optional | When the row last changed. |
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<OrganizationMilestone> | Required | The rows on this page. See OrganizationMilestone. |
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]. |
| 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`). |
curl -sS "https://api.dailybot.com/v1/plan/milestones/?project__in=00000000-0000-4000-8000-000000000001" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project milestones{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000007",
"name": "Beta launch",
"description": null,
"date": "example",
"task_count": 12,
"is_archived": false,
"project": {},
"created_at": "example",
"updated_at": "example"
}
]
}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.
This person's saved views inside a project
Your saved views inside a project: named filter sets that span every board in it. Views are personal and scoped by project, so the same name can exist in two projects. Needs a person: agent and organization keys are refused; a personal API key works.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
SavedView object
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Display name. Max 64 characters. |
| view_mode | enum | Optional | How the filtered set is drawn. Reads always return board for the kanban layout. One of list, board, timeline, calendar. |
| group_by | enum | Optional | The grouping dimension. One of state, owner, priority, category. |
| sort | string | Optional | A sort key, - prefixed for descending. |
| filters | object | Required | The view's filters, in the shared task filter grammar. |
| schema_version | integer | Optional | Version of the view's stored format. |
| visibility | enum | Optional | personal (default) is yours alone. shared and board_default (the default view for that board or project) are readable by everyone who can see the board or project. Setting them needs a board manager on board views, and project oversight (an organization admin or a manager of all teams) on project views; otherwise 403 view_visibility_forbidden. One of personal, shared, board_default. |
| collapsed | object | array | string | number | boolean | Optional | Client UI state stored verbatim (which groups are collapsed). Only size and depth are validated. |
| columns | object | array | string | number | boolean | Optional | Client UI state stored verbatim (which columns are shown). Only size and depth are validated. |
| uuid | uuid | Optional | Stable public identifier. |
| scope | enum | Optional | Which container the view belongs to: board or project. Read-only. One of board, project. |
| board | uuid | null | Optional | The board's uuid when scope is board; null for a project view. Read-only. |
| owner | object | Optional | Who owns the view. Shape: {uuid, name}. |
| created_at | date-time | Optional | When the row was created. |
| updated_at | date-time | Optional | When the row last changed. |
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<SavedView> | Required | The rows on this page. See SavedView. |
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]. |
| 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. |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/views/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project views 00000000-0000-4000-8000-000000000001 --etag{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"name": "My open work",
"view_mode": "list",
"group_by": "state",
"sort": "-updated_at",
"filters": {},
"schema_version": 1,
"visibility": "personal",
"collapsed": {},
"columns": {}
}
]
}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`.
Replace this person's saved views for a project
Replaces your whole saved-view array for the project. If-Match is required, for the same reason as board views.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| If-Match | string | Required | The ETag you received from GET .../views/, quoted. Required, because this PUT replaces the whole array: without a precondition two concurrent saves silently drop one another's view. A stale validator is 412 precondition_failed; a missing one is 428 precondition_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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | array<SavedView> | Required | A JSON array of SavedView objects. |
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]. |
| 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. |
| 412 | The `If-Match` validator is stale (`precondition_failed`). Read again and retry. |
| 428 | `If-Match` is required (`precondition_required`). |
| 429 | Rate limit reached. Wait the number of seconds in `Retry-After`. |
curl -sS -X PUT "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/views/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "If-Match: $VIEWS_ETAG" \
-H "Content-Type: application/json" \
-d '[
{
"name": "Overdue",
"view_mode": "list",
"filters": {
"due_before": "2026-09-25",
"state": [
"open"
]
}
}
]'dailybot plan project view save 00000000-0000-4000-8000-000000000001 -f views.json --fetch-etag[
{
"name": "My open work",
"view_mode": "list",
"group_by": "state",
"sort": "-updated_at",
"filters": {},
"schema_version": 1,
"visibility": "personal",
"collapsed": {},
"columns": {}
}
]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`.
Members of a project
Visible to anyone who can see the project. On a members project this is the membership that grants sight of the project and its boards.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
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. |
BoardMember object
| Name | Type | Required | Description |
|---|---|---|---|
| subject_type | enum | Required | One of user, team. |
| user_uuid | uuid | null | Optional | The person's user uuid. |
| uuid | uuid | null | Optional | Stable public identifier. |
| full_name | string | Optional | — |
| name | string | Optional | Display name. |
| role | enum | null | Optional | Participant role. One of admin, member, guest. |
| team_uuid | uuid | null | Optional | A team's uuid, instead of user_uuid. It creates one live team grant: whoever joins the team later is in, and whoever leaves is out. |
| team_name | string | Optional | — |
| added_at | date-time | Required | — |
| added_by_uuid | uuid | null | Optional | — |
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<BoardMember> | Required | The rows on this page. See BoardMember. |
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/projects/00000000-0000-4000-8000-000000000001/members/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project members 00000000-0000-4000-8000-000000000001{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"subject_type": "user",
"user_uuid": "00000000-0000-4000-8000-00000000000c",
"uuid": "00000000-0000-4000-8000-00000000000c",
"full_name": "Ada L.",
"name": "Ada L.",
"role": "admin",
"team_uuid": null,
"team_name": "example",
"added_at": "2026-09-25T10:14:02Z",
"added_by_uuid": null
}
]
}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`.
Invite somebody, or a whole team, into a project
Grants one person (user_uuid) or one team (team_uuid) access to the project: send exactly one of them; both or neither is 400 invalid_filter_value. A team grant is live: whoever joins the team later is in, and whoever leaves is out. Every non-guest member can call it (with a login session or a personal API key); an agent or organization key gets 403 insufficient_scope.
Writes a project.member_added event carrying actor_is_self, so the project's members can tell an invitation from somebody letting themselves in.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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 |
|---|---|---|---|
| user_uuid | uuid | Optional | The person's user uuid. |
| team_uuid | uuid | Optional | A team's uuid, instead of user_uuid. It creates one live team grant: whoever joins the team later is in, and whoever leaves is out. |
| 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) | BoardMember | Required | A BoardMember object. |
Errors
| Status | When |
|---|---|
| 400 | Send exactly one of `user_uuid` and `team_uuid`; both or neither is `invalid_filter_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]. |
| 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/projects/00000000-0000-4000-8000-000000000001/members/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_uuid": "00000000-0000-4000-8000-00000000000c"
}'dailybot plan project member add 00000000-0000-4000-8000-000000000001 --user 00000000-0000-4000-8000-00000000000cTry 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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 somebody from a project
Removes a person's explicit grant on the project. Every non-guest member can call it (with a login session or a personal API key); an agent or organization key cannot.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| user_id | string | Required | The member'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/projects/00000000-0000-4000-8000-000000000001/members/00000000-0000-4000-8000-00000000000c/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project member remove 00000000-0000-4000-8000-000000000001 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
Inspect a project membership grant (role is read-only)
Project membership has no role column — org roles plus project visibility are the access model. Sending role returns 400. An empty PATCH returns the current grant row.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| user_id | string | Required | The member'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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | BoardMember | Required | A BoardMember 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. |
curl -sS -X PATCH "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/members/00000000-0000-4000-8000-00000000000c/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
List a project's attachments
The project's attachments, ordered by position. Anyone who can see the project can list its attachments; a project you cannot see is 404. Each url is a download link. Do not store it: keep the attachment uuid and read it again when you need the file. To show an image in the project's description, reference it as attachment:{uuid} and resolve it when you render, using the fresh url from this list.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
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. |
TaskAttachment object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| filename | string | Required | File name. |
| content_type | string | Required | MIME type. |
| size | integer | Required | Size in bytes. |
| url | string | Required | Where to download the file. |
| thumbnail_url | uri | null | Optional | Thumbnail for images. |
| width | integer | null | Optional | — |
| height | integer | null | Optional | — |
| status | enum | Required | Current status. One of pending, ready, scanning, rejected. |
| uploaded_by | ActorRef | null | Optional | Who uploaded the file. See ActorRef. |
| executed_by_agent | object | null | Optional | The agent that executed this on behalf of the person, or null when no agent was named: an object with uuid, name, username and avatar. The person in the author field is still the author; the agent is shown as the one who executed it. |
| 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<TaskAttachment> | Required | The rows on this page. See TaskAttachment. |
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 | The project or attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/attachments/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project attachments 00000000-0000-4000-8000-000000000001 --json{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "screenshot.png",
"content_type": "image/png",
"size": 1,
"url": "https://your.app/files/screenshot.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_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.
- 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.
Upload an attachment to a project
Attach a file to a project. Send multipart/form-data with the file field and an optional caption; there is no presign flow here. The limit is 5 MiB in every environment: a larger file is 400 attachment_too_large, with extra.max_size_bytes. The file type is checked from its content against the same list as task attachments (attachment_invalid_type). A project holds at most 50 attachments (attachment_limit_reached).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project'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 |
|---|---|---|---|
| file | binary | Required | The file to upload (max 5 MiB this way). |
| caption | string | Optional | Optional caption. Max 255 characters. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
Errors
| Status | When |
|---|---|
| 400 | The file is missing, too large (`attachment_too_large`, over 5 MiB), of an unsupported type (`attachment_invalid_type`), or the limit of 50 is reached (`attachment_limit_reached`). `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 | Not a non-guest member acting with a login session or a personal API key (`insufficient_scope`); an agent or organization key always gets this. |
| 404 | The project or attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/attachments/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-F "file=@./screenshot.png" \
-F "caption=Staging dashboard"dailybot plan project attach 00000000-0000-4000-8000-000000000001 ./plan.pdf --caption "Launch plan"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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
Download a project attachment's bytes
Streams the file with the content type recorded at upload, X-Content-Type-Options: nosniff and Cache-Control: no-store. It never redirects to storage. Anyone who can see the project can download it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| attachment_id | string | Required | The attachment's uuid. |
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 | The project or attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/attachments/00000000-0000-4000-8000-000000000009/content/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project attachment get 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000009 -o ./plan.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: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.
Remove an attachment from a project
Removes the attachment from the project.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| attachment_id | string | 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. |
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 | Not a non-guest member acting with a login session or a personal API key (`insufficient_scope`); an agent or organization key always gets this. |
| 404 | The project or attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"dailybot plan project attachment delete 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000009 --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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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 a retired milestone
Brings a retired milestone back. It is the inverse of retiring a milestone with DELETE. Idempotent: a milestone that is not retired is returned unchanged. Send an Idempotency-Key to retry safely.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone'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. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | ProjectMilestone | Required | A ProjectMilestone 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 credential cannot write to Plan (`insufficient_scope`), or the caller is a guest (`guest_not_allowed`). |
| 404 | The project or milestone does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/restore/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"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.
/v1/plan/projects/{project_id}/milestones/{milestone_id}/attachments/BetaAPI keyCLI AuthPage-number paginationList a milestone's attachments
The milestone's READY attachments, ordered by position. Anyone who can see the project can list them; a project you cannot see is 404. Each url is a download link. Do not store it: keep the attachment uuid and read it again when you need the file. Reference it from the milestone description with an attachment:{uuid} marker; resolve it with GET /v1/plan/attachments/resolve/ when you render.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
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. |
TaskAttachment object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| filename | string | Required | File name. |
| content_type | string | Required | MIME type. |
| size | integer | Required | Size in bytes. |
| url | string | Required | Where to download the file. |
| thumbnail_url | uri | null | Optional | Thumbnail for images. |
| width | integer | null | Optional | — |
| height | integer | null | Optional | — |
| status | enum | Required | Current status. One of pending, ready, scanning, rejected. |
| uploaded_by | ActorRef | null | Optional | Who uploaded the file. See ActorRef. |
| executed_by_agent | object | null | Optional | The agent that executed this on behalf of the person, or null when no agent was named: an object with uuid, name, username and avatar. The person in the author field is still the author; the agent is shown as the one who executed it. |
| 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<TaskAttachment> | Required | The rows on this page. See TaskAttachment. |
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 | The project or milestone does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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.
Upload an attachment to a milestone
Attaches a file to the milestone. Send multipart/form-data with the file field and an optional caption; there is no presign flow here. The limit is 5 MiB: a larger file is 400 attachment_too_large, with extra.max_size_bytes. The file type is checked from its content against the same list as project attachments (attachment_invalid_type). Attaching follows the milestone's own write rules. Reference it from the milestone description with an attachment:{uuid} marker; resolve it with GET /v1/plan/attachments/resolve/ when you render.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone'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 |
|---|---|---|---|
| file | binary | Required | The file to upload (max 5 MiB this way). |
| caption | string | Optional | Optional caption. Max 255 characters. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
Errors
| Status | When |
|---|---|
| 400 | The file is missing, too large (`attachment_too_large`, over 5 MiB), of an unsupported type (`attachment_invalid_type`), or the limit of 50 is reached (`attachment_limit_reached`). `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 | The credential cannot write to Plan (`insufficient_scope`), or the caller is a guest (`guest_not_allowed`). |
| 404 | The project or milestone does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-F "[email protected]"{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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: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.
/v1/plan/projects/{project_id}/milestones/{milestone_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRetrieve a milestone attachment
One attachment of the milestone. Anyone who can see the project can read it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
| attachment_id | string | Required | The attachment's uuid. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
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 | The project, the milestone or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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.
/v1/plan/projects/{project_id}/milestones/{milestone_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRename a milestone attachment
Changes the attachment's file name; the content does not change. The rules are the milestone's own.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
| attachment_id | string | 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. |
| 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 | The name is missing or not valid. `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 | The credential cannot write to Plan (`insufficient_scope`), or the caller is a guest (`guest_not_allowed`). |
| 404 | The project, the milestone 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/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"filename": "roadmap-v2.png"}'{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap-v2.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap-v2.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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: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.
/v1/plan/projects/{project_id}/milestones/{milestone_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRemove a milestone attachment
Removes the attachment. The rules are the milestone's own.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
| attachment_id | string | 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. |
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 credential cannot write to Plan (`insufficient_scope`), or the caller is a guest (`guest_not_allowed`). |
| 404 | The project, the milestone or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"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.
/v1/plan/projects/{project_id}/milestones/{milestone_id}/attachments/{attachment_id}/content/BetaAPI keyCLI AuthDownload a milestone attachment's bytes
Streams the file with the content type recorded at upload, X-Content-Type-Options: nosniff and Cache-Control: no-store. It never redirects to storage. Anyone who can see the project can download it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| milestone_id | string | Required | The milestone's uuid. |
| attachment_id | string | Required | The attachment's uuid. |
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 | The project, the milestone or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
| 409 | The attachment is not ready yet (`attachment_not_ready`). |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/milestones/00000000-0000-4000-8000-000000000007/attachments/00000000-0000-4000-8000-000000000009/content/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" -o roadmap.pngTry 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.
Get a project update
One status note, with its READY attachments inline, provenance, edited_at (null until the first edit) and executed_by_agent.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | ProjectUpdate | Required | A ProjectUpdate object. |
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 | The project or update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"{
"uuid": "00000000-0000-4000-8000-00000000000a",
"project": "00000000-0000-4000-8000-000000000001",
"body": "Staging is green; rolling out Friday.",
"body_html": "<p>Staging is green; rolling out Friday.</p>",
"mentions": [],
"health": "on_track",
"created_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"provenance": "typed",
"edited_at": null,
"attachments": [],
"created_at": "2026-09-29T10:14:02Z",
"updated_at": "2026-09-29T10: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.
Edit a project update
Changes body and/or health (null clears it) and stamps edited_at. Only the author can edit (403 update_not_author). created_by and the original executed_by_agent never change; an edit made through an API key, or stamped with an agent, makes provenance agent_authored. To place images inline, upload them to the update's attachments and add attachment:{uuid} markers to body. Send If-Match or a body version to avoid overwriting a concurrent edit.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update'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 |
|---|---|---|---|
| body | string | Optional | Markdown. Max 20000 characters. |
| health | enum | null | Optional | Declared health. One of not_set, on_track, at_risk, off_track. |
| 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) | ProjectUpdate | Required | A ProjectUpdate object. |
Errors
| Status | When |
|---|---|
| 400 | The body is empty or too long (`update_body_too_long`), or `health` is not valid. `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 | Only the update's author can do this (`update_not_author`). |
| 404 | The project or update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X PATCH "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body": "Staging is green; rolling out Friday.", "health": "on_track"}'{
"uuid": "00000000-0000-4000-8000-00000000000a",
"project": "00000000-0000-4000-8000-000000000001",
"body": "Staging is green; rolling out Friday.",
"body_html": "<p>Staging is green; rolling out Friday.</p>",
"mentions": [],
"health": "on_track",
"created_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"provenance": "typed",
"edited_at": "2026-09-29T11:02:00Z",
"attachments": [],
"created_at": "2026-09-29T10:14:02Z",
"updated_at": "2026-09-29T11:02:00Z"
}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.
Delete a project update
Removes the update and its attachments; a stored file is deleted once nothing else references it. The author or an organization admin can delete (403 update_not_author for anyone else).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update'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]. |
| 403 | Only the update's author can do this (`update_not_author`). |
| 404 | The project or update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"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.
/v1/plan/projects/{project_id}/updates/{update_id}/attachments/BetaAPI keyCLI AuthPage-number paginationList a update's attachments
The update's READY attachments, ordered by position. Anyone who can see the project can list them; a project you cannot see is 404. Each url is a download link. Do not store it: keep the attachment uuid and read it again when you need the file. Reference it from the update body with an attachment:{uuid} marker; resolve it with GET /v1/plan/attachments/resolve/ when you render.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
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. |
TaskAttachment object
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | uuid | Required | Stable public identifier. |
| filename | string | Required | File name. |
| content_type | string | Required | MIME type. |
| size | integer | Required | Size in bytes. |
| url | string | Required | Where to download the file. |
| thumbnail_url | uri | null | Optional | Thumbnail for images. |
| width | integer | null | Optional | — |
| height | integer | null | Optional | — |
| status | enum | Required | Current status. One of pending, ready, scanning, rejected. |
| uploaded_by | ActorRef | null | Optional | Who uploaded the file. See ActorRef. |
| executed_by_agent | object | null | Optional | The agent that executed this on behalf of the person, or null when no agent was named: an object with uuid, name, username and avatar. The person in the author field is still the author; the agent is shown as the one who executed it. |
| 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<TaskAttachment> | Required | The rows on this page. See TaskAttachment. |
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 | The project or update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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.
Upload an attachment to a update
Attaches a file to the update. Send multipart/form-data with the file field and an optional caption; there is no presign flow here. The limit is 5 MiB: a larger file is 400 attachment_too_large, with extra.max_size_bytes. The file type is checked from its content against the same list as project attachments (attachment_invalid_type). Only the update's author can attach (403 update_not_author). Upload first, then add the marker to the update's body with a PATCH. Reference it from the update body with an attachment:{uuid} marker; resolve it with GET /v1/plan/attachments/resolve/ when you render.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update'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 |
|---|---|---|---|
| file | binary | Required | The file to upload (max 5 MiB this way). |
| caption | string | Optional | Optional caption. Max 255 characters. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
Errors
| Status | When |
|---|---|
| 400 | The file is missing, too large (`attachment_too_large`, over 5 MiB), of an unsupported type (`attachment_invalid_type`), or the limit of 50 is reached (`attachment_limit_reached`). `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 | Only the update's author can do this (`update_not_author`). |
| 404 | The project or update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-F "[email protected]"{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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: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.
/v1/plan/projects/{project_id}/updates/{update_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRetrieve a update attachment
One attachment of the update. Anyone who can see the project can read it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
| attachment_id | string | Required | The attachment's uuid. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| (body) | TaskAttachment | Required | A TaskAttachment object. |
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 | The project, the update or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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.
/v1/plan/projects/{project_id}/updates/{update_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRename a update attachment
Changes the attachment's file name; the content does not change. Only the update's author can rename it (403 update_not_author).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
| attachment_id | string | 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. |
| 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 | The name is missing or not valid. `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 | Only the update's author can do this (`update_not_author`). |
| 404 | The project, the update 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/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"filename": "roadmap-v2.png"}'{
"uuid": "00000000-0000-4000-8000-000000000009",
"filename": "roadmap-v2.png",
"content_type": "image/png",
"size": 48213,
"url": "https://your.app/files/roadmap-v2.png",
"thumbnail_url": null,
"width": null,
"height": null,
"status": "ready",
"uploaded_by": {
"kind": "user",
"uuid": "00000000-0000-4000-8000-00000000000c",
"name": "Ada L."
},
"executed_by_agent": null,
"created_at": "2026-09-29T10: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: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.
/v1/plan/projects/{project_id}/updates/{update_id}/attachments/{attachment_id}/BetaAPI keyCLI AuthRemove a update attachment
Removes the attachment. The update's author can remove it, and so can an organization admin (403 update_not_author for anyone else).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
| attachment_id | string | 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. |
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 | Only the update's author can do this (`update_not_author`). |
| 404 | The project, the update or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN"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.
/v1/plan/projects/{project_id}/updates/{update_id}/attachments/{attachment_id}/content/BetaAPI keyCLI AuthDownload a update attachment's bytes
Streams the file with the content type recorded at upload, X-Content-Type-Options: nosniff and Cache-Control: no-store. It never redirects to storage. Anyone who can see the project can download it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
| attachment_id | string | Required | The attachment's uuid. |
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 | The project, the update or the attachment does not exist or you cannot see it (`not_found`), never a 403. |
| 409 | The attachment is not ready yet (`attachment_not_ready`). |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000001/updates/00000000-0000-4000-8000-00000000000a/attachments/00000000-0000-4000-8000-000000000009/content/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" -o roadmap.pngTry 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.
Rename a project attachment
Changes the display file name; the stored bytes do not change. The rules are the container's own: organization administrators only.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| 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 are not an organization administrator (`insufficient_scope`), or you are a guest (`guest_not_allowed`). An agent or organization key is refused here too. |
| 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/projects/00000000-0000-4000-8000-000000000003/attachments/00000000-0000-4000-8000-000000000009/" \
-H "Authorization: Bearer $DAILYBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filename": "spec-v2.pdf"
}'dailybot plan project attachments rename 00000000-0000-4000-8000-000000000003 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:admin` — container writes. A non-guest member can call it with a login session or a personal API key (a key with explicit Plan scopes needs `tasks:write`, which covers it); an agent or organization key gets `403 insufficient_scope`.
- 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`.
/v1/plan/projects/{project_id}/updates/{update_id}/reactions/BetaAPI keyCLI AuthPage-number paginationList who reacted to a project update
Everyone who reacted to the update, oldest first, as a page. emoji narrows to one emoji. The same shape as a comment's reactor list.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
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. |
| emoji | string | Optional | One emoji; every emoji when omitted. The same rule as writes: anything else is 400 reaction_invalid_emoji. |
Reactor object
ActorRef 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<Reactor> | Required | The page of Reactor objects. |
Errors
| Status | When |
|---|---|
| 400 | `emoji` is not a single emoji (`reaction_invalid_emoji`), or a paging value is not valid. |
| 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 | The project or the update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000003/updates/00000000-0000-4000-8000-000000000007/reactions/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project update reactions 00000000-0000-4000-8000-000000000003 00000000-0000-4000-8000-000000000007Try 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.
Add an emoji reaction to a project update (idempotent)
Adds your emoji reaction to the update; adding it again changes nothing. The same rules as comment reactions: one emoji, one reaction per person per emoji, and a person behind the credential. A person holds at most 20 different emojis on one update (400 reaction_limit_reached, extra.limit). The response is the whole update with its reactions.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update'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 |
|---|---|---|---|
| emoji | string | Required | The emoji. Max 32 characters. |
| 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) | ProjectUpdate | Required | A ProjectUpdate object. |
Errors
| Status | When |
|---|---|
| 400 | Not a single emoji (`reaction_invalid_emoji`), an agent or organization key (`actor_required`), too many different emojis from you on this update (`reaction_limit_reached`), or an invalid agent name (`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 | The project or the update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X POST "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000003/updates/00000000-0000-4000-8000-000000000007/reactions/" \
-H "X-API-KEY: $DAILYBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"emoji": "👍"
}'dailybot plan project update react 00000000-0000-4000-8000-000000000003 00000000-0000-4000-8000-000000000007 👍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.
Remove the caller's emoji reaction from a project update
Removes your reaction with this emoji from the update. It answers 204 even when the reaction was already gone.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| project_id | string | Required | The project's uuid. |
| update_id | string | Required | The update's uuid. |
| emoji | string | Required | The emoji, percent-encoded as UTF-8. |
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 | 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]. |
| 404 | The project or the update does not exist or you cannot see it (`not_found`), never a 403. |
curl -sS -X DELETE "https://api.dailybot.com/v1/plan/projects/00000000-0000-4000-8000-000000000003/updates/00000000-0000-4000-8000-000000000007/reactions/%F0%9F%91%8D/" \
-H "X-API-KEY: $DAILYBOT_API_KEY"dailybot plan project update unreact 00000000-0000-4000-8000-000000000003 00000000-0000-4000-8000-000000000007 👍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.
This page is the reference for Plan · Projects. 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.