> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twin.so/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API

> Integrate Twin programmatically using the REST API

Twin exposes a REST API that lets you create agents, trigger runs, inspect events, and manage API keys programmatically.

## Base URL

```
https://build.twin.so
```

## OpenAPI Specification

A machine-readable OpenAPI 3.1 schema is available at:

```
https://build.twin.so/openapi.json
```

You can use this spec to generate client libraries, import into tools like Postman or Insomnia, or explore the API interactively in the docs playground above.

## Authentication

Use the following header on every request:

```bash theme={null}
x-api-key: YOUR_API_KEY
```

Generate an API key from your [Twin account](https://builder.twin.so) or via the API itself (see below).

## Error Handling

Error responses follow RFC 9457 Problem Details and return `Content-Type: application/problem+json`.

```json theme={null}
{
  "type": "about:blank",
  "title": "Not Found",
  "status": 404,
  "detail": "Description of what went wrong"
}
```

* `type` is a URI identifying the problem type (`about:blank` means no extra semantics beyond the HTTP status).
* `status` is the HTTP status code.
* `title` is the standard HTTP reason phrase.
* `detail` is a human-readable error message.

<Warning>If you are migrating from the previous `error.code` / `error.message` format, update your error parsing logic.</Warning>

***

## 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

<Accordion title="GET /api/public/v1/access-api-keys" icon="list" color="#F4D03F">
  Returns all API keys for the authenticated user.

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/api/public/v1/access-api-keys \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "keys": [
      {
        "key_id": "abc123",
        "name": "my-integration",
        "display_prefix": "tw_live_abc...",
        "created_at": 1706000000,
        "last_used_at": 1706100000
      }
    ]
  }
  ```
</Accordion>

### Create an API key

<Accordion title="POST /api/public/v1/access-api-keys" icon="plus" color="#F4D03F">
  Creates a new API key. The full key is only returned once, so store it securely.

  **Request body**

  | Field  | Type   | Required | Description                 |
  | ------ | ------ | -------- | --------------------------- |
  | `name` | string | Yes      | Key name (1-128 characters) |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/api/public/v1/access-api-keys \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "my-integration"}'
  ```

  **Response**

  ```json theme={null}
  {
    "key_id": "abc123",
    "name": "my-integration",
    "api_key": "tw_live_...",
    "display_prefix": "tw_live_abc...",
    "created_at": 1706000000
  }
  ```

  <Warning>The `api_key` field is only returned at creation time. Store it immediately.</Warning>
</Accordion>

### Revoke an API key

<Accordion title="DELETE /api/public/v1/access-api-keys/{key_id}" icon="trash" color="#F4D03F">
  Permanently revokes an API key. Requests using it stop working immediately.

  **Path parameters**

  | Field    | Type   | Required | Description             |
  | -------- | ------ | -------- | ----------------------- |
  | `key_id` | string | Yes      | ID of the key to revoke |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/api/public/v1/access-api-keys/abc123 \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "revoked": true
  }
  ```
</Accordion>

***

## Identity

### Get current user

<Accordion title="GET /v1/me" icon="user" color="#F4D03F">
  Returns the authenticated user ID.

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/me \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "user_id": "user_123"
  }
  ```
</Accordion>

***

## Agents

Versioned agent endpoints live under `/v1/agents`.

### List agents

<Accordion title="GET /v1/agents" icon="list" color="#F4D03F">
  Returns agents for the authenticated user, with optional pagination and workspace filtering.

  **Query parameters**

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

  **Example**

  ```bash theme={null}
  curl "https://build.twin.so/v1/agents?limit=20" \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "agents": [
      {
        "agent_id": "agent_abc123",
        "latest_run_id": "run_xyz789",
        "latest_run_is_finished": true,
        "has_runs": true,
        "deployment_state": "deployed"
      }
    ]
  }
  ```
</Accordion>

### Create an agent

<Accordion title="POST /v1/agents" icon="plus" color="#F4D03F">
  Creates a new agent and returns the full agent object.

  **Request body**

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

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"workspace_id": "proj_001"}'
  ```

  **Response** `201 Created`

  ```json theme={null}
  {
    "agent": {
      "agent_id": "agent_abc123",
      "latest_run_id": "",
      "latest_run_is_finished": false,
      "has_runs": false,
      "workspace_id": "proj_001",
      "deployment_state": "not_deployed"
    }
  }
  ```
</Accordion>

### Get an agent

<Accordion title="GET /v1/agents/{agent_id}" icon="eye" color="#F4D03F">
  Returns full details for a specific agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/agents/agent_abc123 \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "agent": {
      "agent_id": "agent_abc123",
      "latest_run_id": "run_xyz789",
      "last_activity_at": "2026-02-20T14:30:00Z",
      "latest_run_is_finished": true,
      "has_runs": true,
      "workspace_id": "proj_001",
      "deployment_state": "deployed",
      "deployed_at": "2026-02-18T10:00:00Z"
    }
  }
  ```
