decknote

API Documentation

Decknote REST API, version 1

The API lets you read your boards and create cards from scripts, automations or agents, without logging in. Create a token in Settings → API Tokens. The token is shown once, so store it somewhere safe.

Authentication

Send the token in the Authorization header. Every endpoint below requires it.

curl https://decknote.app/api/v1/me \
  -H "Authorization: Bearer ntrl_your_token_here"

A missing or invalid token returns 401. Tokens carry the permissions of the user who created them: you can read any board you have access to, and write to any board where you are an editor or the owner.

Errors

Errors return the matching HTTP status and a JSON body of the form { "error": "message" }. Exceeding a rate limit returns 429 with a Retry-After header.

Endpoints

get/api/v1/me

Rate limit: 120 requests/minute

Returns the user the token belongs to. Useful to verify a token works.

{
  "user": { "id": "clx…", "name": "Jodie", "email": "[email protected]" }
}

get/api/v1/boards

Rate limit: 120 requests/minute

Every board you can access, each with its lists in display order. This is how you discover the listId values you need to create cards.

{
  "boards": [
    {
      "id": "clx…",
      "title": "Returns",
      "lists": [
        { "id": "cly…", "title": "Requested" },
        { "id": "clz…", "title": "Refunded" }
      ]
    }
  ]
}

post/api/v1/boards

Rate limit: 30 requests/minute

Creates a board owned by the token's user. Send a JSON body:

  • title — required, up to 200 characters.
  • template — optional: blank (default), kanban, content or personal. Picks the initial lists and labels, created in your account's language — same as creating a board from the dashboard.

Returns 201 with the new board and its list ids, ready to create cards into:

{
  "board": {
    "id": "clx…",
    "title": "Ops",
    "lists": [
      { "id": "cly…", "title": "To do" },
      { "id": "clz…", "title": "In progress" },
      { "id": "cl0…", "title": "Done" }
    ],
    "url": "/board/clx…"
  }
}

403 — the free plan's owned-board limit was reached. Archive a board or upgrade to Pro.

post/api/v1/cards

Rate limit: 30 requests/minute

Creates a card. Send a JSON body:

  • listId — the list to create it in. Alternatively send boardId and the card lands in that board's first list. One of the two is required.
  • title — required, up to 500 characters.
  • description — optional, up to 20,000 characters. Accepts Markdown: headings, bullet/numbered lists, - [ ] task lists, **bold**, links and fenced code become the real thing in the card's page. Plain text stays plain paragraphs.
  • dueDate — optional ISO 8601 datetime, e.g. 2026-09-01T15:00:00Z.
  • checklist — optional, a checklist on the card: { "title": "Steps", "items": [{ "text": "…", "done": false }] }.
  • reminders — optional, up to five reminders for you (push and email): { "at": "2026-09-01T12:00:00Z" } for a fixed moment, or { "daysBefore": 1, "time": "09:00", "timeZone": "America/New_York" } to follow the due date, also on recurring cards.
curl -X POST https://decknote.app/api/v1/cards \
  -H "Authorization: Bearer ntrl_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "listId": "cly…",
    "title": "Refund #1042",
    "description": "Customer reported a damaged item.",
    "dueDate": "2026-09-01T15:00:00Z"
  }'

Returns the created card:

{
  "card": {
    "id": "cm…",
    "title": "Refund #1042",
    "listId": "cly…",
    "boardId": "clx…",
    "dueDate": "2026-09-01T15:00:00Z",
    "url": "/board/clx…?card=cm…"
  }
}

On success returns 201. Creating a card writes to the board activity log and shows up live for anyone viewing it, exactly like creating one in the app.

Card-specific errors:

  • 400 — invalid body (missing title, or neither listId nor boardId).
  • 403 — the token owner is not an editor or owner of that board.
  • 404 — the list or board was not found.

post/api/v1/boards/{boardId}/embeds

Rate limit: 30 requests/minute

Creates an embed of a board you own (Pro), same as the Share menu: { "name": "My app", "origins": ["https://my-app.com"], "canEdit": true }. GET on the same path lists them.

post/api/v1/embeds/{embedId}/sessions

Rate limit: 120 requests/minute

