All
/v1HTTP endpoints for agent management, providers, skills, traces, and more.
Looking for a complete index? See API Endpoint Catalog for an auto-generated list of all ~308 REST endpoints.
GoClaw's HTTP API is served on the same port as the WebSocket gateway. All endpoints require a Bearer token in the Authorization header matching GOCLAW_GATEWAY_TOKEN.
Interactive documentation: /docs (Swagger UI) · raw spec: /v1/openapi.json
Base URL: http://<host>:<port>
Auth header:
Authorization: Bearer YOUR_GATEWAY_TOKEN
User identity header (optional, for per-user scoping):
X-GoClaw-User-Id: user123
| Header | Purpose |
|---|---|
Authorization |
Bearer token |
X-GoClaw-User-Id |
External user ID for multi-tenant context |
X-GoClaw-Agent-Id |
Agent identifier for scoped operations |
X-GoClaw-Tenant-Id |
Tenant scope — UUID or slug |
Accept-Language |
Locale (en, vi, zh) for i18n error messages |
X-GoClaw-No-Image-Gen |
(optional) Send to opt out of native image generation for that request. Bypasses both the provider capability check and the agent flag tri-level gate. Applies to chat endpoints. |
Input validation: All string inputs are sanitized — SQL special characters are escaped in ILIKE queries, request bodies are limited to 1 MB, and agent/provider/tool names are validated against allowlist patterns ([a-zA-Z0-9_-]).
OpenAI-compatible chat API for programmatic access to agents.
curl -X POST http://localhost:18790/v1/chat/completions \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "goclaw:agent-id-or-key",
"messages": [{"role": "user", "content": "Hello"}],
"stream": false
}'Response (non-streaming):
{
"id": "chatcmpl-...",
"object": "chat.completion",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "..."},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 10, "completion_tokens": 20, "total_tokens": 30}
}Set "stream": true for SSE chunks terminated by data: [DONE].
Alternative response-based protocol (compatible with OpenAI Responses API). Accepts the same auth and returns structured response objects.
Read-only session discovery and branching over HTTP, for automation that cannot hold a WebSocket connection. Non-admin callers only see their own sessions (matched by X-GoClaw-User-Id); admins and gateway-owner tokens see all sessions.
Full session lifecycle (preview, patch, delete, reset, compact) is available via WebSocket RPC. These HTTP routes cover discovery, branching, and incremental history reads.
List sessions with pagination.
curl "http://localhost:18790/v1/sessions?agent_id=AGENT_UUID&limit=20&offset=0" \
-H "Authorization: Bearer TOKEN" \
-H "X-GoClaw-User-Id: user123"Query params:
| Param | Type | Description |
|---|---|---|
agent_id |
string | Filter by agent (alias: agentId) |
channel |
string | Filter by channel |
limit |
integer | Page size (default 20) |
offset |
integer | Page offset (default 0) |
Response: { "sessions": [...], "total": N, "limit": 20, "offset": 0 }
Branch a new session from an existing one, copying messages up to a given index. The {key} path segment is the source session key; the branch reuses the same agent key.
curl -X POST http://localhost:18790/v1/chat/sessions/{key}/branch \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"up_to_index": 8,
"new_session_key": "",
"label": "what-if branch",
"metadata": {}
}'| Field | Type | Description |
|---|---|---|
up_to_index |
integer | Required. Copy messages [0, up_to_index) into the branch |
new_session_key |
string | Optional. Must use the same agent key as the source. Auto-generated when omitted |
label |
string | Optional human-readable branch label |
metadata |
object | Optional string key-value metadata |
Response (201 Created):
{
"ok": true,
"source_key": "agent:researcher:direct:...",
"session_key": "agent:researcher:branch:direct:...",
"copied_messages": 8,
"total_messages": 20,
"label": "what-if branch"
}Returns 409 if the target key already exists, 400 if up_to_index is out of range.
Cursor-based incremental history read — poll for new messages without re-fetching the whole transcript. File and media references in returned messages are signed.
Query params:
| Param | Type | Description |
|---|---|---|
cursor |
integer | Index to start reading from (default 0) |
limit |
integer | Max messages to return (default 50, max 200) |
Response:
{
"session_key": "agent:researcher:direct:...",
"cursor": 0,
"next_cursor": 50,
"total": 120,
"messages": [ ... ],
"reset": false,
"updated": "2026-06-07T08:00:00Z"
}Pass next_cursor as the next cursor to continue. reset: true (with an empty messages array) signals the cursor ran past the current history length — restart from 0.
CRUD operations for agent management. Requires X-GoClaw-User-Id header for multi-tenant context.
List all agents.
curl http://localhost:18790/v1/agents \
-H "Authorization: Bearer TOKEN"Create a new agent.
curl -X POST http://localhost:18790/v1/agents \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_key": "researcher",
"display_name": "Research Assistant",
"agent_type": "open",
"provider": "anthropic",
"model": "claude-sonnet-4-5-20250929",
"context_window": 200000,
"max_tool_iterations": 20,
"workspace": "~/.goclaw/workspace-researcher"
}'Get a single agent by ID.
Update an agent. Send only the fields to change.
Delete an agent.
Regenerate agent context files from templates.
Re-trigger LLM-based summoning for predefined agents.
Force-abort a stuck summoning process. Transitions a summoning agent to summon_failed so it can be reconfigured or re-triggered. Returns 409 if the agent is not currently in summoning state.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{id}/shares |
List shares for an agent |
POST |
/v1/agents/{id}/shares |
Share agent with a user |
DELETE |
/v1/agents/{id}/shares/{userID} |
Revoke a share |
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{id}/instances |
List user instances |
GET |
/v1/agents/{id}/instances/{userID}/files |
List user context files |
PUT |
/v1/agents/{id}/instances/{userID}/files/{fileName} |
Update user context file (admin) |
PATCH |
/v1/agents/{id}/instances/{userID}/metadata |
Update instance metadata (admin) |
GET |
/v1/agents/{id}/system-prompt-preview |
Preview rendered system prompt (admin) |
To read file content, list files via
GET /v1/agents/{id}/instances/{userID}/filesthen retrieve through the Vault or Storage API. There is no single-file GET for instance files.
Export and import agent configurations and data as a tar.gz archive. Supports selective section export.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{id}/export/preview |
Preview export counts per section (no archive built) |
GET |
/v1/agents/{id}/export |
Download agent archive directly (tar.gz) |
GET |
/v1/agents/{id}/export/download/{token} |
Download a previously prepared archive via short-lived token (valid 5 min) |
POST |
/v1/agents/import |
Import archive as a new agent (multipart file field) |
POST |
/v1/agents/import/preview |
Parse archive and return manifest without importing |
POST |
/v1/agents/{id}/import |
Merge archive data into an existing agent |
Export query params:
| Param | Type | Description |
|---|---|---|
sections |
string | Comma-separated list of sections to include. Defaults to config,context_files. Available: config, context_files, memory, knowledge_graph, cron, user_profiles, user_overrides, workspace |
stream |
bool |
When true, returns SSE progress events then a complete event with download_url for token-based download |
Import query params (POST /v1/agents/import):
| Param | Type | Description |
|---|---|---|
agent_key |
string | Override agent key (falls back to archive value) |
display_name |
string | Override display name |
stream |
bool |
Stream import progress via SSE |
Merge import query params (POST /v1/agents/{id}/import):
| Param | Type | Description |
|---|---|---|
include |
string | Comma-separated sections to merge. Defaults to all sections |
stream |
bool |
Stream merge progress via SSE |
Archive format (agent-{key}-YYYYMMDD.tar.gz):
manifest.json — archive manifest (version, sections summary)
agent.json — agent config (sensitive fields stripped)
context_files/{filename} — agent-level context files
user_context_files/{user_id}/{filename} — per-user context files
memory/global.jsonl — global memory documents
memory/users/{user_id}.jsonl — per-user memory documents
knowledge_graph/entities.jsonl — KG entities (portable external IDs)
knowledge_graph/relations.jsonl — KG relations
cron/jobs.jsonl — cron job definitions
user_profiles.jsonl — user profile records
user_overrides.jsonl — per-user model overrides
workspace/ — workspace directory files
Import response (201 Created):
{
"agent_id": "uuid",
"agent_key": "researcher",
"context_files": 3,
"memory_docs": 12,
"kg_entities": 50,
"kg_relations": 30
}Cron jobs are always imported as disabled. Duplicate jobs (same name) are skipped. Max archive size: 500 MB.
Returns routing activity and per-account health for agents using a Codex OAuth pool. Requires the agent's provider to be chatgpt_oauth type with a pool configured.
Auth: Bearer token required. The requesting user must have access to the agent.
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
limit |
integer | 18 |
Number of recent requests to return (max 50) |
strategy values in response:
| Value | Description |
|---|---|
round_robin |
Even distribution across accounts |
priority_order |
Prefer providers in configured order (default) |
BREAKING (clients): Codex pool API responses now return
priority_orderin place of legacyprimary_first/manualfor the same routing config. Request bodies still accept legacy values for backward compatibility. Update consumers comparing strategy strings literally.
Response:
{
"strategy": "priority_order",
"pool_providers": ["openai-codex", "codex-work"],
"stats_sample_size": 24,
"provider_counts": [
{
"provider_name": "openai-codex",
"request_count": 14,
"direct_selection_count": 10,
"failover_serve_count": 4,
"success_count": 13,
"failure_count": 1,
"consecutive_failures": 0,
"success_rate": 92,
"health_score": 88,
"health_state": "healthy",
"last_used_at": "2026-03-27T08:00:00Z"
}
],
"recent_requests": [
{
"span_id": "uuid",
"trace_id": "uuid",
"started_at": "2026-03-27T08:00:00Z",
"status": "success",
"duration_ms": 1240,
"provider_name": "openai-codex",
"selected_provider": "openai-codex",
"model": "gpt-5.4",
"attempt_count": 1,
"used_failover": false
}
]
}If the agent does not use a chatgpt_oauth provider or the pool is not configured, pool_providers is an empty array and provider_counts/recent_requests are empty.
Returns 503 if the tracing store is unavailable.
POST /v1/agents/{id}/wake
{
"message": "Process new data",
"session_key": "optional-session",
"user_id": "optional-user",
"metadata": {}
}Response: {content, run_id, usage?}. Used by orchestrators (n8n, Paperclip) to trigger agent runs externally.
List all LLM providers.
Create an LLM provider.
curl -X POST http://localhost:18790/v1/providers \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-openrouter",
"display_name": "OpenRouter",
"provider_type": "openai_compat",
"api_base": "https://openrouter.ai/api/v1",
"api_key": "sk-or-...",
"enabled": true
}'Supported types: anthropic_native, openai_compat, chatgpt_oauth, gemini_native, dashscope, bailian, minimax, claude_cli, acp
Get a provider by ID.
Update a provider.
Delete a provider.
List models available from the provider (proxied to the upstream API).
Verify provider connectivity or a specific model. Request body is optional (requestBody.required: false).
Ping mode — omit body (or send {}). Returns {"valid": true} if the provider is registered and reachable. Equivalent to a /healthz check; no LLM call is made.
curl -X POST http://localhost:18790/v1/providers/{id}/verify \
-H "Authorization: Bearer TOKEN"Chat-verify mode — include model to perform an actual chat completion against a specific model alias.
curl -X POST http://localhost:18790/v1/providers/{id}/verify \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "anthropic/claude-sonnet-4"}'Response shape — {"valid": true} on success, {"valid": false, "error": "<msg>"} on failure. The legacy {success, models} shape is no longer returned.
Verify embedding model connectivity for a provider.
Re-establish the in-memory connection for a provider — unregisters it from the runtime registry and re-registers from the stored config. Use after editing credentials or when a provider drops out of the live registry. Does not perform a verify; call /verify separately for that.
curl -X POST http://localhost:18790/v1/providers/{id}/reconnect \
-H "Authorization: Bearer TOKEN"The request body is optional. Sending {"verify": true} is rejected with 400 — reconnect and verify are separate operations.
Response:
{
"status": "reconnected",
"provider": { "id": "uuid", "name": "my-openrouter", "...": "..." },
"registry_updated": true,
"cache_invalidated": true
}status is reconnected (re-registered in memory), not_registered (enabled but registration failed), or disabled (provider is disabled). A cache_invalidate event is emitted so connected agents pick up the change.
Returns Codex OAuth pool routing activity at the provider level (see also agent-level endpoint above).
Check if embedding is configured and available across providers.
Check Claude CLI authentication status (global, not per-provider).
List all skills.
Upload a skill as a .zip file (max 20 MB).
curl -X POST http://localhost:18790/v1/skills/upload \
-H "Authorization: Bearer TOKEN" \
-F "file=@my-skill.zip"Get skill metadata.
Update skill metadata.
Delete a skill.
Toggle skill enabled/disabled state.
Set a per-tenant override for a skill (e.g., enable/disable for the current tenant). Admin only.
Remove per-tenant override (revert to default). Admin only.
Export and import custom skills as a tar.gz archive.
| Method | Path | Description |
|---|---|---|
GET |
/v1/skills/export/preview |
Preview counts before export (no archive built) |
GET |
/v1/skills/export |
Download skills archive directly (tar.gz) |
POST |
/v1/skills/import |
Import skills archive (multipart file field) |
Query params for export:
| Param | Type | Description |
|---|---|---|
stream |
bool |
When true, returns SSE progress events then a complete event with download_url |
Archive format (skills-YYYYMMDD.tar.gz):
skills/{slug}/metadata.json — skill metadata (name, slug, visibility, tags)
skills/{slug}/SKILL.md — skill file content
skills/{slug}/grants.jsonl — agent grants (agent_key + pinned version)
Import response (201 Created):
{
"skills_imported": 3,
"skills_skipped": 1,
"grants_applied": 5
}Skills are skipped (not overwritten) if the slug already exists in the tenant. Grants reference agents by
agent_key— unmatched keys are silently skipped.
| Method | Path | Description |
|---|---|---|
GET |
/v1/skills/{id}/grants/agent |
List agent grants for a skill (admin+) |
POST |
/v1/skills/{id}/grants/agent |
Grant skill to an agent (body supports can_manage flag, migration 66) |
DELETE |
/v1/skills/{id}/grants/agent/{agentID} |
Revoke agent grant |
POST |
/v1/skills/{id}/grants/user |
Grant skill to a user |
DELETE |
/v1/skills/{id}/grants/user/{userID} |
Revoke user grant |
GET |
/v1/agents/{agentID}/skills |
List skills accessible to an agent |
| Method | Path | Description |
|---|---|---|
GET |
/v1/skills/{id}/versions |
List available versions |
GET |
/v1/skills/{id}/files |
List files in skill |
GET |
/v1/skills/{id}/files/{path...} |
Read file content |
POST |
/v1/skills/rescan-deps |
Rescan runtime dependencies |
POST |
/v1/skills/install-deps |
Install all missing dependencies |
POST |
/v1/skills/install-dep |
Install a single dependency |
GET |
/v1/skills/runtimes |
Check runtime availability |
POST /v1/tools/invoke
{
"tool": "web_fetch",
"action": "fetch",
"args": {"url": "https://example.com"},
"dryRun": false,
"agentId": "optional",
"channel": "optional",
"chatId": "optional",
"peerKind": "direct"
}Set "dryRun": true to return tool schema without execution.
| Method | Path | Description |
|---|---|---|
GET |
/v1/tools/builtin |
List all built-in tools |
GET |
/v1/tools/builtin/{name} |
Get tool definition |
GET |
/v1/tools/builtin/{name}/tenant-config |
Get tenant-specific configuration for a built-in tool |
PUT |
/v1/tools/builtin/{name} |
Update enabled/settings |
PUT |
/v1/tools/builtin/{name}/tenant-config |
Set per-tenant override (admin) |
DELETE |
/v1/tools/builtin/{name}/tenant-config |
Remove per-tenant override (admin) |
Note: Custom tools via REST API are not currently implemented. MCP servers and skills provide the recommended extension mechanism.
Per-agent vector memory using pgvector.
| Method | Path | Description |
|---|---|---|
GET |
/v1/memory/documents |
List all documents globally |
GET |
/v1/agents/{agentID}/memory/documents |
List documents for agent |
GET |
/v1/agents/{agentID}/memory/documents/{path...} |
Get document details |
PUT |
/v1/agents/{agentID}/memory/documents/{path...} |
Put/update document |
DELETE |
/v1/agents/{agentID}/memory/documents/{path...} |
Delete document |
GET |
/v1/agents/{agentID}/memory/chunks |
List chunks for a document |
POST |
/v1/agents/{agentID}/memory/index |
Index a single document |
POST |
/v1/agents/{agentID}/memory/index-all |
Index all documents |
POST |
/v1/agents/{agentID}/memory/search |
Semantic search |
Optional query parameter ?user_id= for per-user scoping.
New in v3. Enable per-agent via V3 Feature Flags.
Track tool-usage metrics and receive automated improvement suggestions.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/evolution/metrics |
List raw or aggregated evolution metrics |
GET |
/v1/agents/{agentID}/evolution/suggestions |
List evolution suggestions |
PATCH |
/v1/agents/{agentID}/evolution/suggestions/{suggestionID} |
Update suggestion status (pending → approved/rejected/rolled_back) |
GET /v1/agents/{agentID}/evolution/metrics query params:
| Param | Type | Description |
|---|---|---|
type |
string | Filter: tool, retrieval, feedback |
aggregate |
boolean | Return aggregated metrics grouped by tool/metric (default: false) |
since |
ISO 8601 | Start timestamp (default: 7 days ago) |
limit |
integer | Max results (default: 100, max: 500) |
GET /v1/agents/{agentID}/evolution/suggestions query params: status (filter: pending/approved/applied/rejected/rolled_back), limit
Conversation summaries per user session for long-term context continuity.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/episodic |
List episodic summaries |
POST |
/v1/agents/{agentID}/episodic/search |
Hybrid BM25+vector search over episodic summaries |
GET /v1/agents/{agentID}/episodic query params: user_id, limit (default: 20, max: 500), offset
POST /v1/agents/{agentID}/episodic/search body:
{ "query": "Docker optimization", "user_id": "optional", "max_results": 10, "min_score": 0.5 }Persistent document store with vector embeddings and graph link connections.
Admin-scoped endpoints for cross-agent vault operations.
| Method | Path | Description |
|---|---|---|
POST |
/v1/vault/documents |
Create a global vault document |
PUT |
/v1/vault/documents/{docID} |
Update a global vault document |
DELETE |
/v1/vault/documents/{docID} |
Delete a global vault document |
POST |
/v1/vault/links |
Create a global document link |
DELETE |
/v1/vault/links/{linkID} |
Delete a global document link |
POST |
/v1/vault/links/batch |
Batch get document links |
POST |
/v1/vault/upload |
Upload file to vault |
POST |
/v1/vault/rescan |
Trigger vault rescan |
POST |
/v1/vault/search |
Global vault semantic search |
GET |
/v1/vault/enrichment/status |
Check enrichment worker status |
POST |
/v1/vault/enrichment/stop |
Stop the enrichment worker for the current agent |
GET |
/v1/vault/documents |
List documents across all agents |
GET |
/v1/vault/tree |
Returns hierarchical tree view of vault document structure |
GET |
/v1/vault/graph |
Returns vault document graph visualization data (cross-tenant, node limit 2000) |
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/vault/documents |
List documents for a specific agent |
GET |
/v1/agents/{agentID}/vault/documents/{docID} |
Get a single document (full content) |
POST |
/v1/agents/{agentID}/vault/documents |
Create a vault document for an agent |
PUT |
/v1/agents/{agentID}/vault/documents/{docID} |
Update a vault document |
DELETE |
/v1/agents/{agentID}/vault/documents/{docID} |
Delete a vault document |
POST |
/v1/agents/{agentID}/vault/links |
Create a document link |
DELETE |
/v1/agents/{agentID}/vault/links/{linkID} |
Delete a document link |
POST |
/v1/agents/{agentID}/vault/search |
Hybrid FTS+vector search |
GET |
/v1/agents/{agentID}/vault/documents/{docID}/links |
Get outlinks and backlinks for a document |
List query params: scope, doc_type (comma-separated), limit, offset, agent_id (cross-agent only)
Response shape (list):
{ "documents": [...], "total": 42 }Document objects include a chat_id field (nullable string, added in v3.11.0): the specific chat scope — null means no chat scope.
Search body: { "query": "...", "scope": "team", "doc_types": ["guide"], "max_results": 10 }
Controls how an agent routes requests (standalone, delegation, or team-based).
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/orchestration |
Get current orchestration mode and targets |
Response:
{
"mode": "delegate",
"delegate_targets": [{"agent_key": "research-agent", "display_name": "Research Specialist"}],
"team": null
}Mode values: standalone (direct), delegate (routes to agent links), team (routes via team task system)
Per-agent flags controlling v3 subsystems.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/v3-flags |
Get all v3 flags for an agent |
PATCH |
/v1/agents/{agentID}/v3-flags |
Update flags (partial update accepted) |
Flag keys: evolution_enabled, episodic_enabled, vault_enabled, orchestration_enabled, skill_evolve, self_evolve
Per-agent entity-relation graph.
| Method | Path | Description |
|---|---|---|
GET |
/v1/agents/{agentID}/kg/entities |
List/search entities (BM25) |
GET |
/v1/agents/{agentID}/kg/entities/{entityID} |
Get entity with relations |
POST |
/v1/agents/{agentID}/kg/entities |
Upsert entity |
DELETE |
/v1/agents/{agentID}/kg/entities/{entityID} |
Delete entity |
POST |
/v1/agents/{agentID}/kg/traverse |
Traverse graph (max depth 3) |
POST |
/v1/agents/{agentID}/kg/extract |
LLM-powered entity extraction |
GET |
/v1/agents/{agentID}/kg/stats |
Knowledge graph statistics |
GET |
/v1/agents/{agentID}/kg/graph |
Full graph for visualization |
GET |
/v1/agents/{agentID}/kg/graph/compact |
Compact graph representation (lighter payload than full graph) |
POST |
/v1/agents/{agentID}/kg/dedup/scan |
Scan for duplicate entities |
GET |
/v1/agents/{agentID}/kg/dedup |
List dedup candidates |
POST |
/v1/agents/{agentID}/kg/merge |
Merge duplicate entities |
POST |
/v1/agents/{agentID}/kg/dedup/dismiss |
Dismiss a dedup candidate |
List LLM traces. Supports query params: agentId, userId, status, limit, offset.
curl "http://localhost:18790/v1/traces?agentId=UUID&limit=50" \
-H "Authorization: Bearer TOKEN"Poll for trace updates scoped to a single session or agent — designed for live "tail" views. Requires session_key or agent_id. Non-admin callers are restricted to their own traces.
curl "http://localhost:18790/v1/traces/follow?agent_id=AGENT_UUID&since=2026-06-07T08:00:00Z" \
-H "Authorization: Bearer TOKEN"Query params:
| Param | Type | Description |
|---|---|---|
session_key |
string | Session to follow (required if agent_id omitted) |
agent_id |
string | Agent to follow (required if session_key omitted) |
status |
string | Filter by status |
channel |
string | Filter by channel |
since |
RFC 3339 | Only return traces changed after this time |
limit |
integer | Max traces (default 50, max 200) |
include_spans |
boolean | Include span details (default false) |
Get a single trace with all its spans.
Export trace tree as gzipped JSON.
| Method | Path | Description |
|---|---|---|
GET |
/v1/costs/summary |
Cost summary by agent/time range |
| Method | Path | Description |
|---|---|---|
GET |
/v1/usage/timeseries |
Time-series usage points |
GET |
/v1/usage/breakdown |
Breakdown by provider/model/channel |
GET |
/v1/usage/summary |
Summary with period comparison |
Query params: from, to (RFC 3339), agent_id, provider, model, channel, group_by
Spend-cap policies that limit token usage and cost per window, optionally scoped to a specific agent, provider, or model. All endpoints require admin role; write operations additionally require tenant-admin. Policies marked as managed (provisioned by the platform) cannot be edited or deleted (409).
| Method | Path | Description |
|---|---|---|
GET |
/v1/usage-caps/policies |
List spend-cap policies for the current tenant |
POST |
/v1/usage-caps/policies |
Create a policy |
PATCH |
/v1/usage-caps/policies/{id} |
Partial update (all fields optional) |
DELETE |
/v1/usage-caps/policies/{id} |
Delete a policy (204) |
GET |
/v1/usage-caps/utilization |
Current utilization per policy |
GET |
/v1/usage-caps/events |
Recent cap events (throttles, breaches) |
curl -X POST http://localhost:18790/v1/usage-caps/policies \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"window": "day",
"max_tokens": 1000000,
"max_cost_usd": 25.0,
"agent_id": null,
"provider_id": null,
"priority": 100,
"enabled": true
}'| Field | Type | Description |
|---|---|---|
window |
string | Reset window — e.g. day (default). Required |
max_tokens |
integer | Token cap per window (optional) |
max_cost_usd |
float | Cost cap in USD (optional; converted to micros) |
max_cost_micros |
integer | Cost cap in micro-dollars — takes precedence over max_cost_usd (optional) |
agent_id |
UUID | Scope to one agent (optional) |
provider_id |
UUID | Scope to one provider (optional) |
provider_type |
string | Scope to a provider type (optional) |
model_id |
string | Scope to one model (optional) |
priority |
integer | Evaluation priority, higher first (default 100) |
enabled |
boolean | Default true |
Returns 201 with the created policy. PATCH accepts the same fields, all optional — send null for max_tokens / max_cost_* to clear a cap.
GET /v1/usage-caps/events accepts ?limit= and returns { "events": [...] }. Utilization returns { "rows": [...] }.
Per-model pricing catalog plus per-tenant overrides, used to compute usage cost. Read endpoints require admin role; override writes require tenant-admin; the OpenRouter sync requires master scope.
| Method | Path | Description |
|---|---|---|
GET |
/v1/model-pricing |
List the pricing catalog |
GET |
/v1/model-pricing/overrides |
List tenant pricing overrides |
PUT |
/v1/model-pricing/overrides |
Upsert a pricing override |
DELETE |
/v1/model-pricing/overrides/{id} |
Remove an override |
POST |
/v1/model-pricing/sync-openrouter |
Refresh the catalog from OpenRouter (master scope) |
GET /v1/model-pricing query params: model (filter by model ID), limit (default 100). Response { "models": [...] }.
GET /v1/model-pricing/overrides query param: provider_id (optional UUID filter). Response { "overrides": [...] }.
curl -X PUT http://localhost:18790/v1/model-pricing/overrides \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "PROVIDER_UUID",
"provider_type": "openai_compat",
"model_id": "gpt-4o",
"pricing": { "...": "..." },
"enabled": true
}'| Field | Type | Description |
|---|---|---|
provider_id |
UUID | Required |
provider_type |
string | Provider type |
model_id |
string | Required |
pricing |
object | Pricing fields (input/output rates, etc.) |
enabled |
boolean | Default true |
POST /v1/model-pricing/sync-openrouter fetches the OpenRouter catalog and upserts it. Response { "count": N }. Returns 502 if the upstream fetch fails.
Store selected browser cookies so server-side browser sessions (e.g. the browser tool) can reuse a signed-in state. All endpoints require operator role. Cookies are scoped to tenant + user (+ optional agent) and encrypted at rest — GOCLAW_ENCRYPTION_KEY must be set, otherwise sync returns 503.
| Method | Path | Description |
|---|---|---|
POST |
/v1/browser/cookies/sync |
Upsert cookies for the current scope |
GET |
/v1/browser/cookies |
List stored cookie metadata (values never returned) |
DELETE |
/v1/browser/cookies |
Delete stored cookies in the current scope |
curl -X POST http://localhost:18790/v1/browser/cookies/sync \
-H "Authorization: Bearer TOKEN" \
-H "X-GoClaw-User-Id: user123" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "AGENT_UUID",
"source": "chrome-extension",
"cookies": [
{
"domain": "example.com",
"name": "session",
"path": "/",
"value": "abc123",
"secure": true,
"httpOnly": true,
"sameSite": "Lax",
"expiresAt": "2026-12-31T00:00:00Z"
}
]
}'| Field | Type | Description |
|---|---|---|
agent_id |
string | Optional agent scope (alias: agent) |
source |
string | Origin label (default chrome-extension) |
cookies |
array | Cookie items. Required, non-empty, max 200 |
Cookie item fields: domain (or url to derive it), name, path, value (≤ 16 KB), secure, httpOnly (alias http_only), sameSite (alias same_site), and one of expiresAt / expires_at / expirationDate / expiration_date. Total request body is capped at 1 MB.
Response: { "synced": N }.
Returns cookie metadata only — values are never exposed. Optional query filters: agent_id, domain, name, path. Response { "items": [ { "domain", "name", "path", "secure", "httpOnly", "sameSite", "expiresAt", "source", "updatedAt" } ] }.
Delete cookies in the current scope. Same optional filters as the list endpoint. Response { "deleted": N }.
List all MCP server configurations.
Register an MCP server.
curl -X POST http://localhost:18790/v1/mcp/servers \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
"enabled": true
}'Transport options: "stdio", "sse", "streamable-http".
Get an MCP server.
Update an MCP server. Updatable fields:
| Field | Type | Description |
|---|---|---|
name |
string | Server display name |
transport |
string | "stdio", "sse", "streamable-http" |
command |
string | Command to run (stdio) |
args |
string[] | Command arguments |
url |
string | Server URL (sse/streamable-http) |
api_key |
string | API key for the server |
env |
object | Environment variables |
headers |
object | HTTP headers |
enabled |
boolean | Enable/disable |
tool_prefix |
string | Prefix for tool names |
timeout_sec |
integer | Request timeout in seconds |
agent_id |
string | Bind to specific agent |
config |
object | Additional configuration |
settings |
object | Server settings |
Delete an MCP server.
Test connectivity to an MCP server before saving.
Force reconnect a running MCP server.
List tools discovered from a running MCP server.
| Method | Path | Description |
|---|---|---|
GET |
/v1/mcp/servers/{id}/grants |
List grants for a server |
POST |
/v1/mcp/servers/{id}/grants/agent |
Grant server to an agent |
DELETE |
/v1/mcp/servers/{id}/grants/agent/{agentID} |
Revoke agent grant |
GET |
/v1/mcp/grants/agent/{agentID} |
List all grants for an agent |
POST |
/v1/mcp/servers/{id}/grants/user |
Grant server to a user |
DELETE |
/v1/mcp/servers/{id}/grants/user/{userID} |
Revoke user grant |
| Method | Path | Description |
|---|---|---|
POST |
/v1/mcp/requests |
Submit an access request |
GET |
/v1/mcp/requests |
List pending requests |
POST |
/v1/mcp/requests/{id}/review |
Approve or reject a request |
Export and import MCP server configurations and agent grants as a tar.gz archive.
| Method | Path | Description |
|---|---|---|
GET |
/v1/mcp/export/preview |
Preview export counts (no archive built) |
GET |
/v1/mcp/export |
Download MCP archive directly (tar.gz) |
POST |
/v1/mcp/import |
Import MCP archive (multipart file field) |
Per-user credential storage for MCP servers that require individual authentication.
| Method | Path | Description |
|---|---|---|
PUT |
/v1/mcp/servers/{id}/user-credentials |
Set user credentials for a server |
GET |
/v1/mcp/servers/{id}/user-credentials |
Get user credentials |
DELETE |
/v1/mcp/servers/{id}/user-credentials |
Delete user credentials |
Query params for export:
| Param | Type | Description |
|---|---|---|
stream |
bool |
When true, returns SSE progress events then a complete event with download_url |
Archive format (mcp-servers-YYYYMMDD.tar.gz):
servers.jsonl — MCP server definitions
grants.jsonl — agent grants (server_name + agent_key)
Import response (201 Created):
{
"servers_imported": 2,
"servers_skipped": 0,
"grants_applied": 4
}List all channel instances from the database.
Create a channel instance.
curl -X POST http://localhost:18790/v1/channels/instances \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-telegram-bot",
"channel_type": "telegram",
"agent_id": "AGENT_UUID",
"credentials": { "token": "BOT_TOKEN" },
"enabled": true
}'Supported channels: telegram, discord, slack, whatsapp, zalo_oa, zalo_personal, feishu
Get a channel instance.
Update a channel instance. Updatable fields:
| Field | Type | Description |
|---|---|---|
channel_type |
string | Channel type |
credentials |
object | Channel credentials |
agent_id |
string | Bound agent UUID |
enabled |
boolean | Enable/disable |
display_name |
string | Human-readable name |
group_policy |
string | Group message policy |
allow_from |
string[] | Allowed sender IDs |
metadata |
object | Custom metadata |
webhook_secret |
string | Webhook verification secret |
config |
object | Additional configuration |
Delete a channel instance.
| Method | Path | Description |
|---|---|---|
GET |
/v1/channels/instances/{id}/writers/groups |
List groups with write permissions |
GET |
/v1/channels/instances/{id}/writers |
List authorized writers |
POST |
/v1/channels/instances/{id}/writers/test |
Test whether a user would be allowed to write to a group (no mutation) |
POST |
/v1/channels/instances/{id}/writers |
Add a writer |
DELETE |
/v1/channels/instances/{id}/writers/{userId} |
Remove a writer |
POST .../writers/test — dry-run a writer check before persisting one. Body { "group_id": "...", "user_id": "..." } (both required). Always returns 200 with the evaluation:
{
"allowed": true,
"reason": "writer",
"instance_id": "uuid",
"agent_id": "uuid",
"group_id": "telegram:-100123",
"user_id": "user123",
"writer_count": 3
}reason is one of writer, not_writer, no_writers_configured, or invalid_group.
| Method | Path | Description |
|---|---|---|
GET |
/v1/contacts |
List contacts (paginated) |
GET |
/v1/contacts/resolve |
Resolve contacts by IDs (query string ids= repeated; max 100) |
POST |
/v1/contacts/merge |
Merge duplicate contact records |
POST |
/v1/contacts/unmerge |
Unmerge previously merged contacts |
GET |
/v1/contacts/merged/{tenantUserId} |
List merged contacts for a tenant user |
| Method | Path | Description |
|---|---|---|
GET |
/v1/tenant-users |
List tenant users |
GET |
/v1/users/search |
Search users across channels |
| Method | Path | Description |
|---|---|---|
GET |
/v1/teams/{id}/events |
List team events (paginated) |
| Method | Path | Description |
|---|---|---|
POST |
/v1/teams/{teamId}/workspace/upload |
Upload file to team workspace |
PUT |
/v1/teams/{teamId}/workspace/move |
Move/rename file in team workspace |
| Method | Path | Description |
|---|---|---|
GET |
/v1/teams/{teamId}/attachments/{attachmentId}/download |
Download task attachment |
Export and import a complete team (team metadata + all member agents) as a tar.gz archive.
| Method | Path | Description |
|---|---|---|
GET |
/v1/teams/{id}/export/preview |
Preview export counts (members, tasks, agent_links) without building archive |
GET |
/v1/teams/{id}/export |
Download team archive directly (tar.gz) |
POST |
/v1/teams/import |
Import team archive, creating new agents and wiring the team (multipart file field) |
Export query params:
| Param | Type | Description |
|---|---|---|
stream |
bool |
When true, returns SSE progress events then a complete event with download_url |
Archive format (team-{name}-YYYYMMDD.tar.gz):
manifest.json — archive manifest (team_name, agent_keys, sections)
team/team.json — team metadata
team/members.jsonl — team member records
team/tasks.jsonl — team task records
team/comments.jsonl — task comments
team/events.jsonl — task events
team/links.jsonl — agent link records
team/workspace/ — team workspace files
agents/{agent_key}/agent.json — per-agent config
agents/{agent_key}/context_files/ — per-agent context files
agents/{agent_key}/memory/ — per-agent memory documents
agents/{agent_key}/knowledge_graph/ — per-agent KG entities + relations
agents/{agent_key}/cron/ — per-agent cron jobs
agents/{agent_key}/workspace/ — per-agent workspace files
Import response (201 Created):
{
"team_name": "research-team",
"agents_added": 3,
"agent_keys": ["researcher", "writer", "reviewer"]
}Import requires admin role. Agent keys are deduplicated if they already exist (suffixed
-2,-3, …). Cron jobs are always imported as disabled.
Also available as a shared download endpoint (shared with agent export tokens):
| Method | Path | Description |
|---|---|---|
GET |
/v1/export/download/{token} |
Download a prepared archive by short-lived token (valid 5 min, any export type) |
| Method | Path | Description |
|---|---|---|
GET |
/v1/pending-messages |
List all groups with titles |
GET |
/v1/pending-messages/messages |
List messages by channel+key |
DELETE |
/v1/pending-messages |
Delete message group |
POST |
/v1/pending-messages/compact |
LLM-based summarization (async, 202) |
Requires admin role (full gateway token or empty gateway token in dev/single-user mode).
| Method | Path | Description |
|---|---|---|
GET |
/v1/cli-credentials |
List all credentials |
POST |
/v1/cli-credentials |
Create new credential |
GET |
/v1/cli-credentials/{id} |
Get credential details |
PUT |
/v1/cli-credentials/{id} |
Update credential |
DELETE |
/v1/cli-credentials/{id} |
Delete credential |
GET |
/v1/cli-credentials/presets |
Get preset credential templates |
POST |
/v1/cli-credentials/{id}/test |
Test credential connection (dry-run) |
POST |
/v1/cli-credentials/check-binary |
Validate a binary path for CLI credential use |
| Method | Path | Description |
|---|---|---|
GET |
/v1/cli-credentials/{id}/user-credentials |
List user credentials for a CLI config |
GET |
/v1/cli-credentials/{id}/user-credentials/{userId} |
Get user-specific credentials |
PUT |
/v1/cli-credentials/{id}/user-credentials/{userId} |
Set user-specific credentials |
DELETE |
/v1/cli-credentials/{id}/user-credentials/{userId} |
Delete user-specific credentials |
Per-agent binary grants — control which agents can use a specific CLI credential binary, with optional restrictions on arguments, verbosity, and timeout. Requires admin role.
| Method | Path | Description |
|---|---|---|
GET |
/v1/cli-credentials/{id}/agent-grants |
List all agent grants for a credential |
POST |
/v1/cli-credentials/{id}/agent-grants |
Create an agent grant |
GET |
/v1/cli-credentials/{id}/agent-grants/{grantId} |
Get a specific grant |
PUT |
/v1/cli-credentials/{id}/agent-grants/{grantId} |
Update a grant |
DELETE |
/v1/cli-credentials/{id}/agent-grants/{grantId} |
Delete a grant |
POST |
/v1/cli-credentials/{id}/agent-grants/{grantId}/env:reveal |
Reveal decrypted env vars for a grant (rate-limited; never cacheable — POST chosen over GET for CSRF safety) |
Create/update grant fields:
| Field | Type | Description |
|---|---|---|
agent_id |
UUID | Agent to grant access (required on create) |
env_vars |
object | Per-grant env-var overrides (plaintext on input; encrypted at rest via GOCLAW_ENCRYPTION_KEY; only key names ever returned in list/get responses) |
deny_args |
JSON | Argument restrictions (optional) |
deny_verbose |
JSON | Verbose output restrictions (optional) |
timeout_seconds |
integer | Per-agent execution timeout override (optional) |
tips |
string | Usage hints for the agent (optional) |
enabled |
boolean | Enable/disable the grant (default: true) |
Create response (201 Created): the created grant object (no plaintext env values — only env_keys + env_set).
env:revealreturns the decrypted plaintext for the grant's env vars. The endpoint is rate-limited per credential (configurable RPM + burst) and audited. RequiresGOCLAW_ENCRYPTION_KEYto be set; otherwise grants store unencrypted env on disk only when explicitly configured to do so.
Changes to grants emit a cache_invalidate event on the message bus so connected agents pick up the update immediately.
Per-tenant TTS synthesis and configuration. Requires RoleOperator for synthesis/test endpoints and RoleAdmin for config endpoints.
Convert text to audio using the configured TTS provider.
Request body:
{
"text": "Hello, world!",
"provider": "openai",
"voice_id": "alloy",
"model_id": "tts-1"
}| Field | Type | Description |
|---|---|---|
text |
string | Text to synthesize. Required. Max 500 characters. |
provider |
string | Override provider (openai, elevenlabs, minimax, edge, gemini). Optional — defaults to tenant-configured provider. |
voice_id |
string | Voice identifier. Optional. |
model_id |
string | Model identifier. Optional. |
Response: Raw audio bytes with Content-Type matching the provider's MIME type (e.g., audio/mpeg).
Errors: 400 text empty or exceeds limit · 404 no provider configured · 422 invalid model or params · 429 rate limited · 504 synthesis timeout
Test connectivity to a TTS provider using supplied credentials (does not persist config). Supports the same provider set as synthesize. Pass "***" as api_key to re-test a previously saved key without retyping it.
Request body:
{
"provider": "openai",
"api_key": "sk-...",
"api_base": "",
"voice_id": "alloy",
"model_id": "tts-1",
"group_id": "",
"timeout_ms": 10000
}| Field | Type | Description |
|---|---|---|
provider |
string | Required. One of openai, elevenlabs, minimax, edge, gemini. |
api_key |
string | API key. Required for all providers except edge. Pass "***" to reuse a stored key. |
api_base |
string | Custom API base URL. Optional. |
voice_id |
string | Voice identifier. Optional. |
model_id |
string | Model identifier. Optional. |
group_id |
string | MiniMax group ID. Required for minimax. |
rate |
string | Speech rate (Edge TTS only). Optional. |
timeout_ms |
integer | Request timeout in ms. Optional (default: 10 000). |
params |
object | Provider-specific params blob. Optional. |
Response:
{
"success": true,
"provider": "openai",
"latency_ms": 312
}On failure: {"success": false, "error": "..."}
Errors: 400 missing required fields · 422 invalid voice/model/params · 504 test timeout · 502 upstream error
Return the static capability catalog for every known TTS provider — independent of which providers are configured at runtime. Use this to render per-provider param editors before saving credentials.
Response:
{
"providers": [
{
"provider": "openai",
"models": ["tts-1", "tts-1-hd"],
"params": [
{ "key": "speed", "type": "float", "min": 0.25, "max": 4.0, "default": 1.0 }
]
},
...
]
}Each entry in params has: key, type (string|float|int|bool|enum), optional min/max/default/enum_values, and optional depends_on condition.
Auth: RoleOperator
Return the current tenant's TTS configuration. API keys are masked as "***". Requires RoleAdmin and a valid tenant context.
Response:
{
"provider": "openai",
"auto": "off",
"mode": "final",
"max_length": 1500,
"timeout_ms": 30000,
"openai": { "api_key": "***", "api_base": "", "voice": "alloy", "model": "tts-1" },
"elevenlabs": { "api_key": "***", "voice_id": "", "model_id": "" },
"edge": { "voice_id": "", "rate": "" },
"minimax": { "api_key": "***", "group_id": "", "voice_id": "", "model_id": "" },
"gemini": { "api_key": "***", "voice_id": "", "model_id": "" }
}Save TTS configuration for the current tenant. Requires RoleAdmin.
Request body:
{
"provider": "openai",
"auto": "off",
"mode": "final",
"max_length": 1500,
"timeout_ms": 30000,
"openai": {
"api_key": "sk-...",
"api_base": "",
"voice": "alloy",
"model": "tts-1",
"params": {}
},
"gemini": {
"api_key": "...",
"voice_id": "Aoede",
"model_id": "gemini-2.5-flash-preview-tts",
"speakers": "[{\"name\":\"Speaker1\",\"voice\":\"Aoede\"}]"
}
}| Field | Type | Description |
|---|---|---|
provider |
string | Active TTS provider slug. |
auto |
string | Auto-apply mode: off, final, all. |
mode |
string | Synthesis trigger: final (end of turn) or chunk (streaming). |
max_length |
integer | Max characters per synthesis call. |
timeout_ms |
integer | Provider request timeout in ms. |
{provider} |
object | Per-provider config. api_key: "***" leaves stored key unchanged. |
{provider}.params |
object | Provider-specific params blob (validated against capability schema). |
gemini.speakers |
string | JSON-encoded []SpeakerVoice for Gemini multi-speaker mode. |
Response: { "ok": true }
Voice list discovery for TTS providers with tenant-scoped caching. Supports ElevenLabs and MiniMax. Requires a configured API key for the requested provider in TTS config.
| Method | Path | Description |
|---|---|---|
GET |
/v1/voices |
List available voices (served from cache; fetches live on cache miss) |
POST |
/v1/voices/refresh |
Invalidate the voice cache and re-fetch live voices. Requires admin role. |
Query params (GET /v1/voices):
| Param | Type | Description |
|---|---|---|
provider |
string | Voice provider: elevenlabs (default) or minimax. |
GET /v1/voices response:
{
"voices": [
{ "voice_id": "21m00Tcm4TlvDq8ikWAM", "name": "Rachel", "preview_url": "https://..." },
...
]
}Returns 404 when no API key is configured for the requested provider. Returns 502 when the provider API call fails.
Manage system (apk), Python (pip), and Node (npm) packages. Requires authentication.
List all installed packages grouped by category (system, pip, npm).
{ "package": "github-cli" }Use prefix "pip:pandas" or "npm:typescript" to target a specific manager. Without prefix, defaults to system (apk).
Same format as install.
Check if Python and Node runtimes are available.
{ "python": true, "node": true }List GitHub releases for a repository (used by the package picker UI). Auth: viewer+.
Query params:
| Param | Type | Description |
|---|---|---|
repo |
string | Repository in owner/repo format. Required. |
limit |
integer | Max releases to return (1–50, default 10). |
Response:
{
"releases": [
{
"tag": "v2.40.1",
"name": "GitHub CLI 2.40.1",
"published_at": "2024-01-15T12:00:00Z",
"prerelease": false,
"matching_assets": [{ "name": "gh_2.40.1_linux_amd64.tar.gz", "size_bytes": 10485760 }],
"all_assets_count": 12
}
]
}matching_assets contains the asset matching the server's OS/arch (empty if no match). Draft releases are excluded.
List shell command deny groups (security policy).
Watch and apply package updates across system / pip / npm registries. Read access requires viewer+; writes require admin.
| Method | Path | Description |
|---|---|---|
GET |
/v1/packages/updates |
List pending updates discovered from each registry |
POST |
/v1/packages/updates/refresh |
Force-refresh the update registry cache |
POST |
/v1/packages/update |
Apply a single update — body { "package": "pip:pandas" } |
POST |
/v1/packages/updates/apply-all |
Apply every pending update (long-running; returns SSE progress when ?stream=true) |
Updates emit cache_invalidate events on the bus so connected clients refresh their package lists.
Workspace file management.
| Method | Path | Description |
|---|---|---|
GET |
/v1/storage/files |
List files with depth limiting |
GET |
/v1/storage/files/{path...} |
Read file (JSON or raw) |
POST |
/v1/storage/files |
Upload file to workspace (admin) |
DELETE |
/v1/storage/files/{path...} |
Delete file/directory |
PUT |
/v1/storage/move |
Move/rename a file or directory (admin) |
GET |
/v1/storage/size |
Stream storage size (SSE, cached 60 min) |
?raw=true — serve native MIME type. ?depth=N — limit traversal depth.
| Method | Path | Description |
|---|---|---|
POST |
/v1/media/upload |
Upload file (multipart, 50 MB limit) |
GET |
/v1/media/{id} |
Serve media by ID with caching |
Auth via Bearer token or ?token= query param (for <img> and <audio> tags).
| Method | Path | Description |
|---|---|---|
GET |
/v1/files/{path...} |
Serve workspace file by path |
POST |
/v1/files/sign |
Generate signed URL for file access |
Query parameters:
| Param | Type | Description |
|---|---|---|
download |
bool |
When true, forces Content-Disposition: attachment (browser download instead of inline display) |
| Method | Path | Description |
|---|---|---|
GET |
/v1/api-keys |
List all API keys (masked) |
POST |
/v1/api-keys |
Create API key (returns raw key once) |
POST |
/v1/api-keys/{id}/revoke |
Revoke API key |
{
"name": "ci-deploy",
"scopes": ["operator.read", "operator.write"],
"expires_in": 2592000
}The key field is only returned in the create response. Subsequent calls show only the prefix.
| Method | Path | Description |
|---|---|---|
GET |
/v1/auth/chatgpt/{provider}/status |
Check OAuth status for a provider |
GET |
/v1/auth/chatgpt/{provider}/quota |
Fetch Codex/OpenAI quota state |
POST |
/v1/auth/chatgpt/{provider}/start |
Start OAuth flow for a provider |
POST |
/v1/auth/chatgpt/{provider}/callback |
Manual callback handler |
POST |
/v1/auth/chatgpt/{provider}/logout |
Revoke OAuth token for a provider |
Compatibility aliases for the default openai-codex provider:
| Method | Path | Description |
|---|---|---|
GET |
/v1/auth/openai/status |
Check OpenAI OAuth status |
GET |
/v1/auth/openai/quota |
Fetch quota state |
POST |
/v1/auth/openai/start |
Initiate OAuth flow |
POST |
/v1/auth/openai/callback |
Handle OAuth callback manually |
POST |
/v1/auth/openai/logout |
Remove stored OAuth tokens |
Multi-tenant management (gateway token scope only).
| Method | Path | Description |
|---|---|---|
GET |
/v1/tenants |
List tenants |
POST |
/v1/tenants |
Create tenant |
GET |
/v1/tenants/{id} |
Get tenant |
PATCH |
/v1/tenants/{id} |
Update tenant |
GET |
/v1/tenants/{id}/users |
List tenant users |
POST |
/v1/tenants/{id}/users |
Add user to tenant |
DELETE |
/v1/tenants/{id}/users/{userId} |
Remove user from tenant |
Full system backup for disaster recovery. Requires admin role.
| Method | Path | Description |
|---|---|---|
POST |
/v1/system/backup |
Trigger system backup (returns archive or SSE progress) |
GET |
/v1/system/backup/preflight |
Check backup preconditions |
GET |
/v1/system/backup/download/{token} |
Download backup archive by short-lived token |
| Method | Path | Description |
|---|---|---|
POST |
/v1/system/restore |
Restore tenant/system from backup archive. Requires admin role. |
| Method | Path | Description |
|---|---|---|
GET |
/v1/system/backup/s3/config |
Get S3 backup configuration |
PUT |
/v1/system/backup/s3/config |
Update S3 backup configuration |
GET |
/v1/system/backup/s3/list |
List available S3 backup archives |
POST |
/v1/system/backup/s3/upload |
Upload local backup to S3 |
POST |
/v1/system/backup/s3/backup |
Trigger backup directly to S3 |
Per-tenant backup and restore. Admin role required.
| Method | Path | Description |
|---|---|---|
POST |
/v1/tenant/backup |
Trigger tenant backup (returns archive or SSE progress) |
GET |
/v1/tenant/backup/preflight |
Check tenant backup preconditions |
GET |
/v1/tenant/backup/download/{token} |
Download tenant backup archive by short-lived token |
POST |
/v1/tenant/restore |
Restore tenant from a backup archive |
| Method | Path | Description |
|---|---|---|
GET |
/v1/activity |
List activity audit logs (filterable) |
GET |
/v1/activity/aggregate |
Aggregated activity counts grouped by a dimension |
Return activity counts grouped by a dimension instead of raw rows. Non-admin callers are scoped to their own actor ID; grouping by actor_id requires admin role.
Query params:
| Param | Type | Description |
|---|---|---|
group_by |
string | Grouping dimension — e.g. action, entity_type, actor_type, actor_id (admin only) |
actor_type |
string | Filter by actor type |
actor_id |
string | Filter by actor ID |
action |
string | Filter by action |
entity_type |
string | Filter by entity type |
entity_id |
string | Filter by entity ID |
from |
RFC 3339 | Start of time window |
to |
RFC 3339 | End of time window (must be after from) |
limit |
integer | Max groups returned |
Aggregated view of the in-memory runtime log buffer. Requires admin role.
Return runtime log counts grouped by level or source.
curl "http://localhost:18790/v1/logs/runtime/aggregate?group_by=level" \
-H "Authorization: Bearer TOKEN"Query params:
| Param | Type | Description |
|---|---|---|
group_by |
string | level (default) or source |
level |
string | Filter by log level |
source |
string | Filter by log source |
from |
RFC 3339 | Only count entries after this time |
Live tailing of server logs is available over WebSocket via
logs.tail— see WebSocket Protocol.
Per-tenant key-value configuration store. Read access for all authenticated users; write access requires admin role.
| Method | Path | Description |
|---|---|---|
GET |
/v1/system-configs |
List all config entries for current tenant |
GET |
/v1/system-configs/{key} |
Get a single config value by key |
PUT |
/v1/system-configs/{key} |
Set a config value (admin only) |
DELETE |
/v1/system-configs/{key} |
Delete a config entry (admin only) |
| Method | Path | Description |
|---|---|---|
GET |
/v1/edition |
Get current edition info and feature limits |
Exposes GoClaw tools to Claude CLI via streamable HTTP at /mcp/bridge. Only listens on localhost. Protected by gateway token with HMAC-signed context headers.
| Header | Purpose |
|---|---|
X-Agent-ID |
Agent context for tool execution |
X-User-ID |
User context |
X-Channel |
Channel routing |
X-Chat-ID |
Chat routing |
X-Peer-Kind |
direct or group |
X-Bridge-Sig |
HMAC signature over all context fields |
Standard edition only. Gateway routes return
403on Lite. Requires admin role.
Workstations are remote execution endpoints (SSH or Docker) that agents can target for sandboxed command execution. Each workstation has an allowlist of permitted command patterns and a tamper-evident activity audit log.
| Method | Path | Description |
|---|---|---|
GET |
/v1/workstations |
List workstations for the current tenant |
POST |
/v1/workstations |
Create a workstation |
GET |
/v1/workstations/{id} |
Get a workstation by ID |
PUT |
/v1/workstations/{id} |
Update a workstation |
DELETE |
/v1/workstations/{id} |
Delete a workstation |
POST |
/v1/workstations/{id}/test |
Test connectivity (SSH probe or docker ps) — does not execute commands |
GET |
/v1/workstations/{id}/permissions |
List allowlist patterns |
POST |
/v1/workstations/{id}/permissions |
Add an allowlist pattern |
DELETE |
/v1/workstations/{id}/permissions/{permId} |
Remove a pattern |
PUT |
/v1/workstations/{id}/permissions/{permId}/toggle |
Enable/disable a pattern without deleting |
GET |
/v1/workstations/{id}/activity |
List activity audit entries (filterable, paginated) |
Create body:
{
"workstation_key": "build-host",
"name": "Build host",
"backend_type": "ssh",
"metadata": {
"host": "build.internal",
"port": 22,
"user": "claw",
"private_key_ref": "kms://..."
},
"default_cwd": "/srv/builds",
"default_env": {"PATH": "/usr/local/bin:/usr/bin"}
}| Field | Type | Description |
|---|---|---|
workstation_key |
string | Stable client-facing key — unique per tenant |
name |
string | Display name |
backend_type |
enum | ssh or docker (DB CHECK constraint) |
metadata |
object | Backend-specific connection config — encrypted at rest |
default_cwd |
string | Default working directory for exec calls |
default_env |
object | Env vars merged into every exec — encrypted at rest |
active |
boolean | Workstation is selectable for agent linking |
Activity log entries:
| Field | Type | Description |
|---|---|---|
action |
enum | exec (ran) or deny (rejected by allowlist) |
cmd_hash |
string | SHA-256 of the full command line |
cmd_preview |
string | First 200 bytes of the command (truncated, no secrets) |
exit_code |
integer | Process exit code (nullable for deny) |
duration_ms |
integer | Wall time (nullable for deny) |
agent_id |
UUID | Agent that initiated the call |
Workstation backends share a single per-tenant rate limit and obey the global shell deny-groups list.
Two surfaces:
- Inbound webhook endpoints — receive HMAC-signed requests from external systems and route them through agents or channels. No bearer token required; auth is performed via
X-GoClaw-Signature(HMAC-SHA256) + IP allowlist + optionallocalhost_onlygate. - Webhook administration — CRUD over the webhook registry. Requires admin role and gateway token.
Inbound webhooks require
GOCLAW_ENCRYPTION_KEYto be set so secrets can be stored encrypted at rest. See Environment Variables.
| Method | Path | Description |
|---|---|---|
POST |
/v1/webhooks/llm |
LLM-kind webhook entrypoint (OpenAI-compatible payload routed to the configured agent) |
POST |
/v1/webhooks/message |
Message-kind webhook entrypoint (delivers to a channel/chat) |
Both receivers require headers:
| Header | Purpose |
|---|---|
X-GoClaw-Webhook-Id |
Webhook UUID |
X-GoClaw-Signature |
sha256=... HMAC of the raw body using the webhook's signing key |
X-GoClaw-Timestamp |
RFC3339 timestamp (≤ 5 min skew) |
Idempotency-Key |
Optional — dedupes repeated deliveries (TTL stored in webhook_calls) |
Mode is selected via the query string ?mode=sync|async (default sync for llm, async for message).
| Method | Path | Description |
|---|---|---|
GET |
/v1/webhooks |
List webhooks for the current tenant |
POST |
/v1/webhooks |
Create a webhook — response includes one-time secret + hmac_signing_key |
GET |
/v1/webhooks/{id} |
Get a webhook (secret is never returned again after creation) |
PATCH |
/v1/webhooks/{id} |
Update mutable fields (scopes, rate limits, allowlist, flags) |
POST |
/v1/webhooks/{id}/rotate |
Rotate signing key — returns the new secret once |
DELETE |
/v1/webhooks/{id} |
Revoke a webhook (soft-delete; sets revoked=true) |
Create body:
{
"name": "Datadog incidents",
"kind": "message",
"agent_id": "uuid (required for kind=llm)",
"channel_id": "uuid (required for kind=message)",
"scopes": ["chat.send"],
"rate_limit_per_min": 60,
"ip_allowlist": ["10.0.0.0/8", "203.0.113.42"],
"require_hmac": true,
"localhost_only": false
}| Field | Type | Description |
|---|---|---|
kind |
enum | llm or message (DB CHECK constraint) |
agent_id |
UUID | Required for llm; ignored for message |
channel_id |
UUID | Required for message; ignored for llm |
scopes |
string[] | Permission scopes the inbound request can exercise (default minimal) |
rate_limit_per_min |
integer | Per-webhook rate limit (default tenant-wide cap) |
ip_allowlist |
string[] | CIDR or single-IP entries; empty = no IP restriction |
require_hmac |
boolean | Enforce HMAC signature (default true) |
localhost_only |
boolean | Reject non-loopback callers (Lite edition forces true) |
Create response (201 Created):
{
"id": "uuid",
"secret": "wh_...",
"hmac_signing_key": "raw 32-byte hex",
"secret_prefix": "wh_xxxx",
"kind": "message",
"...": "..."
}
secretandhmac_signing_keyare returned only on create and rotate. Subsequent GETs exposesecret_prefix(first 4 chars) and a one-waysecret_hash. Thewebhook_callstable records every delivery withattempts,status(queued|running|done|failed|dead),mode(sync|async),delivery_id, and an optionallease_tokenfor async lease-based dispatch.
Admin-only self-upgrade flow that downloads a signed release archive and restarts the gateway process in-place.
| Method | Path | Description |
|---|---|---|
POST |
/v1/system/gateway/upgrade |
Trigger an upgrade — body { "target_version": "v3.12.0" } or omitted for latest |
GET |
/v1/system/gateway/upgrade/status |
Poll upgrade progress (`idle |
Upgrade is a one-way operation; restore from backup if a release proves bad. The endpoint refuses to run when the gateway is launched without write access to its own binary.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check (no auth) |
GET |
/v1/openapi.json |
OpenAPI 3.0 spec |
GET |
/docs |
Swagger UI |
Success:
{ "id": "uuid", "name": "...", ... }Error:
{
"error": {
"code": "ERR_AGENT_NOT_FOUND",
"message": "Agent not found. Verify the agent ID and try again."
}
}Error responses use a structured envelope with code (machine-readable error type) and message (human-readable, i18n-translated).
| Code | Meaning |
|---|---|
200 |
OK |
201 |
Created |
400 |
Bad request (invalid JSON, missing fields) |
401 |
Unauthorized |
403 |
Forbidden |
404 |
Not found |
409 |
Conflict (duplicate name) |
429 |
Rate limited |
500 |
Internal server error |
Error messages are localized based on the Accept-Language header.
The following are only available via WebSocket RPC, not HTTP:
- Sessions: List, preview, patch, delete, reset (
sessions.*) - Cron jobs: List, create, update, delete, toggle, status, run, runs (
cron.*) - Config management: Get, apply, patch, schema (
config.*) - Config permissions: List, check, grant, revoke (
config.permissions.*) - Workstations: List, get, create, update, delete, test, link/unlink agent, permissions CRUD, activity (
workstations.*) - Send messages: Send to channels (
send) - Chat: Send, history, abort, inject, session status (
chat.*) - Heartbeat: Get, set, toggle, test, logs, checklist, targets (
heartbeat.*) - Device pairing: Request, approve, deny, list, revoke (
device.pair.*) - Exec approvals: List, approve, deny (
exec.approval.*) - TTS: Status, enable, disable, convert, set provider, providers (
tts.*) - Browser automation: Act, snapshot, screenshot (
browser.*) - Logs: Tail server logs (
logs.tail)
See WebSocket Protocol for full method reference and frame format.
- WebSocket Protocol — real-time RPC for chat and agent events
- Config Reference — full
config.jsonschema - Database Schema — table definitions and relationships