Files
narl-workspace/docs/wiki/API.md
T
nvrl 0245402ead typst: a block of it in markdown is typeset on the server
A ```typst (or ```typ) block is compiled by the typst crate into SVG and
shown as an image where it stands, so math, tables and figures can be
written in typst beside the markdown around them. It shows its source while
it is set, and the error typst gives, with the block's line, when it cannot
be.

Each block is a document of its own: its source is the only file in its
world and the fonts are typst-assets', inside the binary, so nothing is read
from disk or fetched — packages and images are refused. The page fits what
is on it, is transparent, and carries the theme's text colour. Answers are
cached by source, two blocks are laid out at a time off the async threads,
and comemo's memo is evicted after each compile.

A share page asks POST /api/share/{token}/typst, which takes the reader's
cookie and typesets only a block the shared document holds.

typst brings a palette crate whose AsRef impls on arrays made four
`kek.as_ref().into()` in the vault ambiguous; they deref instead.
2026-10-21 15:41:45 +02:00

5.4 KiB

API

Everything except the login, the health check and the two share routes requires the session cookie; /api/capture takes a token instead. Media answers Range requests, so a video seeks, sealed or not.

method path purpose
GET /api/health public: up, and the database answers — for a supervisor
POST /api/login, /api/logout session; /api/logout?everywhere=true ends every one
GET /api/me current user
GET /api/sessions every signed-in browser, the one seen last first
DELETE /api/sessions/{id} sign another browser out, and lock the vault
GET/POST /api/spaces the spaces / create one
GET/POST /api/nodes children (?parent=) or search (?q=, ?space=; a file matched by its text has in_text and the words around the match as excerpt, each matched word between U+0002 and U+0003) / create, from a template with template_id
GET/PUT/DELETE /api/nodes/{id} read / update only the fields sent — name, body, created_at, has_board; with base_updated_at, refused with 409 once it was saved since / delete into the trash, subtree and all — or for good, for something already in it
GET/DELETE /api/trash what was deleted, the last first / empty it
DELETE /api/trash/{id} delete one thing in the trash for good
POST /api/trash/{id}/restore back where it was deleted from, or to its space when that folder is gone
GET /api/spaces/{id}/board the lists and cards of one space
GET /api/agenda open cards due within a week or in hand, on every board, whether the diary has today, its entries on_this_day in earlier years, and today in WORKSPACE_TIMEZONE, with its bounds
GET /api/diary/days?month=2026-10 the diary's entries in a month, each with its local day
GET /api/diary/around/{id} the entries before and after a diary entry, by date
GET /api/nodes/{id}/templates the templates of the space the node is in
POST /api/capture { text, to: "card" | "diary", space? }, with a session or Authorization: Bearer a token
GET/POST /api/tokens the capture tokens / make one, { name }, answered with the token this once
DELETE /api/tokens/{id} remove a capture token
POST /api/spaces/{id}/lists add a list
PUT/DELETE /api/lists/{id} rename / delete a list and its cards
POST /api/lists/{id}/cards add a card
PUT/DELETE /api/cards/{id} update (title, body, due, repeat, done, link) / delete; finishing a repeating card answers its copy as again
POST /api/cards/{id}/move to another list and place in it; again as above
POST /api/nodes/{id}/move reparent, and place among the new siblings
POST /api/nodes/move { ids, parent_id }: several into one folder, all or none
POST /api/nodes/{id}/import import a folder or zip (multipart) under this node
POST /api/import import an export at the root: directories become spaces
GET /api/resolve?path= the node behind a slug path, work/notes/monday
GET /api/nodes/{id}/revisions a document's earlier versions, the newest first
GET /api/nodes/{id}/revisions/{rev} one earlier version, with its text
GET /api/nodes/{id}/backlinks the documents that link to this one, with the line each does it on
POST/DELETE /api/nodes/{id}/share mint or rotate / revoke a share link
GET /api/export the whole workspace, boards and dates included, as a zip
GET/POST /api/backup Proton Drive mirror: status / run now
POST/DELETE /api/backup/login log the mirror in to Proton, body {"username","password"} / forget its session
POST /api/backup/login/totp, /api/backup/login/captcha the two-factor code {"code"}, or the solved human check {"token"}, a waiting login asked for
GET/POST /api/media list / upload (multipart)
GET/DELETE /api/media/{id} serve (with Range) / delete a file nothing in the tree owns
POST /api/typst {source} of a ```typst block → {svg}, or {error} as typst words it
GET /api/spaces/overview every space with what was last written in it
POST /api/nodes/{id}/files upload files into this folder as file nodes (?encrypt=true seals them)
POST /api/nodes/{id}/inspect what a certificate, key or keystore file holds ({password} opens a protected one)
POST /api/nodes/{id}/encrypt, /decrypt seal a file, or a folder for good — what is in it and what lands later — or take it out
GET/POST/PUT /api/vault status / set the password once / change it
POST /api/vault/unlock, /api/vault/lock open / close the vault
GET/POST /api/ssh-keys the keys that may mount over SFTP / add one
DELETE /api/ssh-keys/{id} remove a key, which ends its mounts
POST /api/share/{token} public: read a shared document, body {"key"}; sets the share's media cookie
GET /api/share/{token}/media/{id} public: media inside a shared document, with that cookie
POST /api/share/{token}/typst public: a typst block the shared document holds, with that cookie