Skip to content
Pilotoo
v0.1

HTTP API

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.