2/25/2026
API Reference
Complete endpoint reference for the Leaderbook REST API — authentication, request/response shapes, error codes, and rate limits.

Overview
Base URL: https://leaderbook.app/api/v1
All requests and responses use JSON. Dates are ISO 8601 UTC strings. IDs are CUID strings.
Quick endpoint index
| Method | Path | Description |
|---|---|---|
| GET | /notes | List notes |
| GET | /notes/:id | Get note |
| POST | /notes | Create note |
| PATCH | /notes/:id | Update note |
| DELETE | /notes/:id | Delete note |
| POST | /notes/:id/suggest | Submit content suggestion |
| GET | /notes/:id/suggestions | List suggestions |
| GET | /tasks | List tasks |
| GET | /tasks/:id | Get task |
| POST | /tasks | Create task |
| PATCH | /tasks/:id | Update task |
| DELETE | /tasks/:id | Delete task |
| POST | /tasks/:id/suggest | Submit task suggestion |
| POST | /suggestions/:id/approve | Approve suggestion |
| POST | /suggestions/:id/reject | Reject suggestion |
| GET | /notebooks | List notebooks |
| GET | /notebooks/:id | Get notebook |
| POST | /notebooks | Create notebook |
| GET | /workspaces | List workspaces |
| POST | /workspaces | Create workspace |
| POST | /workspaces/:id/members | Invite member |
| DELETE | /workspaces/:id/members/:userId | Remove member |
| GET | /audit-log | Audit log |
Authentication
Every request must include an API key in the Authorization header.
Authorization: Bearer lb_live_<prefix>_<secret>Key format: lb_live_ + 8-char prefix + _ + 24-char secret. Create and manage keys in Settings → API Keys. The raw secret is shown once at creation and never again.
Scope bitmask
| scope | Label | Operations |
|---|---|---|
| 1 | read | GET |
| 2 | write | POST, PATCH, DELETE |
| 3 | read+write | All |
Access levels
| Key configuration | Accessible resources |
|---|---|
| No workspaceId, no notebookId | All personal notes, tasks, notebooks, workspaces, and audit log |
| workspaceId set | All notebooks in that workspace, workspace membership, and workspace audit log |
| notebookId set | That notebook only |
A workspace-scoped key with scope: 2 (write) can also invite and remove workspace members.
Errors
json{
"error": {
"code": "NOTE_NOT_FOUND",
"message": "Note not found or not accessible with this key.",
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}The X-Request-Id response header echoes the requestId.
| HTTP | Codes |
|---|---|
| 400 | VALIDATION_ERROR MISSING_FIELD INVALID_MARKDOWN |
| 401 | UNAUTHENTICATED |
| 403 | INSUFFICIENT_SCOPE KEY_NOTEBOOK_MISMATCH KEY_WORKSPACE_MISMATCH ITEM_LIMIT_REACHED NOT_WORKSPACE_MEMBER |
| 404 | NOTE_NOT_FOUND TASK_NOT_FOUND NOTEBOOK_NOT_FOUND SUGGESTION_NOT_FOUND WORKSPACE_NOT_FOUND |
| 409 | SUGGESTION_ALREADY_RESOLVED |
| 429 | RATE_LIMIT_EXCEEDED |
| 500 | INTERNAL_ERROR |
Rate Limits
100 requests per minute per user, shared across session and all API keys. On exceed: 429 + Retry-After: 60 header.
Pagination
All list endpoints use cursor-based pagination.
Query parameters: limit (default 20, max 100), cursor (last ID from previous page)
Response shape
json{ "data": [...], "nextCursor": "clxnote99" }Pass nextCursor as cursor in the next request. null means last page.
Content Format
Note and task content is sent and received as Markdown. Leaderbook converts to HTML for storage and back to Markdown for API responses.
Supported syntax
| Markdown | Meaning | ||||||
|---|---|---|---|---|---|---|---|
| # H1 ## H2 ### H3 | Headings (levels 1–3) | ||||||
| **bold** | Bold | ||||||
| *italic* | Italic | ||||||
| ~~strikethrough~~ | Strikethrough | ||||||
| __underline__ | Underline | ||||||
| ` code ` | Inline code | ||||||
| [text](url) | Link | ||||||
| - item | Bullet list | ||||||
| 1. item | Ordered list | ||||||
| > text | Blockquote | ||||||
| ` | Code block | ||||||
| --- | Horizontal rule | ||||||
| #tag | Attaches a tag | ||||||
| @name | Attaches a person mention | ||||||
| > **Why:** text | Why callout block | ||||||
| > **Decision:** text | Decision callout block | ||||||
| `\ | col \ | col \ | + \ | --- \ | --- \ | ` | GFM pipe table |
Not supported via API: images, text alignment, highlight colours.
Notes
List notes
GET /api/v1/notes
| Param | Type | Description |
|---|---|---|
| notebookId | string | Filter by notebook |
| archived | boolean | Include archived (default false) |
| limit | number | Page size |
| cursor | string | Pagination cursor |
bashcurl "https://leaderbook.app/api/v1/notes?notebookId=clxnb1&limit=5" \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [{
"id": "clxnote1",
"content": "# Q2 Planning\n\n> **Decision:** Use PostgreSQL\n\n#q2 @alice",
"notebookId": "clxnb1",
"hasDecision": true,
"archived": false,
"targetAt": null,
"followUpAt": null,
"tags": [
{ "id": "clxtag1", "name": "q2", "kind": "TAG" },
{ "id": "clxtag2", "name": "alice", "kind": "PERSON" }
],
"createdAt": "2026-02-25T09:00:00Z",
"updatedAt": "2026-02-25T09:00:00Z"
}],
"nextCursor": null
}A notebook-scoped key auto-filters to its own notebook.
Get a note
GET /api/v1/notes/:id
bashcurl https://leaderbook.app/api/v1/notes/clxnote1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"id": "clxnote1",
"content": "# Q2 Planning\n\n...",
"notebookId": "clxnb1",
"hasDecision": true,
"archived": false,
"targetAt": null,
"followUpAt": null,
"tags": [{ "id": "clxtag1", "name": "q2", "kind": "TAG" }],
"pendingSuggestion": null,
"createdAt": "2026-02-25T09:00:00Z",
"updatedAt": "2026-02-25T09:00:00Z"
}pendingSuggestion is null or a suggestion object when a change is awaiting review.
Create a note
POST /api/v1/notes
| Field | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Markdown body |
| notebookId | string | Yes | Target notebook |
| targetAt | ISO date | No | Surface in Focus view |
| followUpAt | ISO date | No | Follow-up reminder |
bashcurl -X POST https://leaderbook.app/api/v1/notes \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{
"content": "# Standup 2026-02-25\n\n> **Decision:** Skip standup on Fridays\n\n#standup @alice",
"notebookId": "clxnb1"
}'Response 201 — full note object. hasDecision is set automatically from content.
Update a note
PATCH /api/v1/notes/:id
Only included fields are changed. A version snapshot is saved before overwriting content.
| Field | Type | Description |
|---|---|---|
| content | string | Replacement Markdown |
| notebookId | string | Move to different notebook |
| targetAt | ISO date or null | Change or clear |
| followUpAt | ISO date or null | Change or clear |
| archived | boolean | Archive / un-archive |
bashcurl -X PATCH https://leaderbook.app/api/v1/notes/clxnote1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{ "content": "# Updated content\n\n#standup", "archived": false }'Response 200 — updated note object.
Delete a note
DELETE /api/v1/notes/:id
bashcurl -X DELETE https://leaderbook.app/api/v1/notes/clxnote1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{ "ok": true }Suggest a change
POST /api/v1/notes/:id/suggest
Proposes a content revision without applying it. The note owner reviews the diff inline. An existing PENDING suggestion is automatically superseded.
| Field | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Full proposed replacement (Markdown) |
| rationale | string | No | Explanation shown to the reviewer |
bashcurl -X POST https://leaderbook.app/api/v1/notes/clxnote1/suggest \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{
"content": "# Q2 Planning\n\n- Ship API v1\n- Hire backend engineer\n\n#q2",
"rationale": "Added hiring goal from offsite"
}'json{
"id": "clxsug1",
"status": "PENDING",
"originalContent": "# Q2 Planning\n\n- Ship API v1\n\n#q2",
"suggestedContent": "# Q2 Planning\n\n- Ship API v1\n- Hire backend engineer\n\n#q2",
"rationale": "Added hiring goal from offsite",
"createdAt": "2026-02-25T10:05:00Z"
}List suggestions for a note
GET /api/v1/notes/:id/suggestions
bashcurl https://leaderbook.app/api/v1/notes/clxnote1/suggestions \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [{
"id": "clxsug1",
"status": "PENDING",
"suggestedContent": "# Q2 Planning\n\n...",
"rationale": "Added hiring goal from offsite",
"createdAt": "2026-02-25T10:05:00Z"
}],
"nextCursor": null
}Tasks
Tasks have a title, optional notes (Markdown), status, and priority. Tags and mentions in notes are extracted automatically.
Status values: TODO IN_PROGRESS BLOCKED DONE
Priority values: LOW MEDIUM HIGH URGENT
List tasks
GET /api/v1/tasks
| Param | Description |
|---|---|
| notebookId | Filter by notebook |
| status | TODO IN_PROGRESS BLOCKED DONE |
| archived | Include archived (default false) |
| limit | Page size |
| cursor | Pagination cursor |
bashcurl "https://leaderbook.app/api/v1/tasks?status=TODO&limit=10" \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [{
"id": "clxtask1",
"title": "Write endpoint tests",
"notes": "Cover auth and rate limiting. #backend @alice",
"status": "TODO",
"priority": "HIGH",
"archived": false,
"dueAt": "2026-03-01T00:00:00Z",
"targetAt": null,
"followUpAt": null,
"tags": [
{ "id": "clxtag6", "name": "backend", "kind": "TAG" },
{ "id": "clxtag7", "name": "alice", "kind": "PERSON" }
],
"createdAt": "2026-02-25T10:00:00Z",
"updatedAt": "2026-02-25T10:00:00Z"
}],
"nextCursor": null
}Get a task
GET /api/v1/tasks/:id
bashcurl https://leaderbook.app/api/v1/tasks/clxtask1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"Response 200 — single task object (same shape as list item).
Create a task
POST /api/v1/tasks
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Task title |
| notebookId | string | Yes | Target notebook |
| notes | string | No | Markdown notes |
| status | string | No | Default TODO |
| priority | string | No | Default MEDIUM |
| dueAt | ISO date | No | Due date |
| targetAt | ISO date | No | Focus view date |
| followUpAt | ISO date | No | Follow-up reminder |
bashcurl -X POST https://leaderbook.app/api/v1/tasks \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{
"title": "Write API docs",
"notebookId": "clxnb1",
"notes": "Cover auth, pagination, and all endpoints. #docs @alice",
"priority": "HIGH",
"dueAt": "2026-03-07T00:00:00Z"
}'Response 201 — full task object.
Update a task
PATCH /api/v1/tasks/:id
All fields optional. Only included fields are changed.
bash# Mark done
curl -X PATCH https://leaderbook.app/api/v1/tasks/clxtask1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{ "status": "DONE" }'Response 200 — updated task object.
Delete a task
DELETE /api/v1/tasks/:id
bashcurl -X DELETE https://leaderbook.app/api/v1/tasks/clxtask1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{ "ok": true }Suggest a change to a task
POST /api/v1/tasks/:id/suggest
Proposes a replacement for the task's notes field.
bashcurl -X POST https://leaderbook.app/api/v1/tasks/clxtask1/suggest \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{
"content": "Cover auth, pagination, all endpoints, and webhook events. #docs @alice",
"rationale": "Webhook events added to scope"
}'Response 201 — same shape as note suggestion.
Suggestions
A suggestion is a proposed content change awaiting the resource owner's review. The owner sees a diff inline in the editor.
State machine: PENDING → APPROVED | REJECTED | SUPERSEDED
Submitting a new suggestion for a resource with an existing PENDING one automatically moves the old one to SUPERSEDED.
Approve a suggestion
POST /api/v1/suggestions/:id/approve
Applies the suggested content. A version snapshot of the original is saved first.
bashcurl -X POST https://leaderbook.app/api/v1/suggestions/clxsug1/approve \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{ "ok": true, "status": "APPROVED" }Reject a suggestion
POST /api/v1/suggestions/:id/reject
Dismisses the suggestion. Content is unchanged.
bashcurl -X POST https://leaderbook.app/api/v1/suggestions/clxsug1/reject \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{ "ok": true, "status": "REJECTED" }Notebooks
Every note and task belongs to exactly one notebook.
List notebooks
GET /api/v1/notebooks
bashcurl https://leaderbook.app/api/v1/notebooks \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [{
"id": "clxnb1",
"name": "Engineering",
"color": "blue",
"workspaceId": "clxws1",
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-02-01T00:00:00Z"
}],
"nextCursor": null
}Get a notebook
GET /api/v1/notebooks/:id
bashcurl https://leaderbook.app/api/v1/notebooks/clxnb1 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"Response 200 — single notebook object.
Create a notebook
POST /api/v1/notebooks
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Notebook name (max 40 chars) |
| workspaceId | string | No | Workspace (defaults to personal) |
| color | string | No | Display colour hint |
bashcurl -X POST https://leaderbook.app/api/v1/notebooks \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{ "name": "Product Decisions", "workspaceId": "clxws1" }'Response 201 — created notebook object. Notebook-scoped keys cannot create notebooks.
Workspaces
A workspace-scoped key (workspaceId set) can read and, with scope: 2, manage the membership of its own workspace. A personal key (no workspaceId) has access to all workspaces owned by the key's user.
List workspaces
GET /api/v1/workspaces
Returns workspaces the key (or session user) has access to. A workspace-scoped key returns only its own workspace.
bashcurl https://leaderbook.app/api/v1/workspaces \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [{
"id": "clxws1",
"name": "Engineering Team",
"role": "OWNER",
"members": [
{ "userId": "clxu1", "name": "Alice", "email": "alice@example.com", "role": "OWNER" },
{ "userId": "clxu2", "name": "Bob", "email": "bob@example.com", "role": "MEMBER" }
],
"createdAt": "2026-01-01T00:00:00Z"
}],
"nextCursor": null
}Create a workspace
POST /api/v1/workspaces
Requires scope: 2 (write). A workspace-scoped key cannot create additional workspaces.
bashcurl -X POST https://leaderbook.app/api/v1/workspaces \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{ "name": "Engineering Team" }'Response 201 — created workspace object.
Invite a member
POST /api/v1/workspaces/:id/members
Requires scope: 2 (write) and Owner role in the target workspace. The person must already have a Leaderbook account.
bashcurl -X POST https://leaderbook.app/api/v1/workspaces/clxws1/members \
-H "Authorization: Bearer lb_live_abcd1234_XXXX" \
-H "Content-Type: application/json" \
-d '{ "email": "bob@example.com" }'json{ "workspaceId": "clxws1", "userId": "clxu2", "role": "MEMBER" }Remove a member
DELETE /api/v1/workspaces/:workspaceId/members/:userId
Requires scope: 2 (write). Owners can remove any member; members can remove themselves.
bashcurl -X DELETE https://leaderbook.app/api/v1/workspaces/clxws1/members/clxu2 \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{ "ok": true }API Key Management
API key creation, rotation, and revocation are available only through the Leaderbook UI (Settings → API Keys). These operations are not exposed via the REST API — an API key cannot create or manage other API keys.
Audit Log
Paginated log of every API action on your account. A workspace-scoped key returns only events for that workspace; a personal key returns all events for the user.
GET /api/v1/audit-log
| Param | Description |
|---|---|
| limit | Page size (default 20) |
| cursor | Pagination cursor |
| resourceType | note task notebook |
| apiKeyId | Filter to a specific key |
bashcurl "https://leaderbook.app/api/v1/audit-log?resourceType=note&limit=20" \
-H "Authorization: Bearer lb_live_abcd1234_XXXX"json{
"data": [
{
"id": 42,
"action": "note.create",
"resourceType": "note",
"resourceId": "clxnote2",
"apiKeyName": "My integration",
"apiKeyPrefix": "lb_live_abcd1234",
"createdAt": "2026-02-25T10:00:00Z"
},
{
"id": 41,
"action": "task.update",
"resourceType": "task",
"resourceId": "clxtask1",
"apiKeyName": null,
"apiKeyPrefix": null,
"createdAt": "2026-02-25T09:45:00Z"
}
],
"nextCursor": null
}apiKeyName and apiKeyPrefix identify which key performed the action.
