# Dailybot Plan API

> Plan and track work through the Dailybot Plan API (Beta): projects, boards, tasks and goals over one REST API, with the concepts you need before your first call.

Language: en
Canonical: https://www.dailybot.com/developers/plan
Markdown: send header `Accept: text/markdown` on any URL to receive Markdown instead of HTML.
Last Updated: 2026-10-05

---

> **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 **support@dailybot.com**.
>
> [request beta access](mailto:support@dailybot.com?subject=Dailybot%20Plan%20Beta%20access)

Dailybot Plan is where a team plans and tracks its work: **projects**, **boards**, **tasks** and **goals**. Plan is **agent-first**: almost everything you can do in the `/plan` web app is reachable through the same public API, the Dailybot CLI (`dailybot plan …`) and the agent skill. There is no private API behind the product surface.

All three surfaces call `https://api.dailybot.com/v1/plan/`. If the web app can do it, your integration, CLI script or agent can do it too — with the Phase 2 limits called out on this page (delegation still answers `501`).

This page explains the model once. Every other Plan page links back here.

<h2 id="permissions">Who can do what</h2>

Every authenticated **non-guest member** can use the whole Plan API: create and manage goals, projects, boards, states and memberships. A **personal API key** acts as its person and can do everything that person can do, so a member's key needs no scope grant and no organization-admin role. Guests are refused before entitlement (`403 guest_not_allowed`), with a key or a session.

**Privacy is invite / membership**, not org role. Org-wide projects and boards are a shared workspace. A `members` container is **404** (not visible) without a grant. Invite a person or a team to share; the last grant on a private container is `409 last_grant_cannot_be_removed`. There are no per-project roles (lead/viewer) — membership is a grant, not a role ladder.

**Oversight:** organization admins and managers of all teams can see every project. A `members` board still needs an explicit grant.

**Agent and organization keys** have no person behind them: they see organization-visible boards only and are refused (`403 insufficient_scope`) on the endpoints that need a person. Full detail: [Authentication and scopes for Plan](/developers/plan/authentication).

<h2 id="start-here">Start here</h2>

- **[Concepts](/developers/plan/concepts)**: projects, goals, boards, columns, owners and executors, labels, views and the inbox, one paragraph each.
- **[Agents on Plan](/developers/plan/agents)**: let an agent read a card and write back as a person, with the agent shown on the card.
- **[Dailybot CLI for Plan](/developers/plan/cli)** and the **[agent skill](/developers/plan/agent-skill)**: the command line and the public skill pack.
- **[Quickstart](/developers/plan/quickstart)**: your first calls in under five minutes (sign in, list boards, create, move and comment on a task).
- **[API reference](/developers/api/plan-tasks)**: every endpoint, grouped into [Projects](/developers/api/plan-projects), [Goals](/developers/api/plan-goals), [Boards](/developers/api/plan-boards), [Tasks](/developers/api/plan-tasks), [Comments & files](/developers/api/plan-collaboration) and [Home & search](/developers/api/plan-home).
- **[Authentication and scopes for Plan](/developers/plan/authentication)**: the three credentials, what a personal API key can do, scopes, guests and privacy as membership.
- **[Conventions for Plan](/developers/plan/conventions)**: pagination, filters, sorting, `include`, rate limits, `Idempotency-Key`, `If-Match` and `304`.
- **[Errors for Plan](/developers/plan/errors)**: every code with its status, meaning and what to do next, including `402` during the Beta.
- **[Authentication](/developers/authentication)** and **[Errors](/developers/errors)**: the rules shared by every Dailybot API.

<h2 id="recipes">Recipes</h2>

- **[Show a board and keep it fresh](/developers/plan/recipes/board-live-updates)**: snapshot, delta feed and server-paced polling.
- **[Render a home in one request](/developers/plan/recipes/home-in-one-request)**: the home pulse and its bands.
- **[Create tasks from a list](/developers/plan/recipes/bulk-create)**: bulk create with a dry run and idempotency.
- **[Move a task when a pull request merges](/developers/plan/recipes/move-on-pr-merge)**: from any CI, addressed by key.
- **[Track progress against a goal](/developers/plan/recipes/goal-progress)**: progress, projects and `is_partial`.
- **[React to changes with webhooks](/developers/plan/recipes/webhooks)**: the 25 events and verifying deliveries.

