API
Authentication
Create a personal token under Settings, API tokens. Send it on every request. Tokens are read-only or read and write, are shown once, and can be revoked at any time. Limit: 120 requests a minute per token.
curl -H "Authorization: Bearer slt_YOUR_TOKEN" https://YOUR-DOMAIN/api/boards
Tokens cannot call /api/auth, /api/tokens or /api/admin. Writes need no CSRF header when a bearer token is used. Errors are JSON: {"error": "..."}.
Main endpoints
| Method and path | Purpose |
|---|---|
| GET /api/boards | List boards (?scope=archived or templates) |
| POST /api/boards | Create a board {title} |
| GET /api/boards/:id | Board with lists, cards and labels |
| POST /api/boards/:id/lists | Add a list {title} |
| POST /api/cards | Create a card {list_id, title, description_md, due_at, start_at} |
| GET /api/cards/:id | Card with checklists, comments, attachments |
| PATCH /api/cards/:id | Change title, description_md, due_at, start_at |
| POST /api/cards/:id/move | Move {list_id, before_id, after_id} |
| POST /api/cards/:id/comments | Comment {body_md} |
| GET /api/calendar/events | Calendar events |
| GET /api/data/export.json | Full export (also export.csv, export.ics, /api/data/boards/:id/export.json) |
| POST /api/data/import/trello | Body: the Trello JSON, up to 5 MB (also planka, slate) |
| POST /api/data/import/auto | Detects Trello, Planka or Slate JSON and imports it |
| POST /api/calendar/move | Shift cards or events by whole days {items:[{kind, id, delta_days}]} |
| POST /api/calendar/board-due | Set or clear a board's due date {board_id, date|null} |
| POST /api/boards/bulk | Restore or delete archived boards {ids, action} |
| POST /api/bulk/restore | Restore archived cards {card_ids} |
| POST /api/bulk/delete | Permanently delete archived cards {card_ids} |
| GET /api/embed-thumb/:provider?id= | Cached video thumbnail (youtube, vimeo, framerate) |
Webhooks
Add a URL under Settings, Webhooks. It must be https on a public hostname. Slate sends a POST with a 5 second timeout and retries once. The last 20 deliveries are visible in Settings. Events: card.created, card.moved, card.delivered, card.due_changed.
{
"id": "delivery id",
"event": "card.moved",
"created_at": "2026-10-25T09:00:00.000Z",
"data": {
"card": { "id": "...", "title": "...", "board_id": "...", "list_id": "...", "due_at": null },
"from_list": "To do", "to_list": "Doing",
"actor": { "id": "...", "name": "..." }
}
}
Headers: X-Slate-Event, X-Slate-Delivery, X-Slate-Timestamp (Unix seconds) and X-Slate-Signature, which is sha256= followed by the hex HMAC-SHA256 of timestamp, a full stop, then the raw body, keyed with your webhook secret. Reject deliveries whose timestamp is more than five minutes old.
// Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, headers, rawBody) {
const ts = headers["x-slate-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const want = "sha256=" + createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
const got = headers["x-slate-signature"] || "";
return got.length === want.length && timingSafeEqual(Buffer.from(got), Buffer.from(want));
}