Shows a board inside your own app. Create the embed in the board's Share menu (Pro) with your app's address; then, from your app's SERVER, call this with an API token and put the returned url in an iframe. The token stays on your server: the url is valid for that board only, never with owner powers, and the iframe renews it by itself while the embed is on.

  • cardId — optional: open that card.
curl -X POST https://decknote.app/api/v1/embeds/cmz…/sessions \
  -H "Authorization: Bearer ntrl_your_token_here"

{ "url": "https://decknote.app/embed/board/clx…?s=dkw1…", "boardId": "clx…", "expiresAt": "…" }

<iframe src="{url}" style="width:100%;height:80vh;border:0"></iframe>

The iframe posts decknote:ready to the parent page when it loads and decknote:expired if the embed was turned off; ask for a new url then. Only the addresses saved in the embed can frame it.

404 — not your embed. 410 — the embed was turned off or the board archived. 402 — the board's owner isn't on Pro.

CLI login (get a token from the browser)

The simplest way to get a token is Settings → API Tokens — create one and paste it into the MCP config below. For a CLI or an agent that can drive a browser, Decknote also exposes a device-authorization flow (the same shape as gh auth login), which works over SSH and in containers where there is no browser to redirect back to.

POST /api/v1/cli/auth starts a flow and returns a device code (kept by the caller) and a short user code (shown to the human). The human opens /cli, checks the code matches, and approves while signed in. The caller polls POST /api/v1/cli/auth/token and receives the token exactly once — 202 while pending, 200 with { token } once approved, 410 when the code has expired. Codes last ten minutes, and the minted token counts against your plan's limit (Free includes one).

A reference client for this flow lives in cli/ (the decknote package).

Only approve a code you generated yourself — approving someone else's hands them a token on your account.

MCP server (for AI agents)

Decknote runs a Model Context Protocol server so an AI agent can use a board as a task list it adds to, completes and recalls from — a shared memory between your agents and your team. It speaks MCP over Streamable HTTP (protocol 2025-06-18), authenticated with the same Authorization: Bearer token as the REST API.

Endpoint

POST https://decknote.app/api/v1/mcp

Connectors with OAuth (ChatGPT, Claude)

Apps that sign in with OAuth use https://decknote.app/mcp instead: the same server, but every request needs a token, so the app asks you to log in to Decknote and allow it. It registers itself (RFC 7591), uses PKCE, and finds everything from /.well-known/oauth-protected-resource. Connected apps are listed in Settings, where you can disconnect them.

Connect from an MCP client

Point any MCP client at the endpoint and pass your token as a Bearer header. For example, in a Claude / Claude Code MCP config:

{
  "mcpServers": {
    "decknote": {
      "type": "http",
      "url": "https://decknote.app/api/v1/mcp",
      "headers": { "Authorization": "Bearer ntrl_your_token_here" }
    }
  }
}

A raw tools/list call, to check it works:

curl -X POST https://decknote.app/api/v1/mcp \
  -H "Authorization: Bearer ntrl_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Tools

