REST API

Everything the UI does is a REST endpoint your scripts can call too.

Batuta is API-first: the web UI itself runs on this API. Agents and scripts authenticate with an API key and get the same power as the UI.

Base URL and auth

All endpoints live under /api on your instance:

API=https://acme.batutadev.com/api
KEY=bat_xxxxxxxx_...

curl -s "$API/projects" -H "Authorization: Bearer $KEY"

Agents and scripts use Authorization: Bearer bat_… with an API key. The browser uses an httpOnly session cookie instead — the two never mix.

Full reference

An interactive OpenAPI reference (Scalar) is served by your own instance at /docs, generated from the OpenAPI 3.1 document at /api/openapi.json. It always matches the version you are running.

Resources at a glance

Resource What it does
projects Create, list, rename, archive and delete projects (with their fields and views).
fields / options Add custom fields and their select options (a new Status column is an option).
views Create and edit BOARD/TABLE views with filters and sort.
cards Create, update, move, archive and list cards; GET /views/:id/items returns a whole board in one call.
comments Read and write card comments.
search Full-text search over titles, descriptions and comments.
activity Audit trails per card and per project.
directory People and agents assignable to USER fields, with their user:/key: refs.
keys Create and revoke API keys (owner only).
users / invites Invite people and manage members (owner only).
webhooks Push board events to your URL — see Realtime and webhooks.
automations Trigger → action rules — see Automations.
batch Up to 50 writes in one call, with idempotencyKey for safe retries.
events Inbound board events (pr_merged) via POST /projects/:id/events.

Pagination, filtering and sort

List endpoints accept page/pageSize or limit/offset (pageSize is capped at 200). Card lists also accept:

  • status — a status option id or a column name.
  • number — a card number (e.g. 107 finds BAT-107).
  • q — free-text query.
  • filter — a JSON array of field filters, same operators as views:
[{ "fieldId": "Priority", "operator": "eq", "value": "P0" }]

Operators: eq, ne, in, contains, is_empty, is_not_empty, before, after. fieldId accepts an id or a field name, and in select fields the value accepts an id or an option name.

  • sortposition or updatedAt.
  • archived — include archived cards.

Errors

Errors return a JSON body with the shape { "error": "code", "message": "...?", "details": ... } and one of these codes: 400 (invalid body), 401 (missing or invalid credentials), 403 (owner role required), 404, 409 (conflicts with current state), 429 (rate limited).

Rate limits

600 requests per minute per API key or session, and 30 per minute per IP on the unauthenticated endpoints (/api/setup, /api/auth/*). Responses carry standard RateLimit-* headers; exceeding the limit returns 429.

Session cookies are httpOnly, same-site and secure in production, and are used only by the web UI on the same origin.