Base URL
OpenAPI Specification
A machine-readable OpenAPI 3.1 schema is available at:Authentication
Use the following header on every request:Error Handling
Error responses follow RFC 9457 Problem Details and returnContent-Type: application/problem+json.
typeis a URI identifying the problem type (about:blankmeans no extra semantics beyond the HTTP status).statusis the HTTP status code.titleis the standard HTTP reason phrase.detailis a human-readable error message.
API Keys
API key management endpoints currently use the/api/public/v1 path family.
These endpoints use the same auth headers and Problem Detail error format as the /v1 endpoints.
List API keys
GET /api/public/v1/access-api-keys
GET /api/public/v1/access-api-keys
Create an API key
POST /api/public/v1/access-api-keys
POST /api/public/v1/access-api-keys
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Key name (1-128 characters) |
Revoke an API key
DELETE /api/public/v1/access-api-keys/{key_id}
DELETE /api/public/v1/access-api-keys/{key_id}
| Field | Type | Required | Description |
|---|---|---|---|
key_id | string | Yes | ID of the key to revoke |
Identity
Get current user
GET /v1/me
GET /v1/me
Agents
Versioned agent endpoints live under/v1/agents.
List agents
GET /v1/agents
GET /v1/agents
| Field | Type | Required | Description |
|---|---|---|---|
workspace_id | string | No | Filter to a specific workspace |
cursor | string | No | Cursor for pagination |
limit | integer | No | Max results to return |
Create an agent
POST /v1/agents
POST /v1/agents
| Field | Type | Required | Description |
|---|---|---|---|
workspace_id | string | No | Workspace to assign the agent to |
owner_user_id | string | No | Optional owner override |
is_subagent | boolean | No | Whether the new agent is a subagent |
derived_from_agent_id | string | No | Source agent ID for derived agents |
agent_id | string | No | Explicit agent ID override |
201 CreatedGet an agent
GET /v1/agents/{agent_id}
GET /v1/agents/{agent_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Delete an agent
DELETE /v1/agents/{agent_id}
DELETE /v1/agents/{agent_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
204 No Content — empty body on success. Returns 404 if the agent was not found.Runs
Trigger, list, cancel, and delete runs under each agent.List runs
GET /v1/agents/{agent_id}/runs
GET /v1/agents/{agent_id}/runs
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default 1) |
page_size | integer | No | Results per page (default 100) |
filter_status | string | No | Run status filter |
filter_run_id | string | No | Filter by exact run ID |
filter_started_after | string | No | ISO-8601 lower bound |
filter_started_before | string | No | ISO-8601 upper bound |
filter_policy_type | string | No | Policy type filter |
filter_policy_group | string | No | Policy group filter (builder/runner) |
Start a run
POST /v1/agents/{agent_id}/runs
POST /v1/agents/{agent_id}/runs
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
run_mode | string | No | "build" or "run" |
user_message | string | No | Optional user message for the run |
skip_deploy_check | boolean | No | Skip deployment checks before starting |
201 CreatedDelete a run
DELETE /v1/agents/{agent_id}/runs/{run_id}
DELETE /v1/agents/{agent_id}/runs/{run_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
run_id | string | Yes | The run ID |
204 No Content — empty body on success. Returns 404 if the run was not found.Cancel a run
POST /v1/agents/{agent_id}/runs/{run_id}/cancel
POST /v1/agents/{agent_id}/runs/{run_id}/cancel
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
run_id | string | Yes | The run ID |
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No | Human-readable cancellation reason |
{} or omit the body altogether.Exampleerror means success. A non-empty value is informational (e.g. the run was already stopped).Events
List run events
GET /v1/agents/{agent_id}/runs/{run_id}/events
GET /v1/agents/{agent_id}/runs/{run_id}/events
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
run_id | string | Yes | The run ID |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Max events to return |
after_index | integer | No | Return events after this event index |
Webhooks
Register webhook URLs to receive push notifications when runs change state. Instead of polling for run completion, your backend gets an HTTP POST for each lifecycle event.Event types
| Event | Fired when |
|---|---|
run.started | A run begins executing |
run.completed | A run finishes (success, partial, or fail outcome) |
run.failed | A run hits a policy error |
run.stopped | A run is stopped by the user |
run.paused | A run is paused by the user, or paused by the agent for 15+ minutes |
Create a webhook
POST /v1/agents/{agent_id}/webhooks
POST /v1/agents/{agent_id}/webhooks
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS (or HTTP) endpoint to receive events |
events | string[] | Yes | Event types to subscribe to (at least one required) |
201 CreatedList webhooks
GET /v1/agents/{agent_id}/webhooks
GET /v1/agents/{agent_id}/webhooks
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Get a webhook
GET /v1/agents/{agent_id}/webhooks/{webhook_id}
GET /v1/agents/{agent_id}/webhooks/{webhook_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
webhook_id | string | Yes | The webhook ID |
Update a webhook
PATCH /v1/agents/{agent_id}/webhooks/{webhook_id}
PATCH /v1/agents/{agent_id}/webhooks/{webhook_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
webhook_id | string | Yes | The webhook ID |
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | New endpoint URL |
events | string[] | No | New set of event types |
status | string | No | "active" or "disabled" |
Delete a webhook
DELETE /v1/agents/{agent_id}/webhooks/{webhook_id}
DELETE /v1/agents/{agent_id}/webhooks/{webhook_id}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
webhook_id | string | Yes | The webhook ID |
204 No ContentWebhook payload
When a subscribed event fires, Twin sends an HTTP POST to your webhook URL with a JSON body:| Field | Description |
|---|---|
event | The event type (e.g. run.completed) |
timestamp | ISO-8601 timestamp of when the event was dispatched |
data.run_id | The run that triggered the event |
data.agent_id | The agent the run belongs to |
data.status | Run status: in_progress, completed, error, stopped, or paused |
data.outcome | Present on run.completed: success, partial, or fail |
data.finished_at | Present on terminal events (run.completed, run.failed, run.stopped) |
Verifying webhook signatures
Every webhook delivery includes two headers:| Header | Value |
|---|---|
X-Cobb-Signature | sha256=<hex HMAC-SHA256> |
X-Cobb-Event | The event type (e.g. run.completed) |
HMAC-SHA256(signing_secret, raw_request_body) and compare it to the signature in the header.
Example (Node.js)
Schedules
Manage cron-based schedules for agents. Each agent can have at most one schedule.Get agent schedule
GET /v1/agents/{agent_id}/schedule
GET /v1/agents/{agent_id}/schedule
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
{"schedule": null} if no schedule is set.Set agent schedule
PUT /v1/agents/{agent_id}/schedule
PUT /v1/agents/{agent_id}/schedule
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
cron | string | Yes | Cron expression (7-field format) |
sec min hour day month day-of-week year.Delete agent schedule
DELETE /v1/agents/{agent_id}/schedule
DELETE /v1/agents/{agent_id}/schedule
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Pause schedule
POST /v1/agents/{agent_id}/schedule/pause
POST /v1/agents/{agent_id}/schedule/pause
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Resume schedule
POST /v1/agents/{agent_id}/schedule/resume
POST /v1/agents/{agent_id}/schedule/resume
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
List all schedules
GET /v1/schedules
GET /v1/schedules
Instructions
Read and update the auto-generated instructions for an agent, with version history.Get instructions
GET /v1/agents/{agent_id}/instructions
GET /v1/agents/{agent_id}/instructions
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Update instructions
PUT /v1/agents/{agent_id}/instructions
PUT /v1/agents/{agent_id}/instructions
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The new instructions text |
source_type | string | No | Source of the update (e.g. "api", "builder") |
source_id | string | No | Identifier for the source |
Get instructions history
GET /v1/agents/{agent_id}/instructions/history
GET /v1/agents/{agent_id}/instructions/history
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Max versions to return (default: all) |
Workspaces
Organize agents into workspaces (folders). Every user has at least one default workspace.List workspaces
GET /v1/workspaces
GET /v1/workspaces
Create a workspace
POST /v1/workspaces
POST /v1/workspaces
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workspace name |
201 CreatedUpdate a workspace
PUT /v1/workspaces/{workspace_id}
PUT /v1/workspaces/{workspace_id}
| Field | Type | Required | Description |
|---|---|---|---|
workspace_id | string | Yes | The workspace ID |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | New workspace name |
icon_config | string | No | Icon configuration string |
Delete a workspace
DELETE /v1/workspaces/{workspace_id}
DELETE /v1/workspaces/{workspace_id}
| Field | Type | Required | Description |
|---|---|---|---|
workspace_id | string | Yes | The workspace ID |
Reorder workspaces
POST /v1/workspaces/reorder
POST /v1/workspaces/reorder
| Field | Type | Required | Description |
|---|---|---|---|
workspace_ids | string[] | Yes | Workspace IDs in the desired order |
Move agent to workspace
POST /v1/agents/{agent_id}/move
POST /v1/agents/{agent_id}/move
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
| Field | Type | Required | Description |
|---|---|---|---|
workspace_id | string | Yes | Target workspace ID |
Quick Reference
| Action | Method | Endpoint |
|---|---|---|
| List API keys | GET | /api/public/v1/access-api-keys |
| Create API key | POST | /api/public/v1/access-api-keys |
| Revoke API key | DELETE | /api/public/v1/access-api-keys/{key_id} |
| Get current user | GET | /v1/me |
| List agents | GET | /v1/agents |
| Create agent | POST | /v1/agents |
| Get agent | GET | /v1/agents/{agent_id} |
| Delete agent | DELETE | /v1/agents/{agent_id} |
| List runs | GET | /v1/agents/{agent_id}/runs |
| Start run | POST | /v1/agents/{agent_id}/runs |
| Delete run | DELETE | /v1/agents/{agent_id}/runs/{run_id} |
| Cancel run | POST | /v1/agents/{agent_id}/runs/{run_id}/cancel |
| List run events | GET | /v1/agents/{agent_id}/runs/{run_id}/events |
| Create webhook | POST | /v1/agents/{agent_id}/webhooks |
| List webhooks | GET | /v1/agents/{agent_id}/webhooks |
| Get webhook | GET | /v1/agents/{agent_id}/webhooks/{webhook_id} |
| Update webhook | PATCH | /v1/agents/{agent_id}/webhooks/{webhook_id} |
| Delete webhook | DELETE | /v1/agents/{agent_id}/webhooks/{webhook_id} |
| Get schedule | GET | /v1/agents/{agent_id}/schedule |
| Set schedule | PUT | /v1/agents/{agent_id}/schedule |
| Delete schedule | DELETE | /v1/agents/{agent_id}/schedule |
| Pause schedule | POST | /v1/agents/{agent_id}/schedule/pause |
| Resume schedule | POST | /v1/agents/{agent_id}/schedule/resume |
| List all schedules | GET | /v1/schedules |
| Get instructions | GET | /v1/agents/{agent_id}/instructions |
| Update instructions | PUT | /v1/agents/{agent_id}/instructions |
| Instructions history | GET | /v1/agents/{agent_id}/instructions/history |
| List workspaces | GET | /v1/workspaces |
| Create workspace | POST | /v1/workspaces |
| Update workspace | PUT | /v1/workspaces/{workspace_id} |
| Delete workspace | DELETE | /v1/workspaces/{workspace_id} |
| Reorder workspaces | POST | /v1/workspaces/reorder |
| Move agent | POST | /v1/agents/{agent_id}/move |
/v1 with standard HTTP methods.