Base URL
Authentication
Use one of these headers on every request:Error Handling
Error responses use this shape:code maps to gRPC status names (for example: NOT_FOUND, UNAUTHENTICATED, FAILED_PRECONDITION).
API Keys
API key management endpoints currently use the/api/public/v1 path family.
List API keys
GET /api/public/v1/access-api-keys
GET /api/public/v1/access-api-keys
Returns all API keys for the authenticated user.ExampleResponse
Create an API key
POST /api/public/v1/access-api-keys
POST /api/public/v1/access-api-keys
Creates a new API key. The full key is only returned once, so store it securely.Request body
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Optional name for the key |
Revoke an API key
DELETE /api/public/v1/access-api-keys/{keyId}
DELETE /api/public/v1/access-api-keys/{keyId}
Permanently revokes an API key. Requests using it stop working immediately.Path parameters
Example
| Field | Type | Required | Description |
|---|---|---|---|
keyId | string | Yes | ID of the key to revoke |
Identity
Get current user
GET /v1/me
GET /v1/me
Returns the authenticated user ID.ExampleResponse
Agents
Versioned agent endpoints live under/v1/agents.
List agents
GET /v1/agents
GET /v1/agents
Returns agents for the authenticated user, with optional pagination and project filtering.Query parameters
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
project_id | string | No | Filter to a specific project |
cursor | string | No | Cursor for pagination |
limit | integer | No | Max results to return |
Create an agent
POST /v1/agents
POST /v1/agents
Creates a new agent and returns its ID.Request body
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
project_id | string | No | Project 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 |
Get an agent
GET /v1/agents/{agent_id}
GET /v1/agents/{agent_id}
Returns full details for a specific agent.Path parameters
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Delete an agent
DELETE /v1/agents/{agent_id}
DELETE /v1/agents/{agent_id}
Permanently deletes an agent and its run data.Path parameters
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
Runs
Trigger, list, and delete runs under each agent.List runs
GET /v1/agents/{agent_id}/runs
GET /v1/agents/{agent_id}/runs
Returns run history for an agent.Path parameters
Query parameters
ExampleResponse fields
Run object
Run summary object (
Example
| 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 | Filter by exact policy type (e.g. runner_v2, builder_v3) |
filter_policy_group | string | No | Filter by policy group: builder or runner. Mutually exclusive with filter_policy_type. |
| Field | Type | Description |
|---|---|---|
runs | array | Paginated list of run objects for the requested page |
total_runs | string | Total number of matching runs (respects all filters) |
page | integer | Current page number |
page_size | integer | Number of results per page |
all_run_summaries | array | Lightweight summaries for up to 2 000 matching runs (for UI use) |
| Field | Type | Description |
|---|---|---|
run_id | string | Unique run identifier |
agent_id | string | Parent agent identifier |
user_id | string | User who owns the agent |
user_email | string | Email of the owning user |
started_at | string | ISO-8601 run start time |
last_event_at | string | ISO-8601 timestamp of last event |
event_count | string | Number of events in the run |
event_bytes | string | Total event payload size in bytes |
run_number | integer | 1-based position within the result set |
is_finished | boolean | Whether the run has completed |
is_paused | boolean | Whether the run is paused |
status | string | Current run status |
goal | string | Agent goal at time of run |
summary | string | Run summary (if available) |
outcome | string | Run outcome (if available) |
policy_type | string | Policy type used for the run |
policy_model | string | Model used by the policy |
webhook_subscription_id | string | Webhook subscription that triggered run |
schedule_agent_id | string | Schedule that triggered run |
all_run_summaries)| Field | Type | Description |
|---|---|---|
run_id | string | Unique run identifier |
run_number | integer | 1-based position within the result set |
started_at | string | ISO-8601 run start time |
is_finished | boolean | Whether the run has completed |
is_paused | boolean | Whether the run is paused |
summary | string | Run summary (if available) |
outcome | string | Run outcome (if available) |
policy_type | string | Policy type used for the run |
policy_model | string | Model used by the policy |
credits_consumed | integer | Credits consumed by the run |
webhook_subscription_id | string | Webhook subscription that triggered run |
schedule_agent_id | string | Schedule that triggered run |
tool_icons | array | Tool icons used during the run |
total_action_count | integer | Number of tool actions in the run |
all_run_summaries returns at most 2 000 entries. For agents with more runs,
rely on total_runs and paginate through runs using page / page_size.Start a run
POST /v1/agents/{agent_id}/runs
POST /v1/agents/{agent_id}/runs
Starts a run for an existing agent.Path parameters
Request body
ExampleResponse
| 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 |
Delete a run
DELETE /v1/agents/{agent_id}/runs/{run_id}
DELETE /v1/agents/{agent_id}/runs/{run_id}
Deletes a run for a specific agent.Path parameters
ExampleResponse
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | The agent ID |
run_id | string | Yes | The run ID |
Events
List run events
GET /v1/agents/{agent_id}/runs/{run_id}/events
GET /v1/agents/{agent_id}/runs/{run_id}/events
Returns events for a specific run.Path parameters
Query parameters
ExampleResponse
| 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
Registers a webhook URL for the given agent. The signing secret is returned only once in the response — store it immediately.Path parameters
Request body
ExampleResponse
| 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
Returns all webhooks registered for the given agent.Path parameters
ExampleResponse
| 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}
Returns details for a specific webhook.Path parameters
ExampleResponse
| 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}
Updates a webhook’s URL, subscribed events, or status. All fields are optional — only provided fields are changed.Path parameters
Request body
ExampleResponse
| 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}
Permanently deletes a webhook. No further events will be delivered.Path parameters
ExampleResponse
| 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)
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/{keyId} |
| 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} |
| 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} |
Agent, run, and event APIs are now versioned REST endpoints under
/v1 with standard HTTP methods.Get your API key
Sign in to Twin to generate your API key and start building.
