REST Endpoints

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.

EndpointPurpose
GET /api/system/statusIs the agency running or stopped: {"state", "stopped_by", "stopped_at"}, where state is running or stopped.
POST /api/system/stopStop the agency. Body: {"by": "<who>", "reason": "<optional>"}. Answers with the same shape as status.
POST /api/system/resumeResume 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 503 with {"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

EndpointPurpose
GET /api/agentsEvery 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=trueThe 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}/quarantineStop an external agent now. See [External Frameworks](../integrations/external-frameworks).
POST /api/agents/{name}/releaseRelease 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

EndpointPurpose
GET /api/sessionsSessions, 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,cWhich 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.

EndpointPurpose
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/meshEvery 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/modelsWhat 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/contractThe 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=sandboxThe 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

EndpointPurpose
GET /api/infra/datastoreThe 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/connectionsThe 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}/testAsk the provider whether the connection's credential works: active, failing or readable. See [Connections & the Infra Page](../integrations/connections-and-infra).
GET /api/infra/tenantsThe 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-credentials2.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/vaultsThe vaults in search order.
POST /api/infra/vaultsConnect a vault (checked before it is saved).
PUT /api/infra/vaults/activeChoose 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/typesThe kinds of vault that can be connected, with their forms.
POST /api/infra/vaults/{name}/checkCheck a connected vault answers and its sign-in works.
GET /api/infra/vaults/{name}/secretsNames 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

EndpointPurpose
GET /api/streams/analyticsCost, tokens and model calls, all time.
GET /api/streams/analytics?hours=NThe same over the last N hours (1–192), in UTC hour buckets.
GET /api/budgetsEvery agent's monthly spend against its budget. See [Per-Agent Budgets](../advanced/budgets).

Related

Last updated: 11/10/2026