Skip to content

API Reference

Jaloliddin Ismailov edited this page Oct 4, 2026 · 2 revisions

The Hub's API is plain REST over /api/*, session-cookie authenticated, with the permission checks server-side on every call. This page is the orientation — conventions, auth, error shapes — with the surface organised by domain rather than an exhaustive per-endpoint dump. When in doubt, the handler files in src/endpoints/ are the definitive spec: one file per domain, the paths at the top of each.

Conventions

  • Auth: session cookie from /api/auth/login. MCP and scripts use a bearer HUB_TOKEN issued against a Hub account — the same session, presented differently.
  • Reads: GET, list endpoints paginate; GET /:id or /:slug for one.
  • Writes: POST for transitions, and transitions are named verbs — /present, /close, /withdraw, /review, /approve. A state change that isn't a named verb is usually a smell.
  • Errors: JSON { error, detail? }; 401 unauthenticated, 403 the access engine declined, 422 validation, 429 rate-limited (the login limiter especially).
  • Idempotency on transitions that matter: ballots, writebacks, credential issuance carry their own dedupe — re-POSTing is safe-by-design, not by luck.

The surface, by domain

Auth & session

POST /api/auth/register  /login  /logout  /forgot-password  /reset-password
GET  /api/auth/me        /change-password

Membership & the directory

GET  /api/directory  /api/people  /api/organisations
POST /api/member/affiliations  /decide   org membership requests
GET  /api/member/workspace/:wg  + /join /onboard

Decisions, elections, selections — the full pipeline from Governance and decisions:

GET|POST /api/decisions           /:id  /present /comments /flags
         /flags/:flagId/respond   /flags/:flagId/withdraw
         /close /ballots /vetoes  /vetoes/:vetoId/confirm
         /withdraw /events
GET|POST /api/governance/elections/:id /advance /candidates
         /candidates/:cid/screen   /credential /vote /tally
         /api/governance/selections/:id /open /apply /committee
         /recuse /applications/:aid/evaluate /decide /announce

Platform bodies & Council

GET /api/platform/bodies  /overview /public /records /tasks /enquiries
    /api/council  /api/council/:slug
POST /api/platform/bodies/:id/join  /publish /withdraw-publication
POST /api/platform/decisions/:id/transition /contributions /publish
POST /api/platform/records/:id/revoke

Content, opportunities, resources

GET|POST /api/member/content /drafts /drafts/:id
GET /api/documents/:slug  /resources /submissions /submissions/:slug
GET /api/opportunities    (reviewed pipeline — see Content and publishing)
GET /api/events /events/:slug /coys /coys/:slug /gys /feed /search

Staff & team operations

/api/member/team/membership/…   verify, status, terminate, records/:rid/end,
                                appeals/:id/review, renewals/run, handovers
/api/member/team/partnerships   /recognition /coi /safeguarding /privacy
/api/member/admin/accounts/:id  role, status, team-role, verify, reset-link
/api/member/admin/audit         /notifications/send|outbox|preview

Negotiations

GET  /api/negotiations /:slug        POST /:slug/follow
GET|POST /api/negotiations/projects /:id /versions /amendments
     /amendments/:id/reconciliations /:reconciliationId/confirm
POST /api/negotiations/documents/:id/versions/:versionId/extraction-reviews

Intelligence — read-only by design, one narrow writeback:

POST /api/intelligence/query      GET /metrics
POST /api/intelligence/writebacks /:id/approve /:id/apply

Notifications & push

GET|POST /api/notifications/…     POST /api/push/subscribe /unsubscribe /send
GET  /api/push/vapid-key /status  POST /api/cron/notifications-drain

A worked example

Casting a decision ballot — note it is a named transition with a server-side eligibility recheck, not a PATCH to a votes field:

curl -X POST "$HUB/api/decisions/42/ballots" \
  -H "Cookie: payload-token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"choice": "support"}'

And the same call the MCP makes, as JSON-RPC over its own service (see Agent tools):

{"jsonrpc":"2.0","id":3,"method":"tools/call",
 "params":{"name":"list_opportunities","arguments":{"status":"open"}}}

What is deliberately absent

No generic CRUD passthrough to collections. No /api/admin/* that bypasses the access engine. No way to write to authority_records except through the service layer behind member/admin and team endpoints. If you find yourself wanting "just a raw update endpoint", that want is the thing to code-review — the missing API is usually the security boundary.

Clone this wiki locally