Brain serves JSON over HTTP. A browser calls it with the session cookie; an agent calls POST /mcp with Authorization: Bearer pb_.... Request and response shapes are the zod schemas of @pilotoo/memory-protocol.
Every failure is { "error": { "code": "...", "message": "..." } }.
| Status |
code |
When |
| 400 |
invalid |
The body or query does not match its schema. |
| 401 |
unauthenticated |
No session, or a token that matches nothing. |
| 403 |
forbidden |
You can see the memory but may not do this. |
| 404 |
not_found |
The thing does not exist, or you cannot see it. A hidden memory answers 404, never 403, so its existence does not leak. |
| 405 |
method_not_allowed |
GET or DELETE on /mcp. |
| 409 |
conflict |
The change clashes with existing state. |
| 413 |
too_large |
An upload over 20 MiB. |
| 415 |
unsupported_media_type |
A file type that cannot be read. |
| 500 |
internal |
A defect; the message says nothing about its cause. |
Creating routes answer 201, deletes and decisions answer 204, and the rest answer 200.
| Route |
Purpose |
GET /api/session |
{user, signIn}. user is null when signed out. Needs no session. |
GET /auth/google/start, GET /auth/google/callback |
The Google sign-in. |
POST /auth/logout |
Ends the session (204). |
GET /health |
{status: "ok"}. |
GET /api/people |
The people of the workspace. |
| Route |
Purpose |
GET /api/memories |
The memories you can see, each with myRole and counts. |
POST /api/memories |
{kind, name, description, access, language?}. language is source (the default: each page in the language of its sources) or a two-letter code such as it that fixes it. |
GET, PATCH, DELETE /api/memories/:mid |
Read, rename, change access or language, delete (with everything it owns). |
GET, POST /api/memories/:mid/members |
List, or add {userId, role: "admin" | "member"}. |
DELETE /api/memories/:mid/members/:uid |
Remove a member. |
PUT /api/memories/:mid/members/:uid/roles |
{roleIds}: the label roles of a member. |
| Route |
Purpose |
GET /api/memories/:mid/sources?q=&label=&cursor= |
A page of sources: {items, nextCursor}. |
POST /api/memories/:mid/sources |
A multipart file with optional comma-separated labels and externalId, or JSON {title, text, labels?, externalId?}. |
GET, DELETE /api/memories/:mid/sources/:sid |
Read or delete a source. Deleting retires what only that source supported and rebuilds what other sources still support. |
POST /api/memories/:mid/sources/:sid/erase |
Memory admins only: remove the source and everything derived from it, history and revisions included (204). |
POST /api/memories/:mid/sources/:sid/compile |
Memory admins only: compile it again; answers the source. |
PUT /api/memories/:mid/sources/:sid/labels |
{labelIds}. |
A source is reading, ready or failed, and carries its origin (upload, text, agent or connector).
externalId is your own stable id for the document, up to 200 characters. Adding the same id with the same content changes nothing; with different content it creates the next version, and the source then carries previousVersionId or supersededBy.
| Route |
Purpose |
POST /api/memories/:mid/search |
{query, limit?, as?} returns {passages}. |
POST /api/memories/:mid/ask |
{question, as?} returns {answer, citations, modelOff?}. |
GET /api/memories/:mid/pages?type=&q=&as= |
Pages of a graph memory. |
GET /api/memories/:mid/pages/:pid?as=&history=1 |
One page with sections (its facts), citations, related pages and conflicts. history=1 also returns retired facts, with invalidAt, invalidReason and supersededBy; admins only. |
GET /api/memories/:mid/graph?center=&depth=&as= |
Nodes (page, source) and edges (link, cites). depth is 0 to 4. |
as is a user id: an admin sees the result as that person, and the use is audited. limit is 1 to 50, default 8.
All of these are admin-only, audited, and undoable through the audit log.
| Route |
Purpose |
POST /api/memories/:mid/pages/:pid/merge |
{intoPageId}: merge the page into another. Answers the target page; the old id keeps answering it. |
POST /api/memories/:mid/pages/:pid/split |
{factIds, intoPageId} or {factIds, newTitle, type?}: move facts to an existing or a new page. Answers {fromPageId, intoPageId}. |
PATCH /api/memories/:mid/pages/:pid |
{title?, locked?}: rename (the old title stays an alias) or lock. |
POST /api/memories/:mid/pages/:pid/facts |
{text, labelIds?}: add a fact by hand. |
PATCH /api/memories/:mid/pages/:pid/facts/:fid |
{text?, locked?}: edit or lock a fact. A locked page or fact is not rewritten by a compile. |
GET /api/memories/:mid/health |
{duplicates, orphans, emptyPages, stale} across the memory. |
| Route |
Purpose |
GET, POST /api/memories/:mid/families |
Label families. |
GET, POST /api/memories/:mid/labels |
Labels {familyId, name}. |
DELETE /api/memories/:mid/families/:fid, DELETE /api/memories/:mid/labels/:lid |
Delete one. |
GET, POST /api/memories/:mid/roles |
Roles {name, grants: [{familyId, mode, labelIds}]}, mode being none, some or all. |
PATCH, DELETE /api/memories/:mid/roles/:rid |
Change or delete a role. |
GET /api/memories/:mid/roles/:rid/preview |
{visibleSources, totalSources} for a role. |
GET /api/memories/:mid/review?type= |
Review items, type being labels, conflicts, pages, duplicate or orphan. |
POST /api/memories/:mid/review/:id |
{decision: "accept" | "reject" | "edit", labelIds?, intoPageId?}. On a duplicate, accept merges (intoPageId picks the direction) and reject keeps the pages apart. |
| Route |
Purpose |
GET, POST /api/memories/:mid/checks |
Checks {asUserId, question, mustSourceIds, mustNotSourceIds}. |
POST /api/memories/:mid/checks/run |
Run them: [{checkId, pass, leaked, missing}]. |
GET /api/memories/:mid/audit?cursor= |
The audit log: who, through the web or a token, what and its effect. |
POST /api/memories/:mid/audit/:id/undo |
Undo an event that is undoable. |
GET /api/memories/:mid/connectors |
{connectors, rules}. |
GET /api/memories/:mid/fed-by |
{connectors}: the connectors writing here; memory admins. |
PUT /api/memories/:mid/fed-by/:cid |
{pausedHere}: stop or resume one connector for this memory only. |
| Route |
Purpose |
GET /api/connect/link |
{available, linked, email?, linkedAt?} for the signed-in person. |
GET /api/connect/link/start |
Redirects to Connect’s consent page; callback brings the person back to /#/connectors. |
DELETE /api/connect/link |
Forget the stored Connect token. |
GET /api/connectors/kinds |
The steps the editor offers, including one per tool of your Connect connections. |
GET /api/connectors/templates |
{templates}: workflows a new connector can start from. |
POST /api/connectors/validate |
{definition} → {issues, ports}. |
GET, POST /api/connectors |
List the connectors you can see, or create one {name, definition, template?}; it starts off. |
GET, PATCH, DELETE /api/connectors/:id |
Read, change {name?, definition?, enabled?, dailyCap?} or delete; changes are the owner’s. |
POST /api/connectors/:id/test |
Run without writing anything; the run lists what it would add. |
POST /api/connectors/:id/run |
Run now. |
GET /api/connectors/:id/runs |
{runs}: the latest runs with steps and items. |
| Route |
Purpose |
GET, POST /api/memories/:mid/facts |
List, or add {text}. The answer carries operation: add, update (an older fact was rewritten), delete (a contradicted fact was retired) or noop (already known), and replacedFactId when one is replaced. |
PATCH, DELETE /api/memories/:mid/facts/:fid |
Edit or delete. |
POST /api/memories/:mid/facts/:fid/keep |
Keep a fact that was waiting (pending). If it carries replaces, keeping it retires the fact it replaces. |
POST /api/memories/:mid/facts/:fid/share |
{memoryId}: copy it as a source into a graph memory, where it waits in review. |
GET, PUT /api/memories/:mid/write-policy |
{policy: "auto" | "ask" | "off"}: how agent writes are handled. |
| Route |
Purpose |
GET, POST /api/tokens |
List, or create {name, grants: [{memoryId, access}]}. The secret is returned once. |
DELETE /api/tokens/:id |
Revoke. |
POST /mcp |
The six memory tools. The only route that accepts a pb_ token. See Use it from an agent. |