Skip to content

REST API

callbus serve serves REST next to MCP, on the same port. A running server describes itself at GET /openapi.json (OpenAPI 3.1).

Authentication

When a key is set (--api-key, CALLBUS_API_KEY, or named keys from --api-keys), every /v1 and /mcp request needs Authorization: Bearer <key>, on loopback too; serve refuses to listen on a non-loopback address without one. /healthz and /openapi.json need no key. Requests must come with an allowed Host header and, from a browser, an allowed Origin; bodies are limited to 1 MiB. X-Session-Id groups one conversation's searches and calls in the usage log.

Endpoints

POST /v1/search

{"query": "refund the last payment", "instruction": null, "k": null, "full_schemas": false}

Searches the catalogue. k fixes the number of tools (default: adaptive K); instruction replaces the serving instruction; full_schemas returns every hit's full input schema (default: the first three, the rest shortened). The answer has search_id, mode (semantic, or lexical while the first index builds), took_ms, rule and tools. Each tool has name (its id), api_name, server, kind (mcp or openapi), score, description and inputSchema, with inputSchemaShrunk when the schema was shortened; annotations when the tool has some, method for OpenAPI operations; a tool appended by serve --co-use also has used_with, the returned tool it is called together with. A note for the agent is added when the tools are keyword matches, when none is close enough, or when the reranker did not answer and the tools are in the first stage's order. With a calibration (callbus calibrate) the answer also has confidence, the share of answerable requests whose best score was at or below this one's.

POST /v1/rank

{"query": "refund the last payment", "tools": [{"name": "refund", "description": "...", "inputSchema": {}}]}

Scores up to 200 tools that you pass in (MCP tool objects, with an optional server) or catalogue ids (tool_ids), best first; each result has the tool's index in the request and its score (cosine). Needs the semantic index (503 while the first build runs).

POST /v1/call

{"name": "time/get_current_time", "arguments": {"timezone": "Asia/Tokyo"}, "search_id": "s-..."}

Runs a catalogue tool exactly as MCP call_tool does, with the same write policy. The answer has outcome (ok, tool_error, protocol_error, timeout or refused), isError, content (MCP content blocks) and, for OpenAPI operations, http_status. A tool that fails is still a 200 with isError: true. JSON bodies only.

POST /v1/feedback

{"name": "stripe/PostRefunds", "outcome": "ok", "search_id": "s-...", "took_ms": 840}

For a client that runs the tools itself (its agent platform calls the APIs) and wants callbus to learn from what it called. It reports a call: the tool id, outcome (ok, or tool_error when the tool answered with an error), and optionally the search that found it and how long it took. The call goes to the usage log as if callbus had run it, linked to that search (ran_by: client), so callbus learn, ab and co-use count it. The answer is {name, call_id}. JSON bodies only.

GET /v1/tools, GET /v1/tools/{id}

The catalogue, optionally one server's (?server=). With ?full=true, each tool also has its input schema, annotations and, for OpenAPI operations, the HTTP method, plus the catalogue's hash: the one download a platform client needs.

GET /v1/metrics

Prometheus metrics in the text exposition format, behind the same key as the rest of /v1: searches and calls with their latency histograms, the token estimate, embedding-cache hits, and the catalogue's size. See Metrics.

GET /healthz

200 with {ready, mode} once the semantic index is ready, 503 before. It needs no key and checks no Host (load balancers and probes call it), so it says nothing more.

Errors

Errors are JSON {"error": "..."}:

Status Meaning
400 bad input
401 missing or wrong key
403 a browser origin that is not allowed; /v1/metrics for a key limited to some sources; what a key's scopes do not allow
404 unknown tool
413 body over 1 MiB
415 a call or feedback that is not JSON
421 a Host header that is not allowed
503 index not ready, embedding endpoint down, or backends not running

A client

callbus.client.CallBusClient wraps these endpoints with the standard library only; see the Python API.