Overview

API reference

The OpenAPI document#

https://api.laver.app/openapi.json

Public, no credential needed, generated from the running application — it always matches the deployment that serves it. If a field disagrees with anything written in prose docs, the OpenAPI document is right.

npx openapi-typescript https://api.laver.app/openapi.json -o laver-api.d.ts

Pin the document, not the URL, in anything you ship: download it, commit it, regenerate deliberately.

Authentication#

Two kinds of bearer token, not interchangeable:

  • Session tokens — JWTs the web app holds after sign-in, auto-renewed.
  • API keys — begin laver_, act as their creating person with exactly their access, scoped to the one workspace named at creation.

Service accounts are the exception: an admin can mint a key that belongs to the workspace, given explicit board access, surviving whoever created it.

Route group Session token API key
/workspaces, /boards, /tasks, /wikis, /search Yes Yes
/sprints, /notifications, /notes, /collab Yes No
/profile, /admin, /billing, /staff, /auth Yes No

A key cannot mint another key, and cannot look itself up — read GET /workspaces/<uuid>/members and match on email instead.

Rate limits#

Allowance 900 requests/minute
Window Rolling, one minute
Counted per Authenticated user, individual API key, or client IP
Exempt GET /health, any /events path
Over the limit 429, with retry-after

Every API key has its own budget — a fleet of agents sharing one key shares its 900/minute; a different key starts a separate budget on the same host.

Pagination#

Most collections return complete, no paging. Two that page:

  • Board ticket search (GET /boards/<uuid>/tasks) — limit 1-200 (default 50), keyset cursor over (position, uuid).
  • Notifications — up to 30 per page, next_cursor.

Request validation#

Every request body is validated strictly and undeclared fields are rejected, not ignored:

{"statusCode": 400, "code": "FST_ERR_VALIDATION", "error": "Bad Request", "message": "body must NOT have additional properties"}

Round-tripping a whole ticket object from a GET into a PATCH will fail — a response carries fields no request accepts.

Size limits worth knowing before you hit them#

Thing Limit
Ticket title 500 characters
Comment body 10,000 characters
Column name 100 characters
Labels per ticket 20
Attachment 25 MB per file
API keys 10 live per person per workspace

Updated

Was this page helpful?