</Accordion>

### Delete an agent

<Accordion title="DELETE /v1/agents/{agent_id}" icon="trash" color="#F4D03F">
  Permanently deletes an agent and its run data.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/v1/agents/agent_abc123 \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response** `204 No Content` — empty body on success. Returns `404` if the agent was not found.
</Accordion>

***

## Runs

Trigger, list, cancel, and delete runs under each agent.

### List runs

<Accordion title="GET /v1/agents/{agent_id}/runs" icon="list" color="#F4D03F">
  Returns run history for an agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Query parameters**

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

  **Example**

  ```bash theme={null}
  curl "https://build.twin.so/v1/agents/agent_abc123/runs?page=1&page_size=10&filter_status=finished" \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "runs": [
      {
        "run_id": "run_xyz789",
        "agent_id": "agent_abc123",
        "status": "finished",
        "started_at": "2026-02-20T14:30:00Z",
        "finished_at": "2026-02-20T14:32:15Z"
      }
    ],
    "total_runs": "42",
    "page": 1,
    "page_size": 10
  }
  ```
</Accordion>

### Start a run

<Accordion title="POST /v1/agents/{agent_id}/runs" icon="play" color="#F4D03F">
  Starts a run for an existing agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Request body**

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

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/runs \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"run_mode": "run", "user_message": "Please execute the latest workflow."}'
  ```

  **Response** `201 Created`

  ```json theme={null}
  {
    "run": {
      "run_id": "run_xyz789",
      "agent_id": "agent_abc123",
      "status": "in_progress",
      "started_at": "2026-02-20T14:30:00Z",
      "is_finished": false,
      "is_paused": false,
      "run_number": 1,
      "policy_type": "runner_v2"
    }
  }
  ```
</Accordion>

### Delete a run

<Accordion title="DELETE /v1/agents/{agent_id}/runs/{run_id}" icon="trash" color="#F4D03F">
  Deletes a run for a specific agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |
  | `run_id`   | string | Yes      | The run ID   |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/v1/agents/agent_abc123/runs/run_xyz789 \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response** `204 No Content` — empty body on success. Returns `404` if the run was not found.
</Accordion>

### Cancel a run

<Accordion title="POST /v1/agents/{agent_id}/runs/{run_id}/cancel" icon="stop" color="#F4D03F">
  Cancels a running run. The request is idempotent — cancelling an already-finished run returns success.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |
  | `run_id`   | string | Yes      | The run ID   |

  **Request body** (optional)

  | Field    | Type   | Required | Description                        |
  | -------- | ------ | -------- | ---------------------------------- |
  | `reason` | string | No       | Human-readable cancellation reason |

  The body is entirely optional — you may send an empty object `{}` or omit the body altogether.

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/runs/run_xyz789/cancel \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"reason": "User requested cancellation"}'
  ```

  **Response**

  ```json theme={null}
  {
    "error": ""
  }
  ```

  An empty `error` means success. A non-empty value is informational (e.g. the run was already stopped).
</Accordion>

***

## Events

### List run events

<Accordion title="GET /v1/agents/{agent_id}/runs/{run_id}/events" icon="list" color="#F4D03F">
  Returns events for a specific run.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |
  | `run_id`   | string | Yes      | The run ID   |

  **Query parameters**

  | Field         | Type    | Required | Description                          |
  | ------------- | ------- | -------- | ------------------------------------ |
  | `limit`       | integer | No       | Max events to return                 |
  | `after_index` | integer | No       | Return events after this event index |

  **Example**

  ```bash theme={null}
  curl "https://build.twin.so/v1/agents/agent_abc123/runs/run_xyz789/events?limit=50" \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "events": [
      {
        "index": 1,
        "event": {
          "started": {}
        }
      }
    ]
  }
  ```
</Accordion>

***

## 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

