Skip to main content

REST API endpoints

Derived from backend/src/api/routes/. Paths are given relative to the API base — see Overview, which also explains the response shape (there is no envelope) and why there is no /v1.

Every endpoint below requires authentication. All examples use http://localhost:3001; substitute your own API base.

tenantId is a path segment on most routers, not a body field.

Earlier versions of this page documented tenant-agnostic paths such as POST /api/keys and POST /api/bots/:botId/integrations. Those routes do not exist and never did — the real ones carry the tenant in the path, and it is checked against your principal. A client written against the old paths receives 404.

Tenants

MethodEndpointDescription
GET/api/bots/tenantsList the tenants you administer
GET/api/bots/tenants/:tenantIdGet a tenant with its bots
POST/api/bots/tenantsCreate a tenant
PUT/api/bots/tenants/:tenantIdUpdate a tenant
DELETE/api/bots/tenants/:tenantIdDelete a tenant

Creating a tenant also establishes its first admin, atomically with the tenant itself — a tenant is never created without one. By default that is the caller; pass initialAdminClerkUserId to name another user instead (for provisioning a tenant on someone's behalf without gaining access to it yourself). The id must belong to an existing user or the request fails with 404 and no tenant is created. Subsequent membership changes go through the membership endpoints below, which require a tenant admin.

Bots

MethodEndpointDescription
GET/api/botsList the bots of every tenant you administer
GET/api/bots/available-agentsAgents that can be attached to a bot
POST/api/bots/:tenantId/botsCreate a bot
GET/api/bots/:tenantId/:botIdGet a bot
PUT/api/bots/:tenantId/:botIdUpdate a bot
DELETE/api/bots/:tenantId/:botIdDelete a bot
GET/api/bots/:tenantId/:botId/statsBot statistics
The listing endpoints are scoped to you

GET /api/bots, GET /api/bots/tenants and GET /api/bots/available-agents take no tenant in the path, so they scope to the set of tenants your principal administers — never to everything on the platform. ?tenantId narrows within that set; asking for a tenant outside it returns 403, not an empty list. A caller who administers no tenant gets 403 from the first two.

A parallel /api/bots/superadmin tree manages platform-level bots that are not owned by a tenant. It mirrors the shape above without the :tenantId segment, and every path beneath it is guarded by requireOrgAdmin — an organization-admin role on top of authentication, not merely a logged-in session.

Integrations

An integration connects one bot to one messaging platform.

MethodEndpointDescription
GET/api/bots/:tenantId/:botId/integrationsList a bot's integrations
GET/api/bots/:tenantId/:botId/integrations/:integrationIdGet one integration
POST/api/bots/:tenantId/:botId/integrationsCreate an integration
PUT/api/bots/:tenantId/:botId/integrations/:integrationIdUpdate an integration
DELETE/api/bots/:tenantId/:botId/integrations/:integrationIdDelete an integration

Create an integration

integrationType and credentials are required. integrationId is generated by the server — sending one is ignored, and the generated value comes back in the response.

curl -X POST http://localhost:3001/api/bots/acme/support-bot/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"integrationType": "telegram",
"enabled": true,
"credentials": {
"botToken": "…",
"botName": "acme_support_bot"
}
}'

Creating a Telegram integration also registers the webhook with Telegram. See Webhooks.

Reads never return credentials in plaintext. Integration responses carry a maskedCredentials object instead of the credentials you posted.

Agents

MethodEndpointDescription
GET/api/agentsAgents and their usage
GET/api/agents/statsAggregate agent statistics
GET/api/agents/:agentIdOne agent
PATCH/api/agents/:agentId/statusEnable or disable an agent
POST/api/agents/triage-previewPreview which agent would handle a message
POST/api/agents/registry/refreshReload agents from the database

Definitions

Agent, tool, and capability specs — the authoring surface behind the runtime.

MethodEndpointDescription
GET · POST/api/definitions/agentsList · create agent definitions
GET · DELETE/api/definitions/agents/:idGet · delete one
GET/api/definitions/agents/:id/toolsTools attached to an agent
GET/api/definitions/agents/:id/capabilitiesCapabilities attached to an agent
GET · POST/api/definitions/toolsList · create tool definitions
GET · DELETE/api/definitions/tools/:idGet · delete one
GET/api/definitions/tools/manifestFull tool manifest
GET/api/definitions/tools/availableTools available to the caller
POST/api/definitions/tools/syncSync tool definitions
GET · POST/api/definitions/capabilitiesList · create capabilities
GET · DELETE/api/definitions/capabilities/:idGet · delete one
GET/api/definitions/marketplacePublished, shareable definitions
POST/api/definitions/{agents,capabilities,tools}/:id/publishPublish to the marketplace
POST/api/definitions/{agents,capabilities,tools}/:id/unpublishWithdraw
POST/api/definitions/{agents,capabilities}/:id/copyCopy a published definition into your tenant
GET/api/definitions/healthDefinition subsystem health

