Skip to content

Latest commit

 

History

History
2149 lines (1569 loc) · 73 KB

File metadata and controls

2149 lines (1569 loc) · 73 KB

REST API

All /v1 HTTP endpoints for agent management, providers, skills, traces, and more.

Overview

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

Common Headers

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_-]).


Chat Completions

OpenAI-compatible chat API for programmatic access to agents.

POST /v1/chat/completions

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].


OpenResponses Protocol

POST /v1/responses

Alternative response-based protocol (compatible with OpenAI Responses API). Accepts the same auth and returns structured response objects.


Sessions

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.

GET /v1/sessions

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 }

POST /v1/chat/sessions/{key}/branch

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.

GET /v1/chat/sessions/{key}/history/follow

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.


Agents

CRUD operations for agent management. Requires X-GoClaw-User-Id header for multi-tenant context.

GET /v1/agents

List all agents.

curl http://localhost:18790/v1/agents \
  -H "Authorization: Bearer TOKEN"

POST /v1/agents

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 /v1/agents/{id}

Get a single agent by ID.

PUT /v1/agents/{id}

Update an agent. Send only the fields to change.

DELETE /v1/agents/{id}

Delete an agent.

POST /v1/agents/{id}/regenerate

Regenerate agent context files from templates.

POST /v1/agents/{id}/resummon

Re-trigger LLM-based summoning for predefined agents.

POST /v1/agents/{id}/cancel-summon

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.

Agent Shares

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

Predefined Agent Instances

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}/files then retrieve through the Vault or Storage API. There is no single-file GET for instance files.

Agent Export / Import

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.


GET /v1/agents/{id}/codex-pool-activity

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_order in place of legacy primary_first / manual for 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.


Wake (External Trigger)

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.


Providers

GET /v1/providers

List all LLM providers.

POST /v1/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 /v1/providers/{id}

Get a provider by ID.

PUT /v1/providers/{id}

Update a provider.

DELETE /v1/providers/{id}

Delete a provider.

GET /v1/providers/{id}/models

List models available from the provider (proxied to the upstream API).

POST /v1/providers/{id}/verify

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.

POST /v1/providers/{id}/verify-embedding

Verify embedding model connectivity for a provider.

POST /v1/providers/{id}/reconnect

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.

GET /v1/providers/{id}/codex-pool-activity

Returns Codex OAuth pool routing activity at the provider level (see also agent-level endpoint above).

GET /v1/embedding/status

Check if embedding is configured and available across providers.

GET /v1/providers/claude-cli/auth-status

Check Claude CLI authentication status (global, not per-provider).


Skills

GET /v1/skills

List all skills.

POST /v1/skills/upload

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 /v1/skills/{id}

Get skill metadata.

PUT /v1/skills/{id}

Update skill metadata.

DELETE /v1/skills/{id}

Delete a skill.

POST /v1/skills/{id}/toggle

Toggle skill enabled/disabled state.

PUT /v1/skills/{id}/tenant-config

Set a per-tenant override for a skill (e.g., enable/disable for the current tenant). Admin only.

DELETE /v1/skills/{id}/tenant-config

Remove per-tenant override (revert to default). Admin only.

Skills Export / Import

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.


Skill Grants

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

Skill Files & Dependencies

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

Tools

Direct Invocation

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.

Built-in Tools

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.


Memory

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.


V3 Agent Capabilities

New in v3. Enable per-agent via V3 Feature Flags.

Evolution

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 (pendingapproved/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


Episodic Memory

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 }

Knowledge Vault

Persistent document store with vector embeddings and graph link connections.

Global Vault Endpoints

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)

Agent-Scoped Vault Endpoints

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 }


Orchestration

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)


V3 Feature Flags

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


Knowledge Graph

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

Traces

GET /v1/traces

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"

GET /v1/traces/follow

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 /v1/traces/{traceID}

Get a single trace with all its spans.

GET /v1/traces/{traceID}/export

Export trace tree as gzipped JSON.

Costs

Method Path Description
GET /v1/costs/summary Cost summary by agent/time range

Usage & Analytics

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


Usage Caps

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)

POST /v1/usage-caps/policies

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": [...] }.


Model Pricing

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": [...] }.

PUT /v1/model-pricing/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.


Browser Cookie Sync

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

POST /v1/browser/cookies/sync

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 }.

GET /v1/browser/cookies

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 /v1/browser/cookies

Delete cookies in the current scope. Same optional filters as the list endpoint. Response { "deleted": N }.


MCP Servers

GET /v1/mcp/servers

List all MCP server configurations.