<Accordion title="POST /v1/agents/{agent_id}/webhooks" icon="plus" color="#F4D03F">
  Registers a webhook URL for the given agent. The signing secret is returned **only once** in the response — store it immediately.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Request body**

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

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/webhooks \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com/webhooks/twin",
      "events": ["run.completed", "run.failed"]
    }'
  ```

  **Response** `201 Created`

  ```json theme={null}
  {
    "webhook_id": "01234567-89ab-cdef-0123-456789abcdef",
    "url": "https://example.com/webhooks/twin",
    "events": ["run.completed", "run.failed"],
    "signing_secret": "whsec_a1b2c3d4e5f6...",
    "status": "active",
    "created_at": "2026-03-11T12:00:00Z"
  }
  ```

  <Warning>The `signing_secret` is only returned at creation time. Store it securely — you need it to verify incoming webhook signatures.</Warning>
</Accordion>

### List webhooks

<Accordion title="GET /v1/agents/{agent_id}/webhooks" icon="list" color="#F4D03F">
  Returns all webhooks registered for the given agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/agents/agent_abc123/webhooks \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "webhooks": [
      {
        "webhook_id": "01234567-89ab-cdef-0123-456789abcdef",
        "agent_id": "agent_abc123",
        "user_id": "user_123",
        "url": "https://example.com/webhooks/twin",
        "events": ["run.completed", "run.failed"],
        "status": "active",
        "created_at": "2026-03-11T12:00:00Z",
        "updated_at": "2026-03-11T12:00:00Z"
      }
    ]
  }
  ```
</Accordion>

### Get a webhook

<Accordion title="GET /v1/agents/{agent_id}/webhooks/{webhook_id}" icon="eye" color="#F4D03F">
  Returns details for a specific webhook.

  **Path parameters**

  | Field        | Type   | Required | Description    |
  | ------------ | ------ | -------- | -------------- |
  | `agent_id`   | string | Yes      | The agent ID   |
  | `webhook_id` | string | Yes      | The webhook ID |

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/agents/agent_abc123/webhooks/01234567-89ab-cdef-0123-456789abcdef \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "webhook_id": "01234567-89ab-cdef-0123-456789abcdef",
    "agent_id": "agent_abc123",
    "user_id": "user_123",
    "url": "https://example.com/webhooks/twin",
    "events": ["run.completed", "run.failed"],
    "status": "active",
    "created_at": "2026-03-11T12:00:00Z",
    "updated_at": "2026-03-11T12:00:00Z"
  }
  ```
</Accordion>

### Update a webhook

<Accordion title="PATCH /v1/agents/{agent_id}/webhooks/{webhook_id}" icon="pen" color="#F4D03F">
  Updates a webhook's URL, subscribed events, or status. All fields are optional — only provided fields are changed.

  **Path parameters**

  | Field        | Type   | Required | Description    |
  | ------------ | ------ | -------- | -------------- |
  | `agent_id`   | string | Yes      | The agent ID   |
  | `webhook_id` | string | Yes      | The webhook ID |

  **Request body**

  | Field    | Type      | Required | Description                |
  | -------- | --------- | -------- | -------------------------- |
  | `url`    | string    | No       | New endpoint URL           |
  | `events` | string\[] | No       | New set of event types     |
  | `status` | string    | No       | `"active"` or `"disabled"` |

  **Example**

  ```bash theme={null}
  curl -X PATCH https://build.twin.so/v1/agents/agent_abc123/webhooks/01234567-89ab-cdef-0123-456789abcdef \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"status": "disabled"}'
  ```

  **Response**

  ```json theme={null}
  {
    "webhook_id": "01234567-89ab-cdef-0123-456789abcdef",
    "agent_id": "agent_abc123",
    "user_id": "user_123",
    "url": "https://example.com/webhooks/twin",
    "events": ["run.completed", "run.failed"],
    "status": "disabled",
    "created_at": "2026-03-11T12:00:00Z",
    "updated_at": "2026-03-11T13:00:00Z"
  }
  ```
</Accordion>

### Delete a webhook

<Accordion title="DELETE /v1/agents/{agent_id}/webhooks/{webhook_id}" icon="trash" color="#F4D03F">
  Permanently deletes a webhook. No further events will be delivered.

  **Path parameters**

  | Field        | Type   | Required | Description    |
  | ------------ | ------ | -------- | -------------- |
  | `agent_id`   | string | Yes      | The agent ID   |
  | `webhook_id` | string | Yes      | The webhook ID |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/v1/agents/agent_abc123/webhooks/01234567-89ab-cdef-0123-456789abcdef \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response** `204 No Content`
</Accordion>

### Webhook payload

When a subscribed event fires, Twin sends an HTTP POST to your webhook URL with a JSON body:

```json theme={null}
{
  "event": "run.completed",
  "timestamp": "2026-03-11T14:32:15Z",
  "data": {
    "run_id": "run_xyz789",
    "agent_id": "agent_abc123",
    "status": "completed",
    "outcome": "success",
    "finished_at": "2026-03-11T14:32:15Z"
  }
}
```

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

To verify authenticity, compute `HMAC-SHA256(signing_secret, raw_request_body)` and compare it to the signature in the header.

**Example (Node.js)**

```javascript theme={null}
const crypto = require("crypto");

