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
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/bots/tenants | List the tenants you administer |
| GET | /api/bots/tenants/:tenantId | Get a tenant with its bots |
| POST | /api/bots/tenants | Create a tenant |
| PUT | /api/bots/tenants/:tenantId | Update a tenant |
| DELETE | /api/bots/tenants/:tenantId | Delete 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
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/bots | List the bots of every tenant you administer |
| GET | /api/bots/available-agents | Agents that can be attached to a bot |
| POST | /api/bots/:tenantId/bots | Create a bot |
| GET | /api/bots/:tenantId/:botId | Get a bot |
| PUT | /api/bots/:tenantId/:botId | Update a bot |
| DELETE | /api/bots/:tenantId/:botId | Delete a bot |
| GET | /api/bots/:tenantId/:botId/stats | Bot statistics |
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.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/bots/:tenantId/:botId/integrations | List a bot's integrations |
| GET | /api/bots/:tenantId/:botId/integrations/:integrationId | Get one integration |
| POST | /api/bots/:tenantId/:botId/integrations | Create an integration |
| PUT | /api/bots/:tenantId/:botId/integrations/:integrationId | Update an integration |
| DELETE | /api/bots/:tenantId/:botId/integrations/:integrationId | Delete 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
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/agents | Agents and their usage |
| GET | /api/agents/stats | Aggregate agent statistics |
| GET | /api/agents/:agentId | One agent |
| PATCH | /api/agents/:agentId/status | Enable or disable an agent |
| POST | /api/agents/triage-preview | Preview which agent would handle a message |
| POST | /api/agents/registry/refresh | Reload agents from the database |
Definitions
Agent, tool, and capability specs — the authoring surface behind the runtime.
| Method | Endpoint | Description |
|---|---|---|
| GET · POST | /api/definitions/agents | List · create agent definitions |
| GET · DELETE | /api/definitions/agents/:id | Get · delete one |
| GET | /api/definitions/agents/:id/tools | Tools attached to an agent |
| GET | /api/definitions/agents/:id/capabilities | Capabilities attached to an agent |
| GET · POST | /api/definitions/tools | List · create tool definitions |
| GET · DELETE | /api/definitions/tools/:id | Get · delete one |
| GET | /api/definitions/tools/manifest | Full tool manifest |
| GET | /api/definitions/tools/available | Tools available to the caller |
| POST | /api/definitions/tools/sync | Sync tool definitions |
| GET · POST | /api/definitions/capabilities | List · create capabilities |
| GET · DELETE | /api/definitions/capabilities/:id | Get · delete one |
| GET | /api/definitions/marketplace | Published, shareable definitions |
| POST | /api/definitions/{agents,capabilities,tools}/:id/publish | Publish to the marketplace |
| POST | /api/definitions/{agents,capabilities,tools}/:id/unpublish | Withdraw |
| POST | /api/definitions/{agents,capabilities}/:id/copy | Copy a published definition into your tenant |
| GET | /api/definitions/health | Definition 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:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/keys/:tenantId | List keys, masked |
| POST | /api/keys/:tenantId | Store a key |
| POST | /api/keys/:tenantId/:keyId/validate | Test a key against its provider |
| PUT | /api/keys/:tenantId/:keyId/invalidate | Mark a key invalid |
| DELETE | /api/keys/:tenantId/:keyId | Delete a key |
| GET | /api/keys/:tenantId/resolve/:provider | Which 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
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/current-user | The calling principal |
| GET | /api/current-user/tenants | Tenants the caller can reach |
| POST | /api/current-user/sync | Re-sync the caller from Clerk |
| GET | /api/users | List users |
| GET | /api/users/stats | User statistics |
| GET | /api/users/:userId | One user |
| GET | /api/users/chats · /api/users/quotes | Chats and quotes across users |
| GET | /api/users/:userId/quotes | Quotes for one user |
Usage and quota
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/usage/:tenantId | Usage for a tenant |
| GET | /api/usage/:tenantId/logs | Usage log entries |
| GET | /api/usage/:tenantId/check | Whether the tenant is within quota |
| GET | /api/usage/:tenantId/quota | Current quota |
| POST | /api/usage/:tenantId/quota/initialize | Create a quota |
| POST | /api/usage/:tenantId/quota/reset | Reset 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.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/config | Effective configuration |
| GET | /api/config/status | Configuration status |
| GET | /api/system/info | Build and runtime information |
| GET | /api/system/metrics | Process metrics |
| GET | /api/system/services | Service inventory |
| GET | /api/system/logs | Recent logs |
| GET | /api/system/performance | Performance counters |
| POST | /api/system/services/:serviceName/restart | Restart a service |
| GET | /api/health | Liveness — the only unauthenticated one here |
There is no PUT /api/config; configuration is not editable over the API.
Database and migrations
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/database/stats | Row counts and sizes |
| GET | /api/database/collections | Tables |
| GET | /api/database/collections/:collectionName | One table |
| GET | /api/database/schema | Schema |
| GET | /api/database/migrations | Applied migrations |
| POST | /api/database/health-check | Connectivity probe |
| GET | /api/migrations/authorization-policy/status | Authorization-policy migration state |
| GET | /api/migrations/authorization-policy/preview | Dry-run preview |
| POST | /api/migrations/authorization-policy/execute · /rollback | Run · undo |
| GET | /api/migrations/mesaspec/route-preview | MesaSpec route migration preview |
| POST | /api/migrations/mesaspec/route-execute | Run 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.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/tools/connect · /api/tools/verify | Begin · confirm an authorization |
| GET | /api/integrations/toolkits · /toolkits/:name | Available toolkits |
| GET · DELETE | /api/integrations/connections · /connections/:connectionId | Connected accounts |
| GET · PUT · DELETE | /api/integrations/access-rules | Who may use which tool |
| GET | /api/integrations/pending | Requests awaiting approval |
| POST | /api/integrations/pending/:ticketId/approve · /reject | Decide one |
| GET | /api/integrations/history | Past tool executions |
| GET | /api/integrations/groups · /private-llm | Groups · 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 path | Covers |
|---|---|
/api/archival | Archive, trim, jobs, hierarchy, config, queries |
/api/auth | Authorization rules, moderation, channel and private-chat grants, stats |
/api/authorization-edges | ReBAC edges |
/api/bot-assignment, /api/bot-groups | Channel and group routing for bots |
/api/clerk-admin | Clerk users, tenants, memberships |
/api/context-sources, /api/context-traces | Context assembly |
/api/dashboard | Status and activity |
/api/email-threads, /api/identity-links | Email threads, identity linking |
/api/interactions | Messages, chats, per-channel history |
/api/platforms, /api/platform-users | Platform stats and users |
/api/tenant/select | Choose the session's active tenant |
/api/admin/gdpr | Right-to-erasure requests — tenant-admin; there is no export endpoint |
/api/admin/weft | Weft app templates, apps, bot roster, records, bindings, install, spec editing (drafts + publish) — tenant-admin |
/api/weft | Weft apps read-only — app list and app detail (bindings + current spec) — any tenant member |