<h2 id="check-access">Check that Plan is enabled for your organization</h2>

Plan is in Beta and is enabled per organization. `GET /v1/plan/entitlements/` is the one Plan endpoint that answers even when your organization is not enabled yet, so call it first:

```bash
curl -sS "https://api.dailybot.com/v1/plan/entitlements/" \
  -H "Authorization: Bearer $DAILYBOT_TOKEN"
```

```json
{
  "enabled": false,
  "reason": "rollout",
  "boards": { "used": 0, "limit": 3 },
  "projects": { "used": 0, "limit": 1 },
  "labels": { "enabled": true }
}
```

`enabled: false` with `reason: "rollout"` means your organization is not in the Beta yet. Every other Plan endpoint answers `402 plan_upgrade_required` until it is: that is expected. Write to **support@dailybot.com** to join.

<h2 id="model">The model: organization, project, board, task</h2>

```
Organization
└── Project            what a body of work is (health, status notes, milestones)
    └── Board          where the work is tracked; its columns are workflow states
        └── Task       one unit of work, addressed as ENG-142
```

A board belongs to a project and a task belongs to a board. Tasks can have **sub-tasks** (one level deep), **relations** to other tasks (`blocks`, `relates_to`, `duplicates`), an **owner**, **participants**, **labels**, **comments** and **attachments**.

<h3 id="workflow-states">Workflow states and their five categories</h3>

A board's columns are its **workflow states**. You can name them anything, but every state has one of five fixed **categories**, and the category is what answers "is this finished?" on any board:

| Category | Meaning | Counts as |
|---|---|---|
| `backlog` | Not planned yet | open |
| `todo` | Planned, not started | open |
| `in_progress` | Being worked on | open |
| `done` | Finished | done |
| `canceled` | Will not be done | done |

The `state` filter accepts two shortcuts built on these categories: `open` (`backlog`, `todo`, `in_progress`) and `done` (`done`, `canceled`). "Blocked" is not a category: it is derived from relations, so filter with `blocked=true`.

<h3 id="goals">Goals point at work; they do not contain it</h3>

A **goal** says what the work is *for*, with a period (`period_start`, `period_end`) and a declared `status`. Nothing lives inside a goal. A project can point at several goals and a goal can be served by several projects, so archiving a goal leaves every project where it was.

A task can point at its own goal. When it does not, it inherits its project's goal, and filters and progress roll-ups apply that same rule.

Goal **progress is scoped to you**: it counts only the tasks you can see, and `is_partial: true` tells you when some of the goal's work is hidden from you. Never present it as an organization-wide number.

There is **no dedicated goals-review endpoint**. Build a review client-side with `GET /v1/plan/goals/?include=progress` (and `projects` when you need the linked work). See the [goal progress recipe](/developers/plan/recipes/goal-progress).

<h2 id="identifiers">Identifiers: uuid and KEY-n</h2>

Every object has a `uuid`. A task also has a human-readable key, `KEY-n`, such as `ENG-142`: `ENG` is the board's key and `142` is a per-board counter. **Both work wherever a task is addressed**, for example `GET /v1/plan/tasks/ENG-142/`.

A board's key can be renamed and **old keys keep resolving**, so a link written last year still opens the card. Keys are never reused, even after a task or board is archived. Numeric ids are never accepted.

An identifier that does not exist and an identifier from another organization return the **same `404` body**, so the API never reveals whether something exists outside your organization.

<h2 id="ordering">Ordering: move relative to neighbours</h2>

Cards in a column are ordered by an opaque `rank`. **Never compute a rank.** Place a card relative to its neighbours instead: `POST /v1/plan/tasks/{task_id}/move/` takes a target `state` and at most one of `after` / `before` (a task in that column). Send neither to append at the end. Two people dragging the same card at the same time both produce a valid order.

Moving is the only way to change a task's state.

