REST Endpoints
The mesh's HTTP API, for the routes most integrations use. Every route needs
your org API key in the X-API-Key header. Send X-Tenant-ID to act inside
one tenant's scope (see Multi-Tenancy).
Stop and Resume the agency
One switch for the whole agency — what the Control page uses.
| Endpoint | Purpose |
|---|---|
GET /api/system/status | Is the agency running or stopped: {"state", "stopped_by", "stopped_at"}, where state is running or stopped. |
POST /api/system/stop | Stop the agency. Body: {"by": "<who>", "reason": "<optional>"}. Answers with the same shape as status. |
POST /api/system/resume | Resume it. Body: {"by": "<who>"}. Answers with the same shape as status. |
What Stop does. Stop pauses the mesh; it never exits the process, so the server keeps answering and Resume works.
- No new work starts. API runs, the Playground, reruns, Inbox messages,
webhooks and callbacks answer
503with{"error", "state": "stopped", "stopped_by", "stopped_at"}. Channel messages, schedules, event listeners and follow-ups are dropped. - Runs in flight are cancelled, on every agent type. Their sessions read
cancelled, a waiting caller is told at once, and nothing they produced is handed on. - It holds. The stop is kept in the mesh's own store, so it survives a restart and applies on every worker and pod.
- Resume retries nothing. A schedule that fell inside the stop is skipped, not caught up. Agents someone switched off stay off.
Reads and configuration routes work as usual while stopped.
Agents
| Endpoint | Purpose |
|---|---|
GET /api/agents | Every agent with its type, can_call and status. is_active is false for an agent that is stopped. switched_off is set when its config names a vault connection that does not exist — {reason, missing: [{path, connection, field}]}; its runs fail until the connection is added, and it switches back on by itself. quarantine is set on a stopped external agent — {reason, consecutive_failures, since, by}. |
GET /api/agents/{name} | One agent. Secrets, webhook paths and Authorization values in its config are masked; ${vault:...} references in an MCP process's env are shown as written. |
GET /api/agents/{name}?health=true | The same, plus connector_health for a connector-backed external agent: {framework, healthy, probed, checked_at}. It makes one probe call; healthy: null means nothing could be probed. |
POST /api/agents/{name}/quarantine | Stop an external agent now. See [External Frameworks](../integrations/external-frameworks). |
POST /api/agents/{name}/release | Release a quarantined external agent. |
GET /api/yaml/agents/{name} | One agent's config, masked the same way. |
PATCH /api/yaml/agents/{name} | Change some of an agent's fields. A block such as connector_config or external_policy is merged one level deep — {"external_policy": {"quarantine_after": 3}} keeps the policy's other fields; a key sent as null is removed. A map field sent as {} is emptied. A masked value sent back means "keep what is stored". |
PUT /api/yaml/agents/{name} | Replace an agent's config whole. |
On a mesh setting, a value sent as null returns that setting to its default.
An agent created through the API while the mesh runs receives its entry points and the hand-offs to it at once; deleting one removes it the same way. A saved change reaches the running mesh without a restart: routing (can_call) follows the new list, and an external agent whose framework, connection or connector_config changed gets its connector rebuilt for the next call. On a claude_agent, cwd, allowed_tools and permission_mode are never changed through the API; a write that changes them is refused. Change them on the host with leafmesh agent host-rights <agent> ... (2.4.485), which saves a new version.
Sessions
| Endpoint | Purpose |
|---|---|
GET /api/sessions | Sessions, newest first, with per-row details. Paged with limit (1–500, default 50) and offset; filter with agent_name or source. The response carries status_counts — {active, idle, paused, escalated, terminal} over every session the filters match, not just the page. |
GET /api/sessions/lookup?ids=a,b,c | Which tenant owns each session, for opening a link to a session cold: {rows: [{session_id, exists, tenant_id}]}. Up to 50 ids. Nothing else about the session is returned. |
When the plan is at its limit or an invoice is unpaid, starting a new
session is refused with HTTP 402; runs already in flight carry on (2.4.481).
Who started a session (2.4.491+). GET /api/sessions rows and
GET /api/sessions/{id} carry started_by: {how, via, who, at}, written once
when the session is created and never changed; it is for display only. how
is one of webhook, inbox, channel, api, schedule, followup,
agent, mesh. who is the API key's name or the person's display name,
never a key, id, email or phone. The first run's trace carries
leafmesh.started_by.how, .via and .who; who follows PII redaction (on
by default).
Configuration schema
What Studio uses to build its forms — useful for any editor of your own.
| Endpoint | Purpose |
|---|---|
GET /api/schema/agent?type=<agent type> | Every agent setting: key, type, default and accepted values. type (llm, human, programmatic or external) narrows the list to the settings that mean something on that agent type. Each row also has applies ("live", "reload" or "process_restart") and restart_required, as for /api/schema/mesh. |
GET /api/schema/mesh | Every mesh-level setting, nested blocks as dotted keys. Each row has applies (2.4.485): "live" (taken at once), "reload" (the agency reloads itself in place, automatically, within seconds; a seat's channels count as reload) or "process_restart" (only evolution_api settings). restart_required stays, and is true only when applies is "process_restart". |
GET /api/schema/models | What each model accepts — reasoning effort and its levels, thinking style, temperature, the token parameter, provider family — and whether the SDK has a price for it. ?models=a,b asks about specific names; without it, every priced model. |
GET /api/schema/contract | The whole contract Studio builds on, in one document: every agent and mesh field with its type, default and choices, which fields each agent type keeps on a type change, the save rules, and every framework's and tool block's fields. The same contract ships inside the package. |
GET /api/registry?category=sandbox | The host's sandbox strength: strength (full, or partial / unavailable with the reason), can_contain (whether sandbox_exec is offered at all) and network_allowed (whether a network allowlist is honoured). See [LLM Agents → Running code](../agents/llm-agents#running-code-sandbox). |
GET /api/registry/mcp/tools?agent=<name>&server=<index> | The tools an MCP server offers, for a tool picker. Only a server already declared on that agent (server is its position in the agent's mcp: list); nothing secret is returned. |
Connections and vaults
| Endpoint | Purpose |
|---|---|
GET /api/infra/datastore | The store: whether it is reachable, latency, server, the settings in force and which .env names set them. Never the address or password. Studio shows it under Infrastructure → Datastores. |
GET /api/infra/connections | The connections, names and fields only, never a value. Each row says whose it is (owner: the organisation or the tenant). 2.4.509: ?owners=all (organisation only) lists the organisation's records and every tenant's. |
POST /api/infra/connections/{name}/test | Ask the provider whether the connection's credential works: active, failing or readable. See [Connections & the Infra Page](../integrations/connections-and-infra). |
GET /api/infra/tenants | The tenants with setup on this mesh (names only). A request made as a tenant sees only itself. |
DELETE /api/infra/tenants/{tenant} | 2.4.489+. Organisation only. Takes the tenant off this deployment's tenants list and touches nothing else. Refused with 409 while the tenant still holds its own vault records. |
GET /api/infra/tenant-credentials | 2.4.488+. The records a tenant may fill with its own key (pasted keys only): name, provider, whether it is saved, fields, allowed models and the tenant's pick. You or a tenant may call it; never a value or another tenant's data. See [Tenants' own model keys](../integrations/bring-your-own-vault). |
GET /api/infra/vaults | The vaults in search order. |
POST /api/infra/vaults | Connect a vault (checked before it is saved). |
PUT /api/infra/vaults/active | Choose where new credentials are stored. From 2.4.507 the old vault is no longer read. |
DELETE /api/infra/vaults/{name} | Disconnect a vault. |
GET /api/infra/vaults/types | The kinds of vault that can be connected, with their forms. |
POST /api/infra/vaults/{name}/check | Check a connected vault answers and its sign-in works. |
GET /api/infra/vaults/{name}/secrets | Names and shape of what a vault holds for the mesh — never a value. |
The vault routes are the mesh owner's: a tenant's request is refused. Details in Bring Your Own Vault.
Usage
| Endpoint | Purpose |
|---|---|
GET /api/streams/analytics | Cost, tokens and model calls, all time. |
GET /api/streams/analytics?hours=N | The same over the last N hours (1–192), in UTC hour buckets. |
GET /api/budgets | Every agent's monthly spend against its budget. See [Per-Agent Budgets](../advanced/budgets). |
Related
- Configuration API
- Agent Experience — experience routes
- HITL Workflows — human reply routes