POST /v1/mcp/servers

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 /v1/mcp/servers/{id}

Get an MCP server.

PUT /v1/mcp/servers/{id}

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 /v1/mcp/servers/{id}

Delete an MCP server.

POST /v1/mcp/servers/test

Test connectivity to an MCP server before saving.

POST /v1/mcp/servers/{id}/reconnect

Force reconnect a running MCP server.

GET /v1/mcp/servers/{id}/tools

List tools discovered from a running MCP server.

MCP Grants

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

MCP Access Requests

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

MCP Export / Import

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)

MCP User Credentials

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
}

Channel Instances

GET /v1/channels/instances

List all channel instances from the database.

POST /v1/channels/instances

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 /v1/channels/instances/{id}

Get a channel instance.

PUT /v1/channels/instances/{id}

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 /v1/channels/instances/{id}

Delete a channel instance.

Group Writers

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.


Contacts

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

Tenant Users

Method Path Description
GET /v1/tenant-users List tenant users
GET /v1/users/search Search users across channels

Team Events

Method Path Description
GET /v1/teams/{id}/events List team events (paginated)

Team Workspace

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

Team Attachments

Method Path Description
GET /v1/teams/{teamId}/attachments/{attachmentId}/download Download task attachment

Team Export / Import

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)

Pending Messages

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)

Secure CLI Credentials

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

Per-User CLI Credentials

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

CLI Credential Agent Grants

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:reveal returns the decrypted plaintext for the grant's env vars. The endpoint is rate-limited per credential (configurable RPM + burst) and audited. Requires GOCLAW_ENCRYPTION_KEY to 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.


Text-to-Speech (TTS)

Per-tenant TTS synthesis and configuration. Requires RoleOperator for synthesis/test endpoints and RoleAdmin for config endpoints.

POST /v1/tts/synthesize

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

POST /v1/tts/test-connection

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

GET /v1/tts/capabilities

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

GET /v1/tts/config

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": "" }
}

POST /v1/tts/config

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 }


Voices

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.


Runtime & Packages

Manage system (apk), Python (pip), and Node (npm) packages. Requires authentication.

GET /v1/packages

List all installed packages grouped by category (system, pip, npm).

POST /v1/packages/install

{ "package": "github-cli" }

Use prefix "pip:pandas" or "npm:typescript" to target a specific manager. Without prefix, defaults to system (apk).

POST /v1/packages/uninstall

Same format as install.

GET /v1/packages/runtimes

Check if Python and Node runtimes are available.

{ "python": true, "node": true }

GET /v1/packages/github-releases

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.

GET /v1/shell-deny-groups

List shell command deny groups (security policy).

Package Updates

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.


Storage

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.


Media

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).


Files

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)

API Keys

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

Create Request

{
  "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.


OAuth

Per-Provider ChatGPT/Codex OAuth

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

Legacy OpenAI Aliases

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

Tenants

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

Backup & Restore

System Backup (Admin)

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

System Restore (Admin)

Method Path Description
POST /v1/system/restore Restore tenant/system from backup archive. Requires admin role.

System Backup S3

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

Tenant Backup

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

Activity & Audit

Method Path Description
GET /v1/activity List activity audit logs (filterable)
GET /v1/activity/aggregate Aggregated activity counts grouped by a dimension

GET /v1/activity/aggregate

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

Runtime Logs

Aggregated view of the in-memory runtime log buffer. Requires admin role.

GET /v1/logs/runtime/aggregate

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.


System Configs

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)

Edition

Method Path Description
GET /v1/edition Get current edition info and feature limits

MCP Bridge

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

Workstations

Standard edition only. Gateway routes return 403 on 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.


Webhooks

Two surfaces:

  1. 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 + optional localhost_only gate.
  2. Webhook administration — CRUD over the webhook registry. Requires admin role and gateway token.

Inbound webhooks require GOCLAW_ENCRYPTION_KEY to be set so secrets can be stored encrypted at rest. See Environment Variables.

Inbound Receivers

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).

Webhook Administration

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",
  "...": "..."
}

secret and hmac_signing_key are returned only on create and rotate. Subsequent GETs expose secret_prefix (first 4 chars) and a one-way secret_hash. The webhook_calls table records every delivery with attempts, status (queued|running|done|failed|dead), mode (sync|async), delivery_id, and an optional lease_token for async lease-based dispatch.


Gateway Self-Upgrade

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.


System

Method Path Description
GET /health Health check (no auth)
GET /v1/openapi.json OpenAPI 3.0 spec
GET /docs Swagger UI

Common Response Shapes

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.


WebSocket-Only Endpoints

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.


What's Next