Skip to the content.

HTTP API

The control plane is FastAPI on loopback, default http://127.0.0.1:8765.

   
Health GET /health{ "ok": true } (no auth)
OpenAPI 3.1 GET /openapi.json
Swagger UI GET /docs
Checked-in dump openapi.json (regenerate with make openapi)
Product routes /v1/*
SPA /

There is no /v1/openapi.json.

Authentication

Send one of:

Authorization: Bearer <token>
X-PCH-Token: <token>
Actor Token source Can
Owner POST /v1/setup or GET /v1/bootstrap Full vault + pairing + plugins + export
Connection POST /v1/connections/pair MCP tools and connection-scoped routes under its grants

Missing or revoked → error (Revoked). Owner-only routes use require_owner.

Idempotency middleware is enabled on REST. Repeat a mutating request with the same idempotency header the client sent if you need safe retries.

Hub.ask() exists in pch-core but is not exposed as /v1/ask.


Setup

Method Path Auth Notes
POST /v1/setup special Body { "name"?: string, "restart"?: bool }{ owner_token, … }
GET /v1/setup none { initialized, encrypted, key_storage }
GET /v1/bootstrap none Local UI: { owner_token, setup }
GET /v1/spaces owner [{ "id": "personal", "kind": "personal" }]

Situation (Home)

Method Path Auth Notes
GET /v1/situation owner Live situation for Home. Empty vault → { "project": null, "contract": null }. Assembles get_context_contract for the live project with purpose what matters now.

Method Path
GET POST /v1/projects
GET PATCH DELETE /v1/projects/{id}
GET /v1/projects/{id}/brief
GET /v1/projects/{id}/versions
GET POST /v1/goals
GET POST /v1/commitments
GET POST /v1/decisions

Optimistic concurrency: send If-Match with the version integer on patches that support it.


Memories, artifacts, preferences, profile

Method Path
GET POST /v1/memories
GET PATCH DELETE /v1/memories/{id}
POST /v1/memories/{id}/supersede
POST /v1/memories/{id}/retract
GET /v1/memories/{id}/versions
GET POST /v1/artifacts
GET POST /v1/preferences
GET PATCH /v1/preferences/{id}
POST /v1/preferences/{id}/supersede
POST /v1/preferences/{id}/retract
GET /v1/profile

GET /v1/search?q=Amsterdam&type=memory&project=<id>&classification=private&purpose=status_update&from=&to=

Query parameters: q, type, project, classification, purpose, from, to (date window on event start). Actor-scoped via grants.


Pairing, grants, manifests

Method Path Auth
GET /v1/catalog/assistants owner
POST /v1/connections/links owner — { "name" }
POST /v1/connections/pair code only{ "code", "runtime_info"? }
GET /v1/connections owner
POST /v1/connections/{id}/revoke owner
POST /v1/connections/{id}/recipe owner — { "assistant" }
POST /v1/grants owner — { connection_id, preset?, capabilities?, selectors?, classification_ceiling }
GET /v1/grants?connection= owner
POST /v1/grants/{id}/revoke owner
POST /v1/context-manifests connection
GET /v1/context-manifests/{id} granted actor

Grant presets: read_active_projects, read_project, always_ask_before_sending. Default classification_ceiling is private.

Assistant ids: cursor, claude-code, claude-desktop, chatgpt, hermes, openclaw.


Proposals, conflicts, relations, operational

Method Path
POST GET /v1/memories/proposals
POST /v1/memories/proposals/{id}/accept reject
GET /v1/conflicts
POST /v1/conflicts/{id}/resolve
GET /v1/operational-proposals
POST /v1/operational-proposals/{id}/accept reject
POST GET /v1/relations
PATCH DELETE /v1/relations/{id}
GET /v1/relation-proposals
POST /v1/relation-proposals/{id}/accept reject

Actions and shared state

Method Path
POST /v1/actions/intents
GET /v1/approvals
POST /v1/approvals/{intent_id}/decide
POST /v1/actions/intents/{intent_id}/result
PUT GET /v1/state/{key}

Audit

Method Path
GET /v1/events
GET /v1/events/verify

Plugins and marketplace

Prefix /v1/plugins: list/create, consent, enable, pause, disable, sync, delete, runs, get, update check/apply.

Prefix /v1/marketplace: GET /catalog, POST /refresh, POST /install, plugin update under /plugins/{installation_id}/update.

See Plugins.


Connectors

Method Path
GET /v1/connectors/oauth/callback
GET /v1/connectors/oauth/status
PUT /v1/connectors/oauth/credentials
POST GET /v1/connectors
GET PATCH DELETE /v1/connectors/{id} (DELETE ?purge=)
POST /v1/connectors/{id}/sync pause resume

See Google connectors.


Export / import

Method Path
POST /v1/export
POST /v1/import/stage
GET /v1/import/staging/{id}
POST /v1/import/staging/{id}/apply
POST /v1/import/vendor
GET /v1/import/vendor/{batch_id}
POST /v1/import/vendor/{batch_id}/archive

See Export and import.


MCP over HTTP

Method Path
POST /v1/mcp/tools/{name} — body = tool kwargs
GET /v1/mcp/resources?uri=

Tool names and bodies: MCP tools.


Simulator (dev)

When PCH_SIM_ENABLED=1 or pch serve --sim (not on by default for make serve):

/v1/sim/runs, pause/resume/stop, ticks, GET /v1/sim/objects/{id}.

These routes load pch-lab only if that package is already installed (workspace). The published server does not depend on lab. Without it, sim routes stay 404.

The simulator is test tooling, not a product agent. Data it writes must be labeled as such. It must not act outward.