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.
A board is a project when it has settings (client, status, budget, hourly rate); tasks are the board's cards. Time is tracked with a timer or logged by hand, and rolls up into reports. Durations are written like a person does (1h30, 90m, 1:30); dates are YYYY-MM-DD; money you send is in the currency's main unit (85 or "85.50") and money you read is in cents (the currency's smallest unit: whole yen for JPY), next to the client's currency. Reads allow 120 requests per minute and writes 30.
GET /api/v1/time/timer — your running timer, or null.POST /api/v1/time/timer — start a timer on a project or one of its tasks: { "cardId": "…", "note": "…" }. A timer already running is stopped and returned as stopped.POST /api/v1/time/timer/stop — stop it and keep the time as an entry. A timer stopped within 30 seconds is dropped as an accidental click (discarded: true).GET, POST /api/v1/boards/{boardId}/time — a project's time log (filters cardId userId from to limit), or add hours by hand: { "duration": "1h30", "cardId": "…", "day": "2026-10-19", "note": "…", "billable": true }.PATCH, DELETE /api/v1/time/entries/{entryId} — correct or delete an entry. A person changes their own; the project owner anyone's. Time already invoiced or still running answers 409.GET, PATCH /api/v1/cards/{cardId}/time — a task's estimate against the time tracked, and its entries; PATCH sets the estimate ("estimate": "4h") and whether its time is billable ("billable": false).GET /api/v1/time/week?day=YYYY-MM-DD — your own timesheet for that week, Monday to Sunday.GET, PUT /api/v1/time-rules — the rules that close logged hours: yours for the projects you own, or those that govern one project (?boardId=); PUT sets them: { "lockedUntil": "2026-09-30", "editWindowDays": 7 }. lockedUntil is the last closed day (up to today): nobody, the owner included, can add, edit, move or delete hours on or before it; editWindowDays is how many days back everybody else can fix their own hours (0 = only today); null clears a rule. Setting rules is Pro. A write on a closed day answers 409 with { "code": "closed" }.GET, PUT /api/v1/timer-alert — after how long a timer left running notifies you (a notification and a push, once per timer; it does not stop it): { "hours": 8 }, 0 turns it off, any plan. 8 hours by default.GET, POST /api/v1/clients, PATCH /api/v1/clients/{clientId} — your clients (the free plan includes 2 active ones: 402 beyond that, with upgradeUrl); PATCH edits one or archives it with "archived": true.GET, PATCH /api/v1/boards/{boardId}/project — a board's project settings, and changing them (only the board's owner): { "clientId": "…", "status": "active", "budgetType": "hours", "budgetHours": 40, "hourlyRate": 85, "dueDate": "2026-12-31" }.GET /api/v1/boards/{boardId}/project/summary — time tracked, billable amount, how much of the budget is used and the hours of each person.GET /api/v1/reports/time — time added up by project, client, person, task or day over a date range (from to by boardId clientId userId billable); format=csv returns the detail as a CSV file (Pro, 402 otherwise).GET, POST /api/v1/projects — the projects you can see, with client, status, hours and budget (filters status clientId q sort), or a new one: { "title": "…", "clientId": "…" }. The free plan's board limit answers 402.POST /api/v1/projects/from-template — a new project from a starter (website, marketing, retainer) or a saved template, with its due dates shifted onto the start date: { "templateKind": "saved", "templateId": "…", "title": "…", "startDate": "2026-11-02" }.GET, POST, DELETE /api/v1/projects/sample — your sample project (a labelled client, project and two weeks of hours): see it, create it, or delete it with everything on it.
The project's owner reads everyone's hours and the money (rates and amounts). Anyone else on the project reads and logs only their own hours and never sees rates or amounts. A project, task, entry or client that is not yours answers 404, the same as one that does not exist; the editor role is needed to track or log time. The same operations are MCP tools (below).
Only the account's owner bills: invoices, estimates, payments, the billing details and the reports are theirs, and a document that is not yours answers 404, the same as one that does not exist. Amounts you send are in the currency's main unit (85 or "85.50") and amounts you read are in cents (the currency's smallest unit: whole yen for JPY) next to the currency. Nothing here charges or moves money: a payment records that the client already paid. Reads allow 120 requests per minute and writes 30; the free plan's limit of 2 documents a month answers 402 with upgradeUrl; business errors also carry a code next to the sentence (state, overpay, no_profile, nothing_to_invoice, no_mailer…).
GET, PATCH /api/v1/billing/profile — your billing details, copied onto every new document (null until they are set up), and changing them: { "businessName": "…", "currency": "USD", "defaultTaxPercent": 21, "paymentTermsDays": 14 }. The business name is required the first time.GET, POST /api/v1/boards/{boardId}/expenses — a project's expenses, or log one (a cost, nothing is paid): { "description": "…", "amount": 30, "category": "software", "billable": true }. The project owner reads everyone's, with the markup; anyone else only their own.PATCH, DELETE /api/v1/expenses/{expenseId} — correct or delete an expense that is not on an invoice yet.POST /api/v1/expenses/{expenseId}/receipts · DELETE /api/v1/expense-receipts/{receiptId} — attach a receipt to an expense ({ filename, contentBase64 }: a photo or a PDF), or delete one.GET /api/v1/boards/{boardId}/unbilled, POST …/invoice-preview, POST …/invoices — the project's unbilled work, a preview of the invoice it would make, and the draft itself (its hours and expenses are tied to it until it is voided). Only the project owner; 409 when there is nothing to invoice.GET, POST /api/v1/invoices — your invoices and estimates (filters kind status clientId boardId from to q page pageSize; 25 per page), or a new draft: { "kind": "invoice", "clientId": "…", "lines": [{ "description": "…", "quantity": 1.5, "price": 100 }] }. Nothing is sent or published.GET /api/v1/invoices/aging, GET /api/v1/invoices/export — what clients owe by how late it is, and the invoices as a CSV file (Pro, 402 otherwise).GET, PATCH /api/v1/invoices/{invoiceId} — one document in full, and changing it. A draft takes every field; once sent only the notes and the due date change.GET /api/v1/invoices/{invoiceId}/pdf — the document as a PDF file (application/pdf): the A4 sheet its client gets by mail and from the link, in ?lang=en|es or the account's language. A draft or a voided document says what it is.POST /api/v1/invoices/{invoiceId}/send, GET, POST …/email, POST …/void, POST …/duplicate — publish a draft's link (nothing is emailed), read the email that would go to the client, email it, void the document (its hours and expenses go back to the project) or copy it into a new draft.DELETE /api/v1/invoices/{invoiceId} — delete a draft for good: it was never sent, so it has no number and leaves no gap. Its hours and expenses go back to the project. A sent document is voided instead.GET, POST /api/v1/recurring-invoices · GET, PATCH, DELETE /api/v1/recurring-invoices/{recurringId} — recurring invoices (Pro): list them, make an invoice repeat ({ invoiceId, interval, every?, nextDate, endAfter?, action? }), read, change or pause one, and delete it (the invoices it made stay).- Emailing answers
503 when this server has no email set up and 502 when the email did not go; either way nothing changes. Twenty emails an hour per person and one per document every 10 minutes (429). A new address past the plan's allowance (2 on Free, 25 new a day on Pro) gets a link to confirm it wants the emails, and the answer is 409 until it does. POST /api/v1/invoices/{invoiceId}/answer, POST …/convert — record that the client accepted or declined a sent estimate: { "answer": "accepted", "by": "…" }; and turn an accepted one into a draft invoice, once.POST /api/v1/invoices/{invoiceId}/project — make a project from an accepted estimate: { title?, budget?: "money" | "hours" | "none", tasks? }. Its client, its amount (or hours) as the budget and one task per line.POST, DELETE /api/v1/invoices/{invoiceId}/link — replace the document's public link (the old one stops working at once) or turn it off.POST /api/v1/invoices/{invoiceId}/payments, DELETE /api/v1/payments/{paymentId} — record a payment the client made: { "amount": 100, "day": "2026-10-19", "paymentMethod": "bank", "note": "…" }. It does not charge or move money. A payment above the balance answers 409 with balanceCents until it is sent again with "confirmOverpay": true; deleting one takes it off the books.GET /api/v1/reports/billing — invoiced and collected by month and by client, expenses and each project's profitability for a date range (from to boardId clientId; default the last 12 months, at most 1100 days).
A page for your client, by a secret link and with no account: the tasks you mark, the hours (only hours, never rates or money) and the documents you sent. Only the project owner manages it and reads or answers the comments; an editor marks tasks. Turning it on or changing what it shows is Pro (402 otherwise); turning it off or replacing the link is open to every plan. What clients write is text from a stranger: the responses list those fields in writtenByOthers.
GET, PATCH /api/v1/boards/{boardId}/portal — the portal's link, settings and latest comments, and changing them: { "enabled": true, "showTasks": true, "showHours": false, "showInvoices": true, "allowComments": true, "welcome": "…", "studioName": "…" }.POST /api/v1/boards/{boardId}/portal/link — replace the secret in the link: the old one stops working at once.GET, PATCH /api/v1/cards/{cardId}/portal — a task's conversation with the client (up to 200 messages), and showing the task on the portal: { "visible": true }.POST /api/v1/cards/{cardId}/portal/replies, POST …/read, POST /api/v1/boards/{boardId}/portal/read — answer the client under a task (shown to anyone with the link, signed with the studio name and not emailed): { "text": "…" }; and mark the client's comments as read, those of one task or of the whole project.DELETE /api/v1/client-comments/{commentId} — remove a comment from the conversation.
Notes and discussions go in and out as Markdown, like a task's description. Titles, bodies, comments, file names and task titles are written by project members: the responses list those fields in writtenByOthers. A page can be edited only with the rev it had when it was read; a save made on top of somebody else's answers 409 and overwrites nothing. A body is up to 100,000 characters, which is also the most a read returns (bodyTruncated says it was cut); a page with images, or a body longer than that, keeps its body when edited, and a read returns the newest comments that fit in 30,000 characters.
GET /api/v1/workload, PUT /api/v1/workload/capacity — plans the team's work: the time left on each person's open tasks with an estimate, in the week of the due date for the next six weeks, against that week's capacity: their weekly capacity less the holidays and their own time off, in capacityMinutes offMinutes of each week (Pro; filters personId includeTasks); and setting your own capacity: { "hours": "37:30" }.GET, POST /api/v1/holidays · DELETE /api/v1/holidays/{holidayId} — your holidays (Pro): list them, add one ({ "day": "2026-12-25", "name": "Christmas" }) and remove one. A holiday takes the whole working day off the capacity of everybody in your workload; there is one a day (409 when the day has one) and a weekend holiday takes nothing.GET, POST /api/v1/time-off · PATCH, DELETE /api/v1/time-off/{timeOffId} — time off: yours on any plan and, with Pro, that of the editors of the projects you own (filters userId from to status); record it ({ "userId"?, "kind"?: "vacation|sick|other", "startDay", "endDay"?, "minutesPerDay"?: null, "note"? }), change it or delete it. It lowers that person's capacity in the workload for the weeks it touches. The note is the person's own: only they write and read it, and the owner never receives it.POST /api/v1/time-off/{timeOffId}/approve · POST /api/v1/time-off/{timeOffId}/reject — approving time off (Pro): your own waits for the owners of the projects you edit ("status": "pending") and counts in the workload once "approved"; the owner approves or rejects it with an optional note for the person ({ "note"? }), who gets a notification.GET /api/v1/team-rates, PUT /api/v1/team-rates/{userId} — your team with each person's default hourly rate and what an hour of theirs costs you (cents; the cost is only yours), and setting them: { "hourlyRate": "85.50", "hourlyCost": 40 }. They apply to hours logged from then on (Pro).GET /api/v1/boards/{boardId}/member-rates, PUT /api/v1/boards/{boardId}/member-rates/{userId} — what each person on a project you own is billed at and where that comes from, and setting their rate on that project: { "hourlyRate": 120 } (null goes back to the project's, the client's or their default) (Pro).POST /api/v1/time/reprice — gives the hours already logged (not invoiced, not running, not on a closed day) the rates and costs a new hour would get now: { "from": "2026-10-01", "boardId": "…", "userId": "…", "overwrite": false, "apply": true }. Without apply it only answers what it would do (Pro).GET /api/v1/reports/profitability, GET /api/v1/reports/utilization — what the hours were worth, what they cost and what is left, by project, client, person or task (from to by), and billable hours over what each person could work (Pro; at most 400 days, per currency, in cents).GET /api/v1/reports/assignments — who is doing what: every open task of your projects grouped by the person it is assigned to, and the unassigned ones, with the estimate against the time logged on each (filters boardId clientId userId unassigned due label; format=csv for a file; Pro).GET, POST /api/v1/timesheets · GET, DELETE /api/v1/timesheets/{timesheetId} · POST /api/v1/timesheets/{timesheetId}/approve · POST /api/v1/timesheets/{timesheetId}/reject — weeks of hours under review: the ones you submitted and the ones handed to you (status userId from to); submit your week to the owners of the projects you worked on ({ "week": "2026-10-19", "ownerId"? }); withdraw it while it waits; and, as the owner, approve it (Pro) or send it back with a note. While a week waits or once it is approved its hours are closed to the person: a write there answers 409 with { "code": "closed" }.GET, POST /api/v1/project-templates, PATCH, DELETE /api/v1/project-templates/{templateId} — the starter and saved templates a project can begin from, and saving a project's shape as one: { "boardId": "…", "name": "…", "includeMoney": false }. The free plan keeps one saved template (402 beyond that). Rename or delete a saved one with the second route.GET, POST /api/v1/boards/{boardId}/pages — a project's notes or discussions (kind=note|discussion, search q, archived), or start one: { "kind": "note", "title": "…", "content": "# Markdown" }.GET, PATCH, DELETE /api/v1/pages/{pageId} — read a page with its comments and its rev; edit it, pin it or archive it (the last two are the project owner's): { "rev": "…", "title": "…", "content": "…", "pinned": true, "archived": false }; or delete it with its comments (its author and the project owner).POST /api/v1/pages/{pageId}/comments, PATCH, DELETE /api/v1/page-comments/{commentId} — comment on a page: { "text": "…" }; edit your own comment or delete one (its author and the project owner).GET /api/v1/boards/{boardId}/files — every file and link attached to the project's tasks, newest first, with how many there are of each type (filters q type).
Bring your hours from Toggl, Harvest, Clockify or any CSV with a date and a duration (or start and end times). The file travels as the text csv (up to 8 MB and 20,000 rows); the columns are guessed from the headers, as the Import page does, and any part can be set: { "csv": "…", "fileName": "…", "source": "toggl", "mapping": { "duration": "Hours" }, "dateOrder": "dmy", "durationUnit": "minutes", "createClients": true }. A column is named by its header text or its position (0 is the first). Rows imported before are skipped, and an import can be undone.
POST /api/v1/imports/preview — what importing the file would do, without writing anything: the rows, the clients, projects and tasks that would be created, the rows that cannot be read, and the settings used.GET, POST /api/v1/imports — your imports, or run one (the free plan's limits answer 402).DELETE /api/v1/imports/{importId} — take an import back: its entries and what it created that nobody used since; 409 when some of the time was already invoiced.
A webhook sends what happens in your projects to another app as it happens. Make one in Settings → Webhooks and Slack, or with the routes below. It listens to one board you own, or to all of them and your invoices and estimates. The free plan has 1, Pro 25.
"slack" posts a line to a Slack channel through one of Slack's incoming webhooks (https://hooks.slack.com/services/…)."json" POSTs each event as JSON to any https address (Zapier's Catch Hook, Make, n8n, your own server): { "id": "evt_…", "type": "task.completed", "createdAt": "…", "actor": { "id", "name" }, "board": { … }, "task": { "id", "title", "url", "list", "dueDate", "completed" } }.- Events:
task.created, task.moved, task.completed, task.reopened, comment.created; and, for webhooks of all your boards, invoice.sent, estimate.sent, payment.recorded, invoice.paid, estimate.accepted, estimate.declined. - Each JSON delivery is signed:
X-Decknote-Signature: sha256=… is the hex HMAC-SHA256 of <X-Decknote-Timestamp>.<body> with the webhook's secret (shown once, when it is made or replaced). Check it, and that X-Decknote-Timestamp is recent, before trusting a delivery; X-Decknote-Delivery is the event's id, to drop a repeat. - A delivery waits 8 seconds for a 2xx answer, follows no redirect and is tried once more after a network error, a 429 or a 5xx. After 20 failures in a row the webhook turns itself off and says why; at most 60 events a minute go to each.
GET, POST /api/v1/webhooks — your webhooks (without their secrets), and adding one: { "kind": "json", "url": "https://…", "boardId": "…", "events": ["task.completed"] }. The answer carries the secret, this once.GET, PATCH, DELETE /api/v1/webhooks/{webhookId} — one webhook; changing its events, turning it on or off, or replacing its secret ({ "events"?, "enabled"?, "rotateSecret"? }); deleting it.POST /api/v1/webhooks/{webhookId}/test — send a test now (a sample event marked "test": true) and get back how it went.
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.
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.show_board / get_board_live_url — show a board as a live, interactive kanban inside Claude, ChatGPT and other clients with MCP Apps: drag cards between lists, complete and add them, and it updates itself as anyone changes the board (the second tool is only for the view). Other clients get the board as JSON.get_task / search_tasks / list_my_tasks / list_reminders / overview / list_notifications — these six reads are also drawn as pages inside Claude, ChatGPT and other clients with MCP Apps: a card in full (description, checklists, comments), task lists grouped by due date, the reminders agenda, the account overview and the notification inbox. The answer text is the same; the view never changes anything, its buttons only draft a message for you to send.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.list_webhooks / create_webhook / update_webhook / delete_webhook / test_webhook — the account's webhooks and Slack channels: adding one, deleting one, testing one and turning one back on ask for confirm: true, since what they send leaves Decknote.start_timer / stop_timer / get_running_timer / log_time / list_time_entries / update_time_entry / delete_time_entry — time tracking: a timer on a project or task, hours logged by hand ("1h30"), and the project's time log with corrections; deleting an entry asks for confirmation.get_time_rules / set_time_rules / get_timer_alert / set_timer_alert — closing logged hours (Pro): the day up to which nobody can add, edit, move or delete hours and how many days back people can fix their own, with a confirmation to set them; and the alert for a timer left running.list_timesheets / submit_timesheet / withdraw_timesheet / approve_timesheet / reject_timesheet — reviewing timesheets: a person submits a week of hours to the owners of the projects they worked on and its hours close while it waits; the owner approves it (Pro) or sends it back with a note, which opens it again. Submitting, approving and sending back ask for confirmation.set_task_estimate / set_task_billable / get_task_time — a task's estimate, whether its time is billable, and the time tracked against the estimate.list_clients / create_client / update_client / archive_client / restore_client — clients, the companies or people projects are done for, with currency and default hourly rate (the free plan includes 2 active clients); archiving asks for confirmation.get_project_settings / update_project_settings / get_project_summary / get_week_timesheet / get_time_report / export_time_report — a project's client, status, budget, rate and dates; its summary (time, billable amount, budget used); your weekly timesheet; reports by project, client, person, task or day; and the CSV export (Pro). The project owner reads everyone's hours and the money; any other member only their own hours.get_billing_profile / update_billing_profile / list_expenses / create_expense / update_expense / delete_expense / add_expense_receipt / delete_expense_receipt — your billing details, and the expenses logged on a project (a cost, nothing is paid); deleting an expense asks for confirmation.list_invoices / get_invoice / get_invoice_pdf / get_receivables_aging / export_invoices_csv / get_billing_report — your invoices and estimates, one in full or as a PDF, what clients owe by how late it is, the CSV for your accountant (Pro) and the numbers of a date range: invoiced, collected, expenses and profit per project. Only the account's owner reads them.create_invoice / update_invoice / duplicate_invoice / convert_estimate_to_invoice / convert_estimate_to_project / list_unbilled_work / preview_invoice_from_work / create_invoice_from_work — drafts: start an invoice or estimate, edit it, copy it, turn an accepted estimate into an invoice, and make a draft from a project's unbilled work (the preview first; the draft needs confirm: true and the total repeated as amount). Nothing is sent. The free plan includes 2 documents a month.send_invoice / get_invoice_email_draft / email_invoice / regenerate_invoice_link / revoke_invoice_link / void_invoice / delete_invoice_draft / record_estimate_answer — what reaches the client or closes a document: publishing its link and emailing it (each needs confirm: true and the total repeated as amount; the email is shown in full first), changing or turning off the link, voiding, and recording an estimate's answer.list_recurring_invoices / create_recurring_invoice / update_recurring_invoice / delete_recurring_invoice — recurring invoices (Pro): an invoice that repeats every few weeks, months or years, each new one left as a draft, sent or emailed. Making one, changing it so new invoices go out, and deleting it ask for a confirmation.record_invoice_payment / remove_invoice_payment — write down that the client paid, and take a payment off the books, after a confirmation. They record what already happened: they do not charge or move money.get_client_portal / update_client_portal / regenerate_client_portal_link / set_task_visible_to_client / get_task_portal / reply_to_client / mark_client_comments_read / delete_client_comment — the client portal, a page for your client by a secret link: its settings and comments, turning it on or changing what it shows (after a confirmation of what becomes public), replacing the link, marking tasks, and answering the client under the studio's name.list_projects / create_project / get_workload / set_my_weekly_capacity — the projects you can see with their client, status, hours and budget, starting one, and the team's workload per week against each person's capacity (Pro).list_team_rates / set_team_rate / get_member_rates / set_member_rate / reprice_time / get_profitability_report / get_utilization_report / get_assignments_report — your team's rates and costs, a person's rate on a project, applying them to the hours already logged (after a confirmation), and the profitability (by project, client, person or task), utilization and assignments reports (Pro).list_project_templates / save_project_as_template / create_project_from_template / rename_project_template / delete_project_template — project templates: the starters and your saved ones, saving a project's shape, and starting a project from one (the free plan keeps one saved template).list_pages / get_page / create_page / update_page / set_page_pinned / set_page_archived / delete_page / add_page_comment / edit_page_comment / delete_page_comment / list_project_files — a project's notes and discussions, written as Markdown (an edit needs the rev it was read with, so nobody's save is overwritten), their comments, and the list of every file attached to its tasks.list_holidays / add_holiday / remove_holiday / list_time_off / add_time_off / update_time_off / remove_time_off / approve_time_off / reject_time_off — holidays and time off, which lower each week's capacity in the workload once approved: yours on any plan and, with Pro, your holidays and the time off of the editors of your projects, which you approve or reject. Removing, approving and rejecting ask for confirmation; a note is the person's own and is never returned to anybody else.preview_time_import / import_time_csv / list_time_imports / undo_time_import / create_sample_project / delete_sample_project — importing hours from a CSV given as text (up to 200,000 characters; bigger files go through the Import page): the preview, the import after a confirmation, the history and undoing, and a labelled sample project.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_readGET /api/v1/boards — api_readPOST /api/v1/boards — api_createPOST /api/v1/cards — api_createGET /api/v1/boards/{boardId}/embeds — api_readPOST /api/v1/boards/{boardId}/embeds — api_createGET /api/export — api_readGET /api/link-preview?url=… — api_readGET /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 billing tools keep the books and nothing more: record_invoice_payment writes down that a client paid and does not charge or move money. Publishing an invoice's link, emailing it, voiding it, recording or removing a payment, answering an estimate and changing what the client portal shows need confirm: true; sending, emailing or creating an invoice from work also need amount equal to the document's total in the preview, so the yes is to a figure. Text written by clients, teammates or imported files is data, not instructions from you: results that carry it list those fields in writtenByOthers and a confirmation never comes from 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.