Plano API
Read and change cards from your scripts and services, get events by webhooks and put your tasks in your calendar.
Access
Create a token in Settings → Integrations and send it in the Authorization header. Responses are JSON.
curl https://api.plano.team/users/me \
-H "Authorization: Bearer <token>"- A token has the rights of whoever created it. If that person is deactivated, the token stops working.
- When the plan has ended the workspace is read-only: writes return 402.
- Errors come with a 4xx code and a message field. 401 means no token or a revoked one, 403 means a missing right.
Quick start
Find a project and a column, then create a card:
# 1. list projects
curl https://api.plano.team/projects -H "Authorization: Bearer <token>"
# 2. the board: columns and cards
curl https://api.plano.team/projects/<projectId>/board -H "Authorization: Bearer <token>"
# 3. a new card in a column
curl -X POST https://api.plano.team/cards \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"columnId": "<columnId>", "title": "Hello from the API", "priority": "HIGH", "dueDate": "2026-11-10"}'Main endpoints
API address: https://api.plano.team. Dates are ISO 8601. These endpoints are stable; other endpoints the app uses may change.
| GET | /users/me | You: name, role, rights |
| GET | /users | People in the workspace |
| GET | /projects | List projects |
| POST | /projects | Create a project (title, optional templateId, startDate, deadline) |
| GET | /projects/{id}/board | The project board: columns with cards |
| GET | /cards/search?q= | Search cards by title, description or key |
| GET | /cards/{id} | A whole card: subtasks, comments, history |
| POST | /cards | Create a card (columnId and title are required) |
| PATCH | /cards/{id} | Change card fields |
| POST | /cards/{id}/move | Move to a column (columnId, optional position) |
| DELETE | /cards/{id} | Delete a card (needs the delete right) |
| POST | /cards/{id}/comments | Add a comment |
| POST | /cards/{id}/checklist | Add a subtask (text) |
| GET | /labels | List labels |
| POST | /labels | Create a label (name, color) |
Card fields for create and update: title, description, priority (LOW, MEDIUM, HIGH), startDate, dueDate, estimateHours, assigneeIds, labelIds. A comment takes text and optional mentionIds.
Webhooks
Add an address in Settings → Integrations and Plano will POST JSON to it when things happen. The address must be public and start with https://. Pick the events you need, or none to get them all.
card.createda card was createdcard.updatedcard fields changed; changes lists whichcard.moveda card moved to another column; from and to are column titlescard.deleteda card was deleted; card holds its last statecomment.createda new comment; comment holds the text and author
Example request body:
{
"event": "card.moved",
"createdAt": "2026-11-03T09:15:00.000Z",
"actor": { "id": "clx1…", "name": "Anna" },
"card": {
"id": "clx2…",
"key": "TSK-12",
"title": "Prepare the brief",
"priority": "HIGH",
"dueDate": "2026-11-10T00:00:00.000Z",
"project": { "id": "clx3…", "title": "Website" },
"column": { "id": "clx4…", "title": "In progress" },
"assignees": [{ "id": "clx1…", "name": "Anna" }],
"labels": [{ "id": "clx5…", "name": "Feature", "color": "blue" }],
"url": "https://app.example.com/projects/clx3…?card=clx2…"
},
"from": "Backlog",
"to": "In progress"
}Headers:
X-Plano-Event: the event typeX-Plano-Timestamp: send time in secondsX-Plano-Signature:sha256=<hex>, an HMAC-SHA256 of “X-Plano-Timestamp.body” with the webhook's secret. Check the signature and the time to reject replays.
import { createHmac, timingSafeEqual } from "crypto";
function isValid(rawBody, headers, secret) {
const expected = createHmac("sha256", secret)
.update(headers["x-plano-timestamp"] + "." + rawBody)
.digest("hex");
const got = headers["x-plano-signature"].replace("sha256=", "");
return got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}Answer with a 2xx within 8 seconds. Otherwise Plano retries twice more (after 5 and 30 seconds). The log of recent deliveries is in settings, where you can also send a test event and change the secret.
Task calendar
In your profile you can get a personal calendar link in iCal format. Add it to Google Calendar, Apple Calendar or Outlook as a subscription: it shows your unfinished cards that have a due date. The link is secret and can be replaced at any time.