API reference

Five routes. Requests and responses are JSON. The CLI and the dashboard use exactly these.

Authentication

Send the workspace key as a Bearer token: Authorization: Bearer wl_... (the word Bearer is case-insensitive). POST /api/workspaces needs no key. A missing, malformed or wrong key returns 401 with WWW-Authenticate: Bearer. API responses are sent with Cache-Control: no-store, and there are no CORS headers: browsers can call the API only from the Whyline site itself.

POST /api/workspaces

Create a workspace. Body: {"name": "..."}, 1 to 100 characters (trimmed). Returns 201 with id, name and key. The key is not stored in readable form and cannot be retrieved again.

Creation is limited to 10 workspaces per hour per client address (per /64 network for IPv6); beyond that you get 429. On the hosted service the address is the one Vercel reports. A self-hosted server uses the connection's address and ignores X-Forwarded-For unless it is told to trust a proxy; see self-hosting.

curl -X POST https://whyline.wrklyst.com/api/workspaces \
  -H 'content-type: application/json' \
  -d '{"name":"acme-backend"}'

POST /api/events

Record one event. Requires the Bearer key. Returns 201 with {"id": ...}.

To make retries safe, send an event_id. An event whose event_id is already stored in the workspace is not stored again: the answer is 200 with the stored event's id. Use a new event_id for every new event; the CLI sends a random UUID. Events without one are always stored.

curl -X POST https://whyline.wrklyst.com/api/events \
  -H "authorization: Bearer $WHYLINE_KEY" \
  -H 'content-type: application/json' \
  -d '{"agent":"claude-code","kind":"prompt","prompt":"..."}'

Event fields

agent and kind are required. Every other field is optional. The official tools send kind values of prompt, edit and commit, but any string up to the limit is accepted.

FieldTypeLimitNotes
agentstring100 charactersRequired. For example claude-code, or none for unattributed commits.
kindstring50 charactersRequired.
tsstring40 charactersISO 8601 time the event happened. Defaults to the time received.
authorstring200 charactersThe CLI sends the git author email.
sessionstring200 charactersAgent session identifier.
promptstring20,000 charactersPrompt text.
summarystring5,000 charactersCommit message, or tool and file for edits.
commit_shastring64 charactersCommit hash.
filesarray of strings1,000 items of up to 1,000 charactersPaths, relative to the repository when sent by the CLI.
event_idstring100 charactersLetters, digits, - and _. Idempotency key, unique per workspace.

The request body can be at most 1,000,000 characters (413 beyond that, also for chunked uploads that send no Content-Length).

GET /api/events

List events, newest first. Requires the Bearer key. Returns 200 with {"workspace": "name", "events": [...]}. Each event has id, ts and the fields above.

ParameterMeaning
sinceOnly events with an id greater than this. Default 0.
beforeOnly events with an id less than this. Use the last id of a page to get the next page.
commitOnly events for this commit. Must be a full 40-character lowercase hex hash, otherwise 400.
limitMaximum number of events, 1 to 500. Default 100. A page holds fewer when events are large, so that a response stays under about 4 MB. To read everything, keep paging with before until a page is empty.
curl "https://whyline.wrklyst.com/api/events?limit=20" \
  -H "authorization: Bearer $WHYLINE_KEY"

POST /api/key

Replace the workspace's API key. Requires the Bearer key; no body. Returns 200 with {"name": "...", "key": "wl_..."}. The old key stops working at once. whyline rotate-key calls this and saves the new key.

curl -X POST "https://whyline.wrklyst.com/api/key" \
  -H "authorization: Bearer $WHYLINE_KEY"

DELETE /api/workspaces

Delete the workspace and all of its events. Requires the Bearer key. Returns 200 with {"deleted": "name"}. It cannot be undone, and the key stops working.

Errors

Errors are JSON: {"error": "message"}.

StatusWhen
400Invalid JSON, a missing required field, or a field over its limit.
401Missing, malformed or invalid API key.
404Unknown route.
413Request body too large.
429Too many workspaces created from one IP in the last hour.
500Server error.