<h2 id="versions">Versions and concurrent edits</h2>

Every task carries an integer `version` that increments on each write. To make sure you do not overwrite somebody else's edit, send the version you loaded in the `If-Match` header (or as the body field `version`) when you **update, move, archive or restore** a task (and when you move it to another board). If the task changed meanwhile, the API answers `409 version_conflict` with the current version in `extra.current_version`, so you can re-read and decide. Task detail also returns an `ETag`: send it back as `If-None-Match` to get `304 Not Modified` when nothing changed.

Without `If-Match` on a write, the last write wins. Core writes also accept an `Idempotency-Key` so a retry after a timeout does not double-apply; bulk create **requires** the header. Details: [Conventions for Plan](/developers/plan/conventions#idempotency).

<h2 id="archive">Archive is the delete</h2>

No public endpoint hard-deletes a task, a board or a project. **`DELETE` on a task is a soft archive** (the same as the archive endpoint), and it is reversible:

- Archiving a project cascades to its boards and their tasks; archiving a board cascades to its tasks; archiving a task archives its sub-tasks.
- Restore walks back up, never down: restoring a project does not restore the boards it archived, because the API cannot tell them apart from boards archived on purpose. Restore each one you want back.
- Tasks, boards, projects, goals and workflow states each have a `…/restore/` endpoint.
- The `DELETE` endpoints for tasks and milestones are **aliases that soft-archive** — they do not permanently remove the row.
- Archived rows stay readable: lists hide them unless you pass `include_archived=true`, and a task stays readable by key or uuid.
- Board keys stay reserved through archive and restore.

The archive endpoints, milestone completion and bulk calls accept `?dry_run=true`, which returns the consequence (including a sentence to show a person) without writing anything.

<h2 id="mentions">Mentions</h2>

To mention someone in a comment or a project update, write `<@DB@{uuid}>`, using the person's `uuid` from `GET /v1/plan/boards/{board_id}/mentionables/`:

```text
Looks good. <@DB@00000000-0000-4000-8000-00000000000c> can you review the rollout plan?
```

Responses render mentions as display text in `body` and list the people in `mentions[]`: read them from there, never by parsing `body`. A uuid that names nobody in your organization is removed from the text. Comments support one level of threading through `parent_comment`.

<h2 id="additive-enums">Ignore values you do not recognise</h2>

Event types, relation types, state categories and the list of webhook events are **additive**: new values arrive in minor releases. A client that treats an unknown value as an error will break on a release that changed nothing for it. Skip what you do not know.

<h2 id="phase-2">Phase 2 limits (by design)</h2>

These doors are **not** fully available yet. Document them honestly so agents do not assume a full runtime:

| Topic | Contract today |
|---|---|
| **Task delegation** (delegate / handback / revoke) | API answers **`501`** until a separate agent-runtime plan ships |
| **`author_kind=agent`** | **Never** produced from an organization or agent API key. The person credential stays the author; stamp the runner with `agent_name` / `--agent-name` and read **`executed_by_agent`** on the response |
| **Goals review** | **Client-only**: compose `GET /v1/plan/goals/?include=progress` — no `/goals/review/` door |
| **Structure CRUD** (projects, boards, states, memberships) | Needs a **person** credential (login session or personal API key). An org/agent key alone is refused on person-only endpoints |

Rate limits per actor per minute: **reads 120**, **writes 60**, **bulk 30**, **board delta 240**. Attachment downloads use relative `content_url` paths under `/v1/plan/…/content/` — never bare `http://localhost/media/…` URLs. Full tables: [Conventions](/developers/plan/conventions#rate-limits) and [Agents on Plan](/developers/plan/agents).

<h2 id="beta">What Beta means here</h2>

Paths, fields and behaviour described on these pages can change before general availability; we announce changes in the [API changelog](/developers/api-changelog). If something you rely on is missing or unclear, write to **support@dailybot.com**.

---

## Developer portal navigation

**Getting Started**

- [Overview](/developers)
- [Quick start](/developers/getting-started)
- [Authentication](/developers/authentication)

**API Reference**

- [API Overview](/developers/api)
- [Users](/developers/api/users)
- [Organization](/developers/api/organization)
- [Teams](/developers/api/teams)
- [Invitations](/developers/api/invitations)
- [Check-ins](/developers/api/check-ins)
- [Forms](/developers/api/forms)
- [Labels](/developers/api/labels)
- [Report channels](/developers/api/report-channels)
- [Templates](/developers/api/templates)
- [Kudos](/developers/api/kudos)
- [Mood tracking](/developers/api/mood)
- [Important dates](/developers/api/important-dates)
- [Messaging](/developers/api/messaging)
- [Automations](/developers/api/workflows)
- [Webhooks](/developers/api/webhooks)
- [Commands platform](/developers/api/commands-platform)
- [Agents](/developers/api/agents)
- [OAuth2](/developers/api/oauth2)
- [Integrations](/developers/api/integrations)
- [CLI](/developers/api/cli)
- [Plan · Projects](/developers/api/plan-projects)
- [Plan · Goals](/developers/api/plan-goals)
- [Plan · Boards](/developers/api/plan-boards)
- [Plan · Tasks](/developers/api/plan-tasks)
- [Plan · Comments & files](/developers/api/plan-collaboration)
- [Plan · Home & search](/developers/api/plan-home)
- [Plan · Notifications & reports](/developers/api/plan-notifications)

**Dailybot Plan**

- [Overview](/developers/plan) (this page)
- [Concepts](/developers/plan/concepts)
- [Quickstart](/developers/plan/quickstart)
- [Authentication & scopes](/developers/plan/authentication)
- [Agents on Plan](/developers/plan/agents)
- [Conventions](/developers/plan/conventions)
- [Errors](/developers/plan/errors)
- [CLI for Plan](/developers/plan/cli)
- [Agent skill](/developers/plan/agent-skill)
- [Recipe: live board](/developers/plan/recipes/board-live-updates)
- [Recipe: home in one request](/developers/plan/recipes/home-in-one-request)
- [Recipe: bulk create](/developers/plan/recipes/bulk-create)
- [Recipe: move on PR merge](/developers/plan/recipes/move-on-pr-merge)
- [Recipe: goal progress](/developers/plan/recipes/goal-progress)
- [Recipe: webhooks](/developers/plan/recipes/webhooks)

**API guides**

- [Errors & Status Codes](/developers/errors)
- [Rate Limits](/developers/rate-limits)
- [Conventions](/developers/conventions)
- [API Changelog](/developers/api-changelog)
- [Recipes](/developers/recipes)

**Developer Features**

- [Custom commands](/developers/custom-commands)
- [Serverless commands](/developers/serverless)
- [Webhooks & events](/developers/webhooks)
- [Automation API trigger](/developers/workflow-trigger)
- [Activity API](/developers/activity-api)

**CLI**

- [Overview](/developers/cli)
- [Authentication](/developers/cli-authentication)
- [Command reference](/developers/cli-reference)
- [CI/CD recipes](/developers/cli-ci-cd)
- [Configuration](/developers/cli-configuration)
- [Troubleshooting](/developers/cli-troubleshooting)

**Agent Skill**

- [Overview](/developers/agent-skill)
- [Skills catalog](/skills)

---

## Site navigation

**Product:**
- [Home](/)
- [Product](/product)
- [Pricing](/pricing)
- [Enterprise](/enterprise)
- [Integrations](/integrations)
- [Templates](/templates)

**Resources:**
- [Blog](/blog)
- [Academy](/academy)
- [Changelog](/changelog)
- [Help Center](/help)
- [Developers](/developers)
- [Agents](/agents)

**Company:**
- [About](/about)
- [Careers](/careers)
- [Security](/security)
- [Contact Sales](/demo)

**Connect:**
- [LinkedIn](https://www.linkedin.com/company/dailybot/)
- [X/Twitter](https://twitter.com/dailybot)
- [GitHub](https://github.com/Dailybot-Inc)
- [YouTube](https://www.youtube.com/channel/UC3uM9V52vwX7e3vQpCc4qvA)