function verifyWebhookSignature(secret, body, signatureHeader) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}
```

***

## Schedules

Manage cron-based schedules for agents. Each agent can have at most one schedule.

### Get agent schedule

<Accordion title="GET /v1/agents/{agent_id}/schedule" icon="eye" color="#F4D03F">
  Returns the current schedule for an agent, if one exists.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/agents/agent_abc123/schedule \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "schedule": {
      "cron": "0 0 9 * * * *",
      "paused": false
    }
  }
  ```

  <Note>Returns `{"schedule": null}` if no schedule is set.</Note>
</Accordion>

### Set agent schedule

<Accordion title="PUT /v1/agents/{agent_id}/schedule" icon="clock" color="#F4D03F">
  Creates or replaces the cron schedule for an agent. The agent must be deployed.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Request body**

  | Field  | Type   | Required | Description                      |
  | ------ | ------ | -------- | -------------------------------- |
  | `cron` | string | Yes      | Cron expression (7-field format) |

  **Example**

  ```bash theme={null}
  curl -X PUT https://build.twin.so/v1/agents/agent_abc123/schedule \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"cron": "0 0 9 * * * *"}'
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```

  <Note>Twin uses 7-field cron expressions: `sec min hour day month day-of-week year`.</Note>
</Accordion>

### Delete agent schedule

<Accordion title="DELETE /v1/agents/{agent_id}/schedule" icon="trash" color="#F4D03F">
  Removes the schedule from an agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/v1/agents/agent_abc123/schedule \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

### Pause schedule

<Accordion title="POST /v1/agents/{agent_id}/schedule/pause" icon="pause" color="#F4D03F">
  Pauses the agent's schedule. The schedule is retained but will not trigger runs until resumed.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/schedule/pause \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

### Resume schedule

<Accordion title="POST /v1/agents/{agent_id}/schedule/resume" icon="play" color="#F4D03F">
  Resumes a paused schedule.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/schedule/resume \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

### List all schedules

<Accordion title="GET /v1/schedules" icon="list" color="#F4D03F">
  Returns all schedules for the authenticated user across all agents.

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/schedules \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "schedules": [
      {
        "agent_id": "agent_abc123",
        "cron": "0 0 9 * * * *",
        "paused": false
      }
    ]
  }
  ```
</Accordion>

***

## Instructions

Read and update the auto-generated instructions for an agent, with version history.

### Get instructions

<Accordion title="GET /v1/agents/{agent_id}/instructions" icon="eye" color="#F4D03F">
  Returns the current instructions for an agent.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/agents/agent_abc123/instructions \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "instructions": {
      "content": "Check email every morning and summarize unread messages."
    }
  }
  ```
</Accordion>

### Update instructions

