HTTP API
mdboard serve exposes the HTML board and a JSON API. The HTML board is the human review/consortium surface; the JSON API is useful for inspection, dashboards and integrations.
Reads are public by default. Writes require a local session and a CSRF token.
Start
mdboard serve --actor owner
The server prints:
mdboard serve: http://127.0.0.1:3000
mdboard auth token (actor `owner`): …
mdboard sign-in: http://127.0.0.1:3000/login.html
Without --actor, write endpoints are disabled and the server is read-only.
Authentication
- POST the one-time token to
/api/auth/login. - Receive a
mdboard_sessionHttpOnly, SameSite=Strict cookie and a CSRF token. - Send
X-CSRF-Tokenon every write. - The session lasts 8 hours in memory; restarting the server invalidates it.
curl -c cookies.txt -X POST http://127.0.0.1:3000/api/auth/login \
-H 'content-type: application/json' \
-d '{"token":"<printed-token>"}'
Response:
{"actor":"owner","role":"owner","roles":["owner"],"csrf":"…"}
The token is one-time. The origin of a write must match the server host.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/board.json |
Board summary, roadmap and card list |
| GET | /api/cards/<id> or /api/cards/<id>.json |
One card with tasks, reviews and cost |
| GET | /api/meetings.json |
Meeting gates and statuses |
| GET | /api/schema.json |
Kinds, states, transitions and authority |
| POST | /api/ideas/<id>/accept |
Consortium accepts a pitch |
| POST | /api/ideas/<id>/reject |
Consortium rejects a pitch |
| POST | /api/batches/<id>/review |
Record a review artifact |
| POST | /api/batches/<id>/request-changes |
Return a handover batch to doing |
| POST | /api/batches/<id>/complete |
Owner accept and complete |
| POST | /api/meetings/<id>/accept |
Accept a gate |
| POST | /api/meetings/<id>/defer |
Defer a gate |
| POST | /api/meetings/<id>/dismiss |
Dismiss a gate |
Actions enforce the same authority as the CLI. Writes require the session cookie and X-CSRF-Token.
Board JSON
{
"schema": 2,
"upstream": {"iteration":7,"status":"open","base":"…","writer":"agent"},
"roadmap":{"count":3,"limit":5,"estimated_cost_eur":0.42},
"active_batch":"#0009",
"pending_meetings":["M0009-01"],
"cards":[
{"id":"#0009","kind":"batch","state":"doing","title":"CSV export","intent_owner":"owner"}
]
}
Card JSON
{
"card": {
"id":"#0007",
"kind":"batch",
"state":"handover",
"title":"CSV export",
"intent_owner":"owner",
"estimate":{"tokens":{"weighted":12667.0},"agent_hours":{"weighted":1.0}},
"report":null,
"blocked_from":null
},
"tasks":[{"id":"#0007-01","state":"done"}],
"reviews":[{"id":"RV-0007-01-01","reviewer":"reviewer","verdict":"accepted"}],
"estimated_cost_eur":0.0027
}
Meeting JSON
{
"id":"M-0007-01",
"kind":"handover-review",
"status":"pending",
"trigger":"Batch #0007 entered handover",
"linked_cards":["#0007"],
"due":null,
"questions":[]
}
Static pages
/overview/board.html/roadmap.html/cards/<id>.html/meetings.html/login.html/assets/style.css,/assets/process.js
The HTML board is a view. Do not scrape it for automation; use the CLI or JSON API.
Security boundary
This is a local server. It is not a multi-tenant service, has no OIDC or trusted-proxy mode in the alpha, and must not be exposed directly to the internet. See Security.