Provider API keys

These hold your model-provider credentials (BYOK) — OpenAI, Anthropic, and the configured private-LLM provider. They are not credentials for this API.

Every route is tenant-scoped in the path:

MethodEndpointDescription
GET/api/keys/:tenantIdList keys, masked
POST/api/keys/:tenantIdStore a key
POST/api/keys/:tenantId/:keyId/validateTest a key against its provider
PUT/api/keys/:tenantId/:keyId/invalidateMark a key invalid
DELETE/api/keys/:tenantId/:keyIdDelete a key
GET/api/keys/:tenantId/resolve/:providerWhich key resolves for a provider

Store a key

provider and apiKey are required. Scope defaults to the whole tenant; pass scopeType and scopeId to narrow it.

curl -X POST http://localhost:3001/api/keys/acme \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"apiKey": "sk-…",
"keyType": "byok"
}'

Raw key material is never returned by any endpoint. Reads are masked.

Users and the caller

MethodEndpointDescription
GET/api/current-userThe calling principal
GET/api/current-user/tenantsTenants the caller can reach
POST/api/current-user/syncRe-sync the caller from Clerk
GET/api/usersList users
GET/api/users/statsUser statistics
GET/api/users/:userIdOne user
GET/api/users/chats · /api/users/quotesChats and quotes across users
GET/api/users/:userId/quotesQuotes for one user

Usage and quota

MethodEndpointDescription
GET/api/usage/:tenantIdUsage for a tenant
GET/api/usage/:tenantId/logsUsage log entries
GET/api/usage/:tenantId/checkWhether the tenant is within quota
GET/api/usage/:tenantId/quotaCurrent quota
POST/api/usage/:tenantId/quota/initializeCreate a quota
POST/api/usage/:tenantId/quota/resetReset counters

Exceeding a quota is enforced inside the product; it does not surface as an HTTP 429. See Rate limiting.

Configuration and system

Read-only, apart from a service restart.

MethodEndpointDescription
GET/api/configEffective configuration
GET/api/config/statusConfiguration status
GET/api/system/infoBuild and runtime information
GET/api/system/metricsProcess metrics
GET/api/system/servicesService inventory
GET/api/system/logsRecent logs
GET/api/system/performancePerformance counters
POST/api/system/services/:serviceName/restartRestart a service
GET/api/healthLiveness — the only unauthenticated one here

There is no PUT /api/config; configuration is not editable over the API.

Database and migrations

MethodEndpointDescription
GET/api/database/statsRow counts and sizes
GET/api/database/collectionsTables
GET/api/database/collections/:collectionNameOne table
GET/api/database/schemaSchema
GET/api/database/migrationsApplied migrations
POST/api/database/health-checkConnectivity probe
GET/api/migrations/authorization-policy/statusAuthorization-policy migration state
GET/api/migrations/authorization-policy/previewDry-run preview
POST/api/migrations/authorization-policy/execute · /rollbackRun · undo
GET/api/migrations/mesaspec/route-previewMesaSpec route migration preview
POST/api/migrations/mesaspec/route-executeRun it

External tool integrations

/api/tools, /api/integrations, and /api/admin/integrations return 503 unless TOOL_INTEGRATIONS_ENABLED=true. The check runs before any router logic, so a disabled deployment exposes no part of this surface. See Guarantee status.

MethodEndpointDescription
POST/api/tools/connect · /api/tools/verifyBegin · confirm an authorization
GET/api/integrations/toolkits · /toolkits/:nameAvailable toolkits
GET · DELETE/api/integrations/connections · /connections/:connectionIdConnected accounts
GET · PUT · DELETE/api/integrations/access-rulesWho may use which tool
GET/api/integrations/pendingRequests awaiting approval
POST/api/integrations/pending/:ticketId/approve · /rejectDecide one
GET/api/integrations/historyPast tool executions
GET/api/integrations/groups · /private-llmGroups · private-LLM settings

Other routers

Documented here only as an inventory; these are used by the admin console and are the least stable part of the surface.

Base pathCovers
/api/archivalArchive, trim, jobs, hierarchy, config, queries
/api/authAuthorization rules, moderation, channel and private-chat grants, stats
/api/authorization-edgesReBAC edges
/api/bot-assignment, /api/bot-groupsChannel and group routing for bots
/api/clerk-adminClerk users, tenants, memberships
/api/context-sources, /api/context-tracesContext assembly
/api/dashboardStatus and activity
/api/email-threads, /api/identity-linksEmail threads, identity linking
/api/interactionsMessages, chats, per-channel history
/api/platforms, /api/platform-usersPlatform stats and users
/api/tenant/selectChoose the session's active tenant
/api/admin/gdprRight-to-erasure requests — tenant-admin; there is no export endpoint
/api/admin/weftWeft app templates, apps, bot roster, records, bindings, install, spec editing (drafts + publish) — tenant-admin
/api/weftWeft apps read-only — app list and app detail (bindings + current spec) — any tenant member