Skip to content

JSON-RPC

Chorus exposes a single JSON-RPC 2.0 endpoint, POST /rpc. It frames the same command catalog as the REST and MCP transports — the wire layer only validates the envelope and dispatches to a method handler (src/rpc/routes.ts). Auth is member: send your API key as Authorization: Bearer <key>.

The envelope is standard JSON-RPC 2.0 (JsonRpcRequestSchema, src/rpc/types.ts:21):

{ "jsonrpc": "2.0", "method": "memory.store", "params": { ... }, "id": 1 }

jsonrpc must be the literal "2.0", method a non-empty string, params is optional, and id is a string, number, or null.

Method names: dot-form canonical, slash-form back-compat

Section titled “Method names: dot-form canonical, slash-form back-compat”

The method registry carries two naming conventions at once (methodRegistry, src/rpc/methods.ts:1165-1377 — 198 keys at HEAD). 102 catalog dot-form names (memory.store, tasks.create, signals.emit.pulse) sit alongside 96 legacy slash-form names (memory/store, signals/emit, org/create_ring). Many ops are dual-registered under both spellings and resolve to the same catalog command; the canon for every naming seam (tools, leases, ids, rings, signal types) lives on Naming & conventions.

Use When
domain.op (dot) Canonical. Post-#416 catalog spelling. Prefer this.
domain/op (slash) Back-compat alias for existing SDK/CLI/MCP clients.

The dot-form catalog covers the full RFC-291 execution surface (tasks.*, runs.*, deliveries.*, checkouts.*), plus circles.*, workstreams.*, webhooks.*, workflow.*, admin.*, and the eight signals.emit.<type> foundation methods. The authoritative list is the registry itself.

processRequest runs one request object; the top-level handler dispatches on body shape (src/rpc/routes.ts:36, :106).

  • Single — one object → one response object, HTTP 200.
  • Batch — a JSON array of requests. Each is processed in order; non-notification results are collected into a response array, HTTP 200. An empty array is INVALID_REQUEST; a batch of all-notifications returns HTTP 204 (:141).
  • Notification — a request with no id field (absent, not null). The method runs but no response is emitted; a single notification returns HTTP 204 (isNotification, src/rpc/types.ts:75; :164).
[
{ "jsonrpc": "2.0", "method": "rings.list", "params": {}, "id": 1 },
{ "jsonrpc": "2.0", "method": "signals.emit.pulse", "params": { "content": "hi" } }
]

The second item above is a notification (no id), so the batch response array contains only the result for id: 1.

Success returns { "jsonrpc": "2.0", "result": <any>, "id": ... }. Errors return { "jsonrpc": "2.0", "error": { "code", "message", "data"? }, "id": ... } (jsonRpcResult / jsonRpcError, src/rpc/types.ts:51, :58).

Standard numeric codes (src/rpc/types.ts:10):

Code Constant Meaning
-32700 PARSE_ERROR Body was not valid JSON
-32600 INVALID_REQUEST Envelope failed schema (or empty batch)
-32601 METHOD_NOT_FOUND No handler for method
-32602 INVALID_PARAMS Handler rejected params
-32603 INTERNAL_ERROR Unhandled handler failure
-32000 APP_ERROR A ChorusError — app code nested under error.data.code

A ChorusError maps to APP_ERROR (-32000) with the domain code carried in error.data.code and error.data.details (toJsonRpcError, src/rpc/types.ts:83). Note that this differs from the REST envelope: JSON-RPC errors have no flat code string, no request_id, and no docs_url (gap-4 §1.3).