<Accordion title="PUT /v1/agents/{agent_id}/instructions" icon="pen" color="#F4D03F">
  Replaces the agent's instructions. Each update creates a new version in the history.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Request body**

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

  **Example**

  ```bash theme={null}
  curl -X PUT https://build.twin.so/v1/agents/agent_abc123/instructions \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"content": "Check email and Slack every morning."}'
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

### Get instructions history

<Accordion title="GET /v1/agents/{agent_id}/instructions/history" icon="clock-rotate-left" color="#F4D03F">
  Returns previous versions of the agent's instructions.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Query parameters**

  | Field   | Type    | Required | Description                           |
  | ------- | ------- | -------- | ------------------------------------- |
  | `limit` | integer | No       | Max versions to return (default: all) |

  **Example**

  ```bash theme={null}
  curl "https://build.twin.so/v1/agents/agent_abc123/instructions/history?limit=10" \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "instruction_versions": [
      {
        "content": "Check email and Slack every morning.",
        "created_at": "2026-03-11T15:00:00Z"
      },
      {
        "content": "Check email every morning and summarize unread messages.",
        "created_at": "2026-03-11T14:00:00Z"
      }
    ]
  }
  ```
</Accordion>

***

## Workspaces

Organize agents into workspaces (folders). Every user has at least one default workspace.

### List workspaces

<Accordion title="GET /v1/workspaces" icon="list" color="#F4D03F">
  Returns all workspaces for the authenticated user.

  **Example**

  ```bash theme={null}
  curl https://build.twin.so/v1/workspaces \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "workspaces": [
      {
        "workspace_id": "ws_001",
        "name": "My Workspace"
      }
    ]
  }
  ```
</Accordion>

### Create a workspace

<Accordion title="POST /v1/workspaces" icon="plus" color="#F4D03F">
  Creates a new workspace.

  **Request body**

  | Field  | Type   | Required | Description    |
  | ------ | ------ | -------- | -------------- |
  | `name` | string | Yes      | Workspace name |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/workspaces \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "Marketing Agents"}'
  ```

  **Response** `201 Created`

  ```json theme={null}
  {
    "workspace": {
      "workspace_id": "ws_002",
      "name": "Marketing Agents"
    }
  }
  ```
</Accordion>

### Update a workspace

<Accordion title="PUT /v1/workspaces/{workspace_id}" icon="pen" color="#F4D03F">
  Updates a workspace's name or icon.

  **Path parameters**

  | Field          | Type   | Required | Description      |
  | -------------- | ------ | -------- | ---------------- |
  | `workspace_id` | string | Yes      | The workspace ID |

  **Request body**

  | Field         | Type   | Required | Description               |
  | ------------- | ------ | -------- | ------------------------- |
  | `name`        | string | Yes      | New workspace name        |
  | `icon_config` | string | No       | Icon configuration string |

  **Example**

  ```bash theme={null}
  curl -X PUT https://build.twin.so/v1/workspaces/proj_002 \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "Renamed Workspace"}'
  ```

  **Response**

  ```json theme={null}
  {
    "workspace": {
      "workspace_id": "ws_002",
      "name": "Renamed Workspace"
    }
  }
  ```
</Accordion>

### Delete a workspace

<Accordion title="DELETE /v1/workspaces/{workspace_id}" icon="trash" color="#F4D03F">
  Deletes a workspace and all agents inside it.

  **Path parameters**

  | Field          | Type   | Required | Description      |
  | -------------- | ------ | -------- | ---------------- |
  | `workspace_id` | string | Yes      | The workspace ID |

  **Example**

  ```bash theme={null}
  curl -X DELETE https://build.twin.so/v1/workspaces/proj_002 \
    -H "x-api-key: YOUR_API_KEY"
  ```

  **Response**

  ```json theme={null}
  {
    "deleted": true
  }
  ```

  <Warning>This permanently deletes the workspace and all agents within it.</Warning>
</Accordion>

### Reorder workspaces

<Accordion title="POST /v1/workspaces/reorder" icon="arrows-up-down" color="#F4D03F">
  Sets the display order of workspaces.

  **Request body**

  | Field           | Type      | Required | Description                        |
  | --------------- | --------- | -------- | ---------------------------------- |
  | `workspace_ids` | string\[] | Yes      | Workspace IDs in the desired order |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/workspaces/reorder \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"workspace_ids": ["proj_002", "proj_001"]}'
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

### Move agent to workspace

<Accordion title="POST /v1/agents/{agent_id}/move" icon="arrow-right" color="#F4D03F">
  Moves an agent from its current workspace to a different one.

  **Path parameters**

  | Field      | Type   | Required | Description  |
  | ---------- | ------ | -------- | ------------ |
  | `agent_id` | string | Yes      | The agent ID |

  **Request body**

  | Field          | Type   | Required | Description         |
  | -------------- | ------ | -------- | ------------------- |
  | `workspace_id` | string | Yes      | Target workspace ID |

  **Example**

  ```bash theme={null}
  curl -X POST https://build.twin.so/v1/agents/agent_abc123/move \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"workspace_id": "proj_002"}'
  ```

  **Response**

  ```json theme={null}
  {
    "success": true
  }
  ```
</Accordion>

***

## 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`                  |

<Note>
  Agent, run, and event APIs are now versioned REST endpoints under `/v1` with standard HTTP methods.
</Note>

<Card title="Get your API key" icon="key" href="https://builder.twin.so/" color="#F4D03F">
  Sign in to Twin to generate your API key and start building.
</Card>
