# Authentication and scopes for Plan

> Which credentials reach the Dailybot Plan API (Beta): login sessions, personal API keys that act as their person, agent and organization keys, scopes, guests and privacy.

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

---

> **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**.

The Plan API accepts three credentials. They behave differently, so pick the one that matches who is acting. The general rules for every Dailybot API live in [Authentication](/developers/authentication) and [CLI authentication](/developers/cli-authentication); this page covers what is specific to Plan.

<h2 id="credentials">Three credentials</h2>

| Credential | How you send it | Acts as | Use it for |
|---|---|---|---|
| **Login session** | `Authorization: Bearer <token>` (the web app, or `dailybot login` for the CLI) | You, with your role | The Dailybot web app, and scripts and agents working on behalf of one person |
| **Personal API key** | `X-API-KEY: <key>` | The person who created it, for themselves | Scripts, CI and agents that should be that person |
| **Agent or organization key** | `X-API-KEY: <key>` | A system actor: no person behind it | Server-to-server integrations that read or write organization-visible work |

<h3 id="cli-token">Login session: acts as you</h3>

A login session carries your identity and your role in the organization. `dailybot login` gets one with an emailed one-time code; the same flow is available over HTTP (see the [quickstart](/developers/plan/quickstart#step-1)). A login token only travels to the API host that issued it.

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

<h3 id="user-key">Personal API key: acts as its person</h3>

A **personal API key** is created by a person for themselves. On Plan it answers exactly as that person does in the web app:

- It sees what the person sees, including the private boards they belong to. `me` is the person, and every write is recorded as the person.
- **It can do everything the person can do on every Plan endpoint**: all reads and all task writes, and all structure and membership writes: projects, boards, columns, goals, milestones, members (by user or team), participants, mute, saved views and attachments.
- There is **no organization-admin prerequisite** and **no scope to request**: every non-guest member can, so their key can.
- A key row that carries explicit `tasks:*` scopes is a **ceiling the person chose**: `tasks:write` covers admin operations too, and `tasks:read` keeps the key read-only. A key with only non-Plan scopes has no Plan access.

```bash
curl -sS "https://api.dailybot.com/v1/plan/me/tasks/" \
  -H "X-API-KEY: $DAILYBOT_API_KEY"
```

<h3 id="api-key">Agent or organization key: a system actor</h3>

A key with no person behind it never acts as a person:

- It sees **organization-visible boards only**, never members-only boards.
- It has no `me`: `?owner=me` answers `400 actor_required`.
- Endpoints that need a person or an administrator (listed [below](#person-only)) answer `403 insufficient_scope`.
- It must hold **Plan scopes of its own** (`tasks:read` and `tasks:write`).
- It acts as a specific person only when the request also carries an exchange token (`X-EXCHANGE-TOKEN`), as described in [Authentication](/developers/authentication).
- It cannot name an agent on a write: sending an agent name with an agent key is `400 invalid_agent_attribution`.

```bash
curl -sS "https://api.dailybot.com/v1/plan/boards/" \
  -H "X-API-KEY: $DAILYBOT_API_KEY"
```

> **Agent and organization keys need Plan scopes enabled for the key.** A new key has none. During the Beta, write to **support@dailybot.com** to enable them.

**Guests** are limited by role with a key or a session alike: `403 guest_not_allowed`, before anything else is checked. An expired key is `401 credential_expired`; a revoked key or a deactivated owner is `401` too (see [sign-in errors](#sign-in-errors)).

<h2 id="scopes">Scopes</h2>

| Scope | Grants |
|---|---|
| `tasks:read` | Every read |
| `tasks:write` | Row-level writes: tasks, comments, labels, relations, participants. On a key row it also covers the admin operations below |
| `tasks:admin` | Container writes: projects, boards, states, memberships, goals. Every non-guest member holds it |

Each endpoint in the [reference](/developers/api/plan-tasks) states its scope. How a credential gets them:

| Credential | Scopes |
|---|---|
| Login session, non-guest member | `tasks:read`, `tasks:write`, `tasks:admin` |
| Personal API key | Everything its person can do, without granting anything. If the key row lists explicit Plan scopes, they are a ceiling |
| Agent or organization key | Only the scopes granted to the key (`tasks:read`, `tasks:write`); it is refused on the endpoints that need a person |
| Guest, with any credential | None: refused with `403 guest_not_allowed` before entitlement |

A call without the scope it needs answers `403 insufficient_scope`.

**Privacy is membership (invite), not org role.** Org-wide containers are a shared workspace. A `members` project, board or task answers **404 not found** to anyone without a grant, in reads, lists, search, comments, attachments and activity alike. Treat that as **not visible**, never as “not allowed”. A board inside a `members` project follows the project's membership, and boards expose `effective_visibility` (`org` or `members`) so you can tell. Invite a person or a team with membership writes to share; the last grant on a private container is `409 last_grant_cannot_be_removed`. There are no per-project roles such as lead or viewer: membership is a grant only.

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

Guests are refused before anything else is checked, so a guest never learns whether the organization is enabled for Plan or how close it is to its plan limits.

<h2 id="person-only">Endpoints that need a person</h2>

Some endpoints need a person behind the request, so an agent or organization key is refused with `403 insufficient_scope`. A login session and a personal API key work on all of them. In the [reference](/developers/api/plan-tasks), the *API key* badge on an endpoint means an agent or organization key is accepted too; endpoints without it are the ones listed here. They fall into four families:

- **Your own things**: your tasks, counts, recent boards, inbox, activity cursor, favorites and saved views.
- **Who can see**: project member lists (a board's member list works with any key). Changing members is an administration operation (below).
- **Who is notified**: task participants and watch subscriptions. A key with no person has nobody to be accountable for who gets notified.
- **Administration** (`tasks:admin`): creating, editing, archiving and restoring projects, boards, workflow states and goals, reordering states, adding and removing project and goal attachments, adding, changing and removing board and project members, and linking goals to projects. A personal API key can do all of it.

Managing organization labels through the Plan API (`…/labels/`) needs a person as well.

<!-- Generated from the apiEndpoints collection (auth.api_key = false). -->

**[Plan · Projects](/developers/api/plan-projects)**

- [`POST /v1/plan/projects/`](/developers/api/plan-projects#plan-project-create): Create a project
- [`PATCH /v1/plan/projects/{project_id}/`](/developers/api/plan-projects#plan-project-patch): Update a project
- [`POST /v1/plan/projects/{project_id}/archive/`](/developers/api/plan-projects#plan-project-archive): Archive a project, cascading to its boards and their tasks
- [`POST /v1/plan/projects/{project_id}/restore/`](/developers/api/plan-projects#plan-project-restore): Restore an archived project
- [`GET /v1/plan/projects/{project_id}/views/`](/developers/api/plan-projects#plan-project-views-list): This person's saved views inside a project
- [`PUT /v1/plan/projects/{project_id}/views/`](/developers/api/plan-projects#plan-project-views-save): Replace this person's saved views for a project
- [`GET /v1/plan/projects/{project_id}/members/`](/developers/api/plan-projects#plan-project-members-list): Members of a project
- [`POST /v1/plan/projects/{project_id}/members/`](/developers/api/plan-projects#plan-project-member-add): Invite somebody, or a whole team, into a project
- [`DELETE /v1/plan/projects/{project_id}/members/{user_id}/`](/developers/api/plan-projects#plan-project-member-remove): Remove somebody from a project
- [`PATCH /v1/plan/projects/{project_id}/members/{user_id}/`](/developers/api/plan-projects#plan-project-member-patch): Inspect a project membership grant (role is read-only)
- [`POST /v1/plan/projects/{project_id}/attachments/`](/developers/api/plan-projects#plan-project-attachment-multipart): Upload an attachment to a project
- [`DELETE /v1/plan/projects/{project_id}/attachments/{attachment_id}/`](/developers/api/plan-projects#plan-project-attachment-delete): Remove an attachment from a project

**[Plan · Goals](/developers/api/plan-goals)**

- [`POST /v1/plan/goals/`](/developers/api/plan-goals#plan-goal-create): Create a goal
- [`PATCH /v1/plan/goals/{goal_id}/`](/developers/api/plan-goals#plan-goal-update): Update a goal, or declare its status
- [`POST /v1/plan/goals/{goal_id}/archive/`](/developers/api/plan-goals#plan-goal-archive): Archive a goal. The projects survive, unpointed
- [`POST /v1/plan/goals/{goal_id}/restore/`](/developers/api/plan-goals#plan-goals-restore): Bring an archived goal back
- [`POST /v1/plan/goals/{goal_id}/projects/`](/developers/api/plan-goals#plan-goal-project-link): Link a project to a goal (from the goal page)
- [`DELETE /v1/plan/goals/{goal_id}/projects/{project_id}/`](/developers/api/plan-goals#plan-goal-project-unlink): Unlink a project from a goal
- [`POST /v1/plan/goals/{goal_id}/attachments/`](/developers/api/plan-goals#plan-goal-attachment-multipart): Upload an attachment to a goal
- [`DELETE /v1/plan/goals/{goal_id}/attachments/{attachment_id}/`](/developers/api/plan-goals#plan-goal-attachment-delete): Remove an attachment from a goal

**[Plan · Boards](/developers/api/plan-boards)**

- [`POST /v1/plan/boards/`](/developers/api/plan-boards#plan-board-create): Create a board and seed its five default states
- [`PATCH /v1/plan/boards/{board_id}/`](/developers/api/plan-boards#plan-board-patch): Update a board, including renaming its key
- [`POST /v1/plan/boards/{board_id}/archive/`](/developers/api/plan-boards#plan-board-archive): Archive a board, cascading to its tasks
- [`POST /v1/plan/boards/{board_id}/restore/`](/developers/api/plan-boards#plan-board-restore): Restore an archived board
- [`POST /v1/plan/boards/{board_id}/visit/`](/developers/api/plan-boards#plan-board-visit): Record that the caller opened a board (HomePulse recent_boards)
- [`POST /v1/plan/boards/{board_id}/states/`](/developers/api/plan-boards#plan-board-state-create): Add a workflow state to a board
- [`PATCH /v1/plan/boards/{board_id}/states/{state_id}/`](/developers/api/plan-boards#plan-board-state-patch): Rename, recolour or reorder a workflow state
- [`POST /v1/plan/boards/{board_id}/states/{state_id}/archive/`](/developers/api/plan-boards#plan-board-state-archive): Retire a column
- [`POST /v1/plan/boards/{board_id}/states/{state_id}/restore/`](/developers/api/plan-boards#plan-board-state-restore): Restore a retired column
- [`POST /v1/plan/boards/{board_id}/states/reorder/`](/developers/api/plan-boards#plan-board-states-reorder): Reorder every live column on a board in one call
- [`GET /v1/plan/boards/{board_id}/views/`](/developers/api/plan-boards#plan-board-views-list): The caller's saved views for this board
- [`PUT /v1/plan/boards/{board_id}/views/`](/developers/api/plan-boards#plan-board-views-save): Replace the caller's saved views for this board
- [`GET /v1/plan/boards/{board_id}/mentionables/`](/developers/api/plan-boards#plan-board-mentionables): Search people mentionable on a board
- [`POST /v1/plan/boards/{board_id}/members/`](/developers/api/plan-boards#plan-board-member-add): Add a member to a board
- [`DELETE /v1/plan/boards/{board_id}/members/{user_id}/`](/developers/api/plan-boards#plan-board-member-remove): Remove a member from a board
- [`PATCH /v1/plan/boards/{board_id}/members/{user_id}/`](/developers/api/plan-boards#plan-board-member-patch): Inspect a board membership grant (role is read-only)
- [`GET /v1/plan/boards/{board_id}/labels/`](/developers/api/plan-boards#plan-board-labels-list): List organization labels (board access gate)
- [`POST /v1/plan/boards/{board_id}/labels/`](/developers/api/plan-boards#plan-board-label-create): Create an organization label
- [`GET /v1/plan/views/{view_id}/`](/developers/api/plan-boards#plan-view-get): One saved view by uuid
- [`PATCH /v1/plan/views/{view_id}/`](/developers/api/plan-boards#plan-view-patch): Edit one saved view
- [`DELETE /v1/plan/views/{view_id}/`](/developers/api/plan-boards#plan-view-delete): Delete one saved view

**[Plan · Tasks](/developers/api/plan-tasks)**

- [`POST /v1/plan/tasks/{task_id}/subscription/`](/developers/api/plan-tasks#plan-task-subscribe): Subscribe to task notifications (watcher role)
- [`DELETE /v1/plan/tasks/{task_id}/subscription/`](/developers/api/plan-tasks#plan-task-unsubscribe): Remove a watcher subscription
- [`GET /v1/plan/tasks/{task_id}/participants/`](/developers/api/plan-tasks#plan-task-participants-list): Who is on this card
- [`POST /v1/plan/tasks/{task_id}/participants/`](/developers/api/plan-tasks#plan-task-participant-add): Put someone on this card
- [`DELETE /v1/plan/tasks/{task_id}/participants/{user_uuid}/`](/developers/api/plan-tasks#plan-task-participant-remove): Take someone off this card

**[Plan · Home & search](/developers/api/plan-home)**

- [`GET /v1/plan/me/tasks/`](/developers/api/plan-home#plan-me-tasks-list): The calling user's tasks
- [`GET /v1/plan/me/tasks/counts/`](/developers/api/plan-home#plan-me-tasks-counts): Personal task tab counts
- [`GET /v1/plan/me/recents/`](/developers/api/plan-home#plan-me-recents-list): Recently visited boards for the caller
- [`GET /v1/plan/inbox/`](/developers/api/plan-home#plan-inbox-list): Notification-worthy task events for the caller
- [`POST /v1/plan/inbox/read-all/`](/developers/api/plan-home#plan-inbox-read-all): Mark all inbox items read
- [`POST /v1/plan/inbox/{item_uuid}/read/`](/developers/api/plan-home#plan-inbox-item-read): Catch up to one inbox row
- [`GET /v1/plan/inbox/unread-count/`](/developers/api/plan-home#plan-inbox-unread-count): Unread inbox count for the caller
- [`GET /v1/plan/me/activity-cursor/`](/developers/api/plan-home#plan-me-activity-cursor-get): Read the caller's activity read cursor
- [`PUT /v1/plan/me/activity-cursor/`](/developers/api/plan-home#plan-me-activity-cursor-put): Mark activity as read up to a timestamp
- [`GET /v1/plan/labels/`](/developers/api/plan-home#plan-org-labels-list): List organization labels
- [`POST /v1/plan/labels/`](/developers/api/plan-home#plan-org-label-create): Create an organization label
- [`PATCH /v1/plan/labels/{label_id}/`](/developers/api/plan-home#plan-org-label-update): Update an organization label
- [`DELETE /v1/plan/labels/{label_id}/`](/developers/api/plan-home#plan-org-label-delete): Delete an organization label
- [`GET /v1/plan/me/favorites/`](/developers/api/plan-home#plan-me-favorites-list): Your pinned boards and saved views
- [`POST /v1/plan/me/favorites/`](/developers/api/plan-home#plan-me-favorites-create): Pin a board or a saved view
- [`PATCH /v1/plan/me/favorites/{favorite_id}/`](/developers/api/plan-home#plan-me-favorite-reorder): Move one pin within your list
- [`DELETE /v1/plan/me/favorites/{favorite_id}/`](/developers/api/plan-home#plan-me-favorite-delete): Unpin

<h2 id="not-enabled">When Plan is not enabled</h2>

What you get depends on why:

| Situation | Response |
|---|---|
| Your organization's plan allows Plan but it is not in the Beta yet | `402 plan_upgrade_required` on every Plan endpoint, with any credential. This is expected during the Beta: write to **support@dailybot.com** |
| Free-plan organization, CLI user token | `403 plan_upgrade_required`, raised at sign-in, before Plan is reached |
| Free-plan organization, organization API key | `401 plan_free_api_keys_forbidden` |

`GET /v1/plan/entitlements/` never answers `402`: call it to find out whether Plan is enabled and why not.

<h2 id="sign-in-errors">Sign-in errors</h2>

These come from the credential itself, before any Plan rule runs:

| Status | Code | Meaning |
|---|---|---|
| 401 | `credential_absent` · `credential_expired` · `credential_malformed` | No credential, an expired one, or one that cannot be read |
| 401 | `invalid_credentials` | The key or token does not exist |
| 401 | `api_key_owner_inactive` | The key's owner has been deactivated |
| 401 | `plan_free_api_keys_forbidden` | API keys are not available on the free plan |
| 401 | `plan_missing_core_api_integrations` | The organization's plan does not include API access |
| 403 | `plan_upgrade_required` | Free-plan CLI sign-in reaching a paid endpoint |
| 429 | (throttled) | Too many requests: wait the seconds in `Retry-After` |

The full list of Plan codes is in the reference's error tables and in [Errors](/developers/errors).

---

## 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)
- [Concepts](/developers/plan/concepts)
- [Quickstart](/developers/plan/quickstart)
- [Authentication & scopes](/developers/plan/authentication) (this page)
- [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)