Everything a signed-in person can do in the app has a tool. Start with overview: it returns the plan and its limits, recent boards, what needs attention and suggested next actions naming the tool to use.

  • list_boards — discover boards and lists.
  • create_board — create a board, optionally from a template (blank, kanban, content, personal).
  • create_list — add a list (column) at the end of a board.
  • search_tasks — recall: find tasks by text, status and due date.
  • get_task — read one task in full, with the ids of its checklists, comments, attachments and links.
  • create_task — add a task to a list. The description accepts Markdown.
  • update_task — edit title, description (Markdown), dates, repeat or cover.
  • complete_task / reopen_task — mark done or reopen.
  • move_task — move a task to another list or board.
  • archive_task — archive (soft-delete) a task; recurring dated tasks schedule their next occurrence.
  • add_comment — leave a progress note a human will read (with notify: true, mentioned people and watchers are notified, as in the app — after a confirmation).
  • add_reminder / list_reminders / remove_reminder — reminders for you: a push and an email at a moment, or a few days before the due date.
  • search / fetch — read: search the cards of every board, then read one in full (description, checklists, comments). The shape ChatGPT expects.
  • get_board / list_activity — read a whole board (lists, cards, labels, members, fields, rules, templates, archived cards, public link, pending invitations) and its activity history.
  • update_board / set_board_preferences / duplicate_board / archive_board / restore_board / delete_board / import_trello_board — the board itself: title, icon, color and background (Pro), your favorite and mute, copy, archive, restore, delete (with confirmation) and import from Trello.
  • share_board / update_member / remove_member / leave_board / transfer_board / set_public_link / list_embeds / create_embed / revoke_embed — people and sharing: invite by email (Pro on the web), change roles, remove someone, leave, transfer ownership, the public read-only link and embeds in your own apps.
  • update_list / duplicate_list / sort_list / delete_list — lists: rename, reorder, WIP limit (Pro), copy, sort and delete.
  • create_label / update_label / delete_label / create_custom_field / update_custom_field / delete_custom_field — labels and custom fields of a board.
  • create_saved_view / delete_saved_view / create_automation / set_automation_enabled / delete_automation — your saved views and the board's rules (when a card is added, moved or labeled, do something).
  • duplicate_task / restore_task / delete_task / set_task_labels / set_task_assignees / watch_task / set_task_field / link_tasks / unlink_tasks / bulk_tasks — inside a task: copy, restore from the archive, delete, labels, assignees, watching, custom field values, links between tasks, and bulk move/label/archive.
  • create_task_from_template / save_task_as_template / delete_card_template — card templates.
  • edit_comment / delete_comment / react_to_comment / add_checklist / update_checklist / delete_checklist / add_checklist_items / update_checklist_item / delete_checklist_item / add_attachment / rename_attachment / delete_attachment — comments, checklists and attachments (links, or files sent as base64 within the plan's size limits).
  • list_my_tasks / list_notifications / mark_notifications_read — your tasks across every board and your notifications.
  • get_account / update_account / revoke_access / export_data — your account: settings, plan and limits, notification preferences, revoking a token or a connected app, and the full export.
  • start_pro_checkout / open_billing_portal — the plan, as links only: a Stripe Checkout link to upgrade to Pro (the agent must repeat the exact price, and the person pays on Stripe) and a link to the billing portal to manage or cancel. No tool charges, refunds or pays anything.
  • api_read / api_create — Decknote's own HTTP API as you, for what has no dedicated tool: reading (GET) and creating (POST, with confirmation) are separate tools, on a fixed list of routes (below); never authentication, tokens, sessions, admin or payments, and secrets are stripped.

Decknote's HTTP API from the MCP

api_read and api_create reach only these routes, as the person who connected. The /api/v1 ones are documented above, with their bodies and responses; the others are the routes the app itself uses for the export, link previews and attached files. A path from another site, with .. or encoded escapes, or to authentication, tokens, sessions, admin, payment or internal endpoints is refused.

  • GET /api/v1/me — api_read
  • GET /api/v1/boards — api_read
  • POST /api/v1/boards — api_create
  • POST /api/v1/cards — api_create
  • GET /api/v1/boards/{boardId}/embeds — api_read
  • POST /api/v1/boards/{boardId}/embeds — api_create
  • GET /api/export — api_read
  • GET /api/link-preview?url=… — api_read
  • GET /api/attachments/{attachmentId} — api_read

What needs a confirmation

Writes that delete something for good or reach other people (an email, an assignment, a public link, an embed) never happen on the first call: without confirm: true the tool changes nothing and returns a preview of what it would do, for the agent to show you. No tool moves money: start_pro_checkout also needs the exact price and only returns a Stripe link the person pays on. Every tool has a title; read-only tools are marked readOnlyHint, and every tool that changes data is marked destructiveHint, so the app asks before running it.

The server also offers prompts (prompts/list) for the usual workflows: daily_review, capture_tasks and board_cleanup.

Each tool returns its result as JSON inside a text content block — result.content[0].text is a JSON string you parse. A task looks like { id, title, listId, boardId, dueDate, completed, description, url }; the write tools return { task }, search_tasks returns { tasks: [...] }, and list_boards returns { boards: [{ id, title, lists }] }.

Every tool is scoped to the boards your token can access, with the same permissions as the REST API: it can read any board you belong to and write to any board where you are an editor or owner. Tool errors (no access, invalid input) come back as an MCP error result (a text content block with isError: true), not a broken connection. MCP calls have their own rate limit — about 200 per minute per token, separate from your REST usage.

Exporting your data

The API is for automation, not for backups. To take everything with you — boards, lists, cards, checklists, comments and attachment metadata — use Settings → Your data, or request /api/export while signed in. It returns a single JSON file and is not restricted by plan.