Skip to content

Workspace Data

Tags, tasks, search, attachments, and templates.

Updated View as Markdown

Everything on this page is under /api/workspaces/:workspaceId/... and requires Workspace Member. See Conventions for the shared pagination rule these list endpoints follow.

Tags

See Tags for how #tag is parsed out of a log’s markdown.

GET /api/workspaces/:workspaceId/tags

GETWorkspace Member

Every tag in the workspace, with how many (non-deleted) logs carry it — sorted by count, then name.

Query Parameters

Field Type Required Notes
from string No Only count logs on or after this date
to string No Only count logs on or before this date
page number No Page number

Response

{ "tags": [{ "id": "...", "name": "postgres", "count": 3 }], "hasMore": false, "page": 1, "limit": 10 }

Tasks

See Tasks for the - [ ] and due-date syntax that produces these.

GET /api/workspaces/:workspaceId/tasks

GETWorkspace Member

Query Parameters

Field Type Required Notes
day string No Only tasks written into this day’s logs — unpaginated
board string No What the day board shows for this date: undated tasks written that day, plus any task (from any day) due on it — unpaginated
from string No Only logs on or after this date
to string No Only logs on or before this date
status pending | completed No Filter by completion
page number No Page number, used when neither day nor board is set

Response

{
  "tasks": [{ "id": "...", "logId": "...", "text": "Ship the release notes", "done": false, "dueDate": "2026-09-07", "lineNo": 1, "completedAt": null, "logTitle": "Standup notes", "day": "2026-09-06" }],
  "hasMore": false, "page": 1, "limit": 10
}

PATCH /api/workspaces/:workspaceId/tasks/:taskId

PATCHWorkspace Member

Ticks or unticks a task. This rewrites the - [ ]/- [x] line in the log’s actual markdown body — the file is the source of truth, which is why every task tracks lineNo. Fails with 409 CONFLICT if that line no longer looks like a task (the log was edited since the task was parsed).

Request body

Field Type Required
done boolean Yes

Response: { "log": {...} } — the whole updated log, same shape as GET /logs/:logId.

See Search for the Cmd+K palette this backs.

GET /api/workspaces/:workspaceId/search

GETWorkspace Member

Full-text search across logs (SQLite FTS5, unicode61 tokenizer, ranked with bm25), plus a plain LIKE match against tag names and task text. Not paginated — capped at 24 combined results.

Query Parameters

Field Type Required Notes
q string Yes Up to 500 characters. Empty string returns []

Response

{
  "results": [
    { "type": "log", "id": "...", "title": "Postgres tuning notes", "snippet": "Bumped <mark>work_mem</mark> and re-ran…", "day": "2026-09-05" },
    { "type": "tag", "id": "...", "title": "#postgres", "snippet": "", "day": null },
    { "type": "task", "id": "...", "title": "Ship the release notes", "snippet": "Standup notes", "day": "2026-09-06" }
  ]
}

Attachments

See Attachments for paste-to-upload and storage backends.

GET /api/workspaces/:workspaceId/attachments

GETWorkspace Member

Query Parameters

Field Type Required Notes
from string No Only attachments on logs on or after this date
to string No Only attachments on logs on or before this date
extension string No Filter by file extension, e.g. png
page number No Page number

Response

{
  "attachments": [{ "id": "...", "logId": "...", "workspaceId": "...", "filename": "01JB...-screenshot.png", "mime": "image/png", "size": 48213, "storageKey": "workspaces/personal-demo/2026/09/06/_files/01JB...-screenshot.png", "createdAt": "...", "logTitle": "Deploy notes", "day": "2026-09-06" }],
  "hasMore": false, "page": 1, "limit": 10
}

GET /api/workspaces/:workspaceId/attachments/extensions

GETWorkspace Member

Every distinct file extension in the workspace, for populating a filter dropdown.

Response: { "extensions": ["jpg", "pdf", "png"] }

POST /api/workspaces/:workspaceId/attachments

POSTWorkspace Member

Uploads a file and attaches it to a log. multipart/form-data, not JSON.

Form fields

Field Type Required Notes
file file Yes Rejected with 400 if missing, 503 if the instance has no storage backend configured
logId string Yes The log to attach it to

Rejected with 400 VALIDATION if the file exceeds the instance’s maxAttachmentSize or its MIME type isn’t in allowedFileTypes (see Admin → Instance Settings).

Response: 201 with { "id": "...", "filename": "01JB...-screenshot.png", "relativeLink": "./_files/01JB...-screenshot.png", "mime": "image/png", "size": 48213 }. Paste relativeLink into the log’s markdown body (![alt](./_files/...) for an image) to have it render inline — that’s what the editor’s paste handler does automatically.

GET /api/workspaces/:workspaceId/attachments/:attachmentId/file

GETWorkspace Member

Streams the raw file bytes with its original content-type and an inline content-disposition. 404 if storage is off or the object is missing.

DELETE /api/workspaces/:workspaceId/attachments/:attachmentId

DELETEWorkspace Member

Deletes the stored file and its database row. Doesn’t touch the ![...] link left behind in the log’s body — remove that separately if you don’t want a broken reference.

Response: { "ok": true }

Templates

See Daily Templates for today_only vs. any_visited_day.

GET /api/workspaces/:workspaceId/templates

GETWorkspace Member

Response: { "templates": [{ "id": "...", "workspaceId": "...", "title": "Standup", "body": "...", "enabled": true, "createdAt": "..." }] }

POST /api/workspaces/:workspaceId/templates

POSTWorkspace Member

Request body

Field Type Required Notes
body string Yes Markdown — becomes a new log’s body each time the template applies
title string | null No
enabled boolean No Defaults to true

Response: { "template": {...} }

PUT /api/workspaces/:workspaceId/templates/:id

PUTWorkspace Member

Request body — all optional: title, body, enabled.

Response: { "template": {...} }

DELETE /api/workspaces/:workspaceId/templates/:id

DELETEWorkspace Member

Response: { "success": true } — this endpoint and PUT /templates/mode below use success rather than the ok key every other mutation in this API uses.

PUT /api/workspaces/:workspaceId/templates/mode

PUTWorkspace Member

Sets whether templates apply only to today, or to any day the board is opened for.

Request body

Field Type Required
mode today_only | any_visited_day Yes

Response: { "success": true }

POST /api/workspaces/:workspaceId/templates/apply

POSTWorkspace Member

Applies every enabled template to a day, creating one new log per template — but only once per (workspace, day) pair, and only if today_only mode’s date check passes. The day board calls this itself every time you open a day, so you’ll rarely need to call it directly.

Request body

Field Type Required
day string Yes

Response: { "applied": true } if templates were generated (or there were none enabled to generate), { "applied": false } if this day was already applied, or if today_only mode and day isn’t today.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close