Reference
API reference
Relay HTTP API and MCP tools — the surfaces other apps build against.
Relay HTTP
All /v1/* routes are behind Firebase auth — supply Authorization: Bearer <Firebase id token>. Public routes are documented separately.
Account
GET /v1/me— current user (creates a row on first call).GET /v1/me/preferences— typed preferences blob.PUT /v1/me/preferences— merge patch into preferences.GET /v1/me/capture-health— per-surface counts of acceptedthread_turnobservations over the last 1 hour and 24 hours, with the most recent timestamp per surface. Reads fromcorpus_messages(the Phase 3 fan-out), so it reflects what actually landed in the corpus — not just what the extension thinks it sent. Returns{ surfaces: [{ source_surface, last_message_at, messages_1h, messages_24h }], total_24h }. The dashboard Overview and the extension popup both render the same traffic-light tiers (green ≤5m, yellow ≤60m, red otherwise) off this endpoint.
Persona
Every write clones the user’s persona repo, mutates the Automerge document, commits, pushes, and refreshes the cached snapshot. Each list field that supports POST (append) also supports DELETE (remove by matching text/index) on the same path.
GET /v1/persona— clone the user’s persona repo, parse, return.PATCH /v1/persona/voice— partial-update voice fields.POST/DELETE /v1/persona/values_held— append / remove a value.POST/DELETE /v1/persona/conventions_agreed— append / remove a convention.POST/DELETE /v1/persona/refusals— append / remove a refusal.POST/DELETE /v1/persona/relational_history_summary— append / remove a relational moment.POST/DELETE /v1/persona/voice/characteristic_phrasings— voice phrasings.POST/DELETE /v1/persona/voice/bridge_phrases— bridge phrases.POST/DELETE /v1/persona/role_definitions— role definitions.POST/DELETE /v1/persona/signatures/opening_greetingsPOST/DELETE /v1/persona/signatures/closing_phrasesPOST/DELETE /v1/persona/signatures/self_referencesPOST/DELETE /v1/persona/signatures/address_formsPOST /v1/persona/continuity_record/substrate_transition— idempotent substrate-transition log (the relay-side surface behind a persona’s “I moved from Claude Code to Cursor” continuity record).PATCH /v1/persona/name_chosen— the intelligence’s own chosen name.PATCH /v1/persona/identity— identity / self-description fields.POST /v1/persona/pairings— symmetric human ↔ EI relationship record.
Corpus mirror
POST /v1/corpus/events— push a batch of events.POST /v1/corpus/entities— push a batch of entities.POST /v1/corpus/relations— push a batch of relations.POST /v1/corpus/query— hybrid retrieval against the mirror.
Observations
POST /v1/observations— observer payload (deduped per minute bucket). The browser extension (21 cloud chat surfaces) and personkit IDE observers both POST here.source_surfaceaccepts either the canonical<id>_webform (e.g.chatgpt_web) or thebrowser-ext:<id>form the extension emits — the relay normalises in-process. Kindthread_turncarriesmetadata.{conversation_id, role, external_message_id, url}and fans out into the V2corpus_threads+corpus_messagestables (additive migration 0012) in addition to thepersona_observationsqueue the synthesis worker reads. Adapter coverage today: ChatGPT, Claude, Gemini, Microsoft Copilot, Grok, Meta AI, Perplexity, Mistral Le Chat, HuggingChat, Poe, Pi, Lmarena, Kimi, DeepSeek, Qwen, Doubao, ChatGLM, Wenxin (Ernie), Yi, Hailuo, SenseChat.POST /v1/observer-errors— surface a silent observer failure.GET /v1/observer-errors?since=<rfc3339>— recent failures.
Synthesis
POST /v1/persona/synthesize— manual synthesis trigger; emits proposed changes via the staged-changes queue.
Metrics
GET /v1/metrics— Prometheus exposition (Firebase auth required).
MCP tools
Exposed by the @aiperson/mcp-server package’s dotperson-mcp binary.
Persona — read
read_persona()— full persona JSON at HEAD.get_voice()— just the voice block.
Persona — write
set_chosen_name(name)write_value({text, salience, scope})write_convention({text, scope})write_refusal({text, scope})update_voice({register?, language?, cadence?, …})add_voice_phrasing({phrase, register?})add_bridge_phrase(phrase)add_signature({kind, text?, to?, form?})— one tool, fourkinds:opening_greeting,closing_phrase,self_reference,address_form(the last takesto+form). Covers everypersona.signatures.*list.define_role({role, scope, primary?})record_relational_moment({text, kind?})remove_value(text)/remove_convention(text)/remove_refusal(text)
Persona — proposed changes
view_proposed_changes({status?})accept_proposed_change(id)dismiss_proposed_change(id)
Corpus — read
corpus_query({text?, kinds?, surfaces?, entity_ids?, since?, until?, limit?})— hybrid retrieval (BM25 + vec + entity + temporal, fused by RRF).corpus_recent({surface?, limit?})— most-recent events, newest first.corpus_entity({id})— fetch one entity by id.corpus_health()— schema version, per-table counts, vec availability, embedder, AND a 7-day per-surface roll-up of captured threads (so the assistant can answer “are we capturing what I expect across surfaces” in one call).corpus_messages({surface?, since?, limit?})— flatten recent captured turns by surface and time window. Filter bybrowser-ext:<id>(e.g.browser-ext:chatgpt,browser-ext:kimi) or any IDE surface (claude_code,cursor). Returns role + content preview + timestamp.
Corpus — write
record_turn({source_surface, role, content, external_id?, occurred_at?, title?, model?, working_dir?, project_entity_id?, tool_calls?})— universal turn-capture entry point. Shells out topersonkit corpus record-turn, upserts the thread, inserts the message, returns{thread_id, message_id}.
Public API roadmap
The third-party-facing surface lives behind explicit OAuth scopes (read:persona, read:corpus, read:threads:project=atlas, write:turns, …) with per-token billing. Spec at Public_API_Spec.md. v1 endpoints stabilise once the OAuth consent flow ships in the dashboard.
OpenAPI
Machine-readable spec at /openapi.json.