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

# Replica API

> Programmatically create and manage replicas.

The Replica API lets you programmatically create workspaces, send messages to coding agents, manage chats, and monitor workspace state.

<Note>
  The Replica API and [Automations](/features/automations) are the **only** sanctioned channels for programmatic use of Replicas. Scripting against the dashboard, automating the CLI, or driving interactive surfaces from headless browsers is prohibited under our [Terms of Service](https://tryreplicas.com/terms).
</Note>

## Authentication

Organization admins can generate org API keys from [Organization → Settings → API Keys](https://tryreplicas.com/dashboard/settings?tab=api-keys). You can generate personal API keys from [Personal → API Keys](https://tryreplicas.com/dashboard/account/api-keys).

Include it as a Bearer token in requests:

```bash theme={null}
curl -X GET "https://api.tryreplicas.com/v1/replica" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The API key identifies your organization automatically - no additional headers are needed. Organization API keys can manage org resources. Personal API keys can manage org automations and personal automations owned by that user.

### Org vs Personal API Keys

|                                 | Org API Key                | Personal API Key                                 |
| ------------------------------- | -------------------------- | ------------------------------------------------ |
| Created by                      | Org admins                 | Any member                                       |
| Workspace attribution           | Replicas bot (no user)     | Owning user                                      |
| Can manage org automations      | Yes                        | Yes                                              |
| Can manage personal automations | No                         | Own automations only                             |
| Use case                        | CI/CD, shared integrations | Personal automations, user-attributed workspaces |

User-session JWTs are not accepted by `/v1/replica` endpoints. Use an organization or personal API key.

Each organization can have up to 100 API and Automation workspaces running or preparing at once.

## Quick Start

### 1. List Available Repositories

Before creating a replica, list the repositories available in your organization:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/repositories" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### 2. Create a Replica

The `name` field must not contain whitespace (e.g. `fix-auth-bug`, not `fix auth bug`).

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "fix-auth-bug",
    "environment_id": "ENVIRONMENT_UUID",
    "message": "Fix the login timeout issue in src/auth.ts",
    "coding_agent": "claude",
    "model": "claude-sonnet-5"
  }'
```

The selected environment determines which repository or repository set is checked out, and which variables, files, skills, MCPs, hooks, warm pool, and system prompt apply.

Optional `coding_agent` chooses the agent for the initial message. Valid values are `claude`, `codex`, `cursor`, `opencode`, and `pi`. Cursor requires a Cursor API key in [Organization → Coding Agents](https://tryreplicas.com/dashboard/agents); Opencode supports OpenCode Go, Aster, or OpenRouter, while Pi supports the shared Aster or OpenRouter key.

When Opencode or Pi runs on OpenRouter, `model` must be one an organization admin enabled in [Coding Agents settings](https://tryreplicas.com/dashboard/agents). Requests for any other model are rejected, including messages sent to an existing workspace. Call `GET /v1/openrouter/models` to list the enabled models.

Optional `lifecycle_policy` controls what happens when work is done:

* `default` - workspace sleeps after inactivity, archives after 7 days asleep, and is deleted after 30 days dormant (default)
* `archive_when_done` - workspace is archived when the agent finishes
* `sleep_when_done` - workspace sleeps when the agent finishes, keeping history available
* `delete_after_inactivity` - workspace is deleted after a period of inactivity. Not available to [automations](/features/automations), whose workspaces archive instead so each run stays inspectable

Optional `size` picks the compute envelope and per-minute price for this replica:

| `size`  | Compute                          | Price         |
| ------- | -------------------------------- | ------------- |
| `small` | 2 vCPU, 8 GB memory, 20 GB disk  | \$0.008 / min |
| `large` | 4 vCPU, 16 GB memory, 32 GB disk | \$0.016 / min |

Omit `size` to default to `small`, the lower per-minute price, best for cheap, frequent jobs; pick `large` for memory or CPU-bound work. Mixed fleets bill correctly; each workspace charges at its own rate.

Optional `config` controls per-workspace behavior. API-created replicas default to `capabilities.pr_followups: true`, meaning Replicas will auto-reply to CI failures and allowed review bots on matching PRs created or touched by that workspace; human PR reviews still require a mention unless enabled in [GitHub settings](/features/github#human-pr-review-auto-response). Set it to `false` to stop those follow-ups; it controls PR routing only and never affects whether the replica can push. To stop a replica from committing or pushing, set `capabilities.read_only_contents: true`, which leaves it able to comment on pull requests, open issues, and report checks. Set `preferences.keep_open_on_pr_merge: true` when that workspace should remain open after its tracked PR merges, or `preferences.keep_open_on_pr_close: true` when it should remain open after its tracked PR is closed without merging. See [Automations: Pull request management](/features/automations#pull-request-management) for how the `pr_followups` default flips for automation-created workspaces.

The replica boots asynchronously and the message is delivered once ready.

### 3. Send a Follow-up Message

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Also add tests for the fix"
  }'
```

If the replica is sleeping or archived, it wakes automatically. Messages queue if the agent is busy.

The workspace chat endpoints also accept chats and messages while a workspace is preparing or sleeping. Pending chats stay visible, and messages are delivered in order after startup completes. Sending a message to an archived workspace queues it and wakes the workspace.

### 4. Check Status

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}?include=environment" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `include=environment` to get detailed environment info, or `include=diffs` for full git diffs.

The status response also includes `lastChatMessage`, a preview of the most recent input message across the workspace's chats (its `text`, the agent that received it (`claude`, `codex`, `cursor`, `opencode`, or `pi`), and a timestamp), so you can surface recent activity without fetching full chat history. Each chat object likewise exposes `lastMessageText`, the preview for that individual chat.

To list dashboard workspaces with their repository and pull request metadata, use `GET /v1/workspaces`. The paginated response includes `workspaces`, `workspace_repositories`, `workspace_pull_requests`, and `workspace_turn_completed_at`, which maps workspace IDs to their latest completed turn timestamps. Each `workspace_pull_requests` item contains a `workspace_id`, its pull request `url` when available, and a `status` of `open`, `merged`, or `closed`.

```bash theme={null}
curl "https://api.tryreplicas.com/v1/workspaces?page=1&limit=100" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `GET /v1/presence` to list which organization members are currently active. The response is `{ "presence": [...] }`, where each entry has a `userId`, a `status` of `online` or `typing`, an optional `location` (`environmentId` and/or `workspaceId`), and a `ts` timestamp.

```bash theme={null}
curl "https://api.tryreplicas.com/v1/presence" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `GET /v1/organization/default-agent` to resolve the authenticated user's saved harness and a compatible model after organization defaults and credential availability are applied. The response includes `default_agent` and nullable `default_model`.

Report your own activity with `POST /v1/presence`, sending `{ "status": "online" | "typing", "location"?: { "environmentId"?: "...", "workspaceId"?: "..." } }`. Presence entries expire automatically, so send periodic updates while active. Streaming `GET /v1/workspaces/events` also delivers a `presence.changed` event whenever any member's presence changes, so you can refresh without polling.

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/presence" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "typing", "location": {"workspaceId": "..."}}'
```

### 5. Archive a Workspace

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/archive" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Archived workspaces stay paused, stop compute charges, and can be woken later by opening them or sending a message.

To pause a workspace without archiving it, force it to sleep:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/sleep" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Only active workspaces can be slept; the request is a no-op for already-sleeping or archived workspaces and returns **409** for `preparing` or `error` workspaces. Like archived workspaces, slept workspaces stop compute charges and can be woken later.

### 6. Use a Workspace Terminal

Active workspaces created with a terminal-capable engine expose terminal sessions through the workspace API. Older workspaces return `404` because engine updates are not retroactive.

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/terminal/sessions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "cols": 100, "rows": 30 }'
```

Use the returned session ID to send input, resize, stream output over SSE, or delete the session. Each workspace supports up to eight simultaneous terminal sessions. See the endpoint reference below for request schemas.

Terminal input batches require a client generation and a zero-based sequence number so concurrent requests are applied in order. Start at sequence `0`, increment it for each batch, and use a greater generation with sequence `0` to reset ordering after a failed request.

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/terminal/sessions/{sessionId}/input" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "data": "ls\n", "generation": 1, "sequence": 0 }'
```

### 7. List Mobile Testing Instances

List active iOS simulators and Android emulators associated with a workspace:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/mobile-testing/instances" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The response includes `enabled` and an `instances` array. Stream URLs and tokens are short-lived credentials; keep them scoped to the requested organization and workspace.

### 8. Delete a Replica

```bash theme={null}
curl -X DELETE "https://api.tryreplicas.com/v1/replica/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Deleting a replica is idempotent for replicas in your organization: if the replica was already deleted, the API still returns `200 OK` with `{ "success": true }`. IDs that never existed or belong to another organization return `404`.

### 9. Stream Events (SSE)

```bash theme={null}
curl -N "https://api.tryreplicas.com/v1/replica/{id}/events" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: text/event-stream"
```

Receive real-time updates including chat turns, repository changes, and hook progress.

### 10. Webhook Callbacks (alternative to polling)

Pass `webhook_url` when creating a replica to receive status updates without polling:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "fix-auth-bug",
    "environment_id": "ENVIRONMENT_UUID",
    "message": "Fix the login timeout issue",
    "webhook_url": {
      "url": "https://your-app.example.com/replicas/webhook",
      "secret": "whsec_your_shared_secret"
    }
  }'
```

`webhook_url` accepts either a bare URL string (`"https://..."`) or an object `{ url, secret }`.

The platform `POST`s a JSON body for every event with these headers:

| Header                  | Description                                                                      |
| ----------------------- | -------------------------------------------------------------------------------- |
| `X-Replicas-Event`      | Event type, e.g. `replica.turn_completed`                                        |
| `X-Replicas-Event-Id`   | Stable per-event ID. Reuse for idempotent processing.                            |
| `X-Replicas-Delivery`   | Unique delivery ID for this event delivery. Retry attempts reuse the same value. |
| `X-Replicas-Replica-Id` | The replica's workspace ID                                                       |
| `X-Replicas-Signature`  | `sha256=<hex HMAC-SHA256(secret, raw body)>` (only present when a secret is set) |

Emitted event types:

* `replica.ready`: the workspace finished provisioning (or finished waking) and is reachable. Use this as the "your replica is ready" signal instead of polling `GET /v1/replica/:id`.
* `replica.turn_completed`: the coding agent finished a turn. Payload includes per-repository branches and any newly opened PR URLs.
* `replica.deleted`: the workspace was deleted. Payload data is empty. Only explicit deletion emits this event; closing a linked PR or issue now archives the workspace (silently, with no callback), so automated cleanup no longer fires `replica.deleted`.
* `replica.error`: the workspace entered `error` state and remains queryable. The payload includes the failure message, and `GET /v1/workspaces/:id/status` returns the same message in its `error` field. Some wake/resume errors can be retried with the wake endpoint.

Example `replica.turn_completed` body:

```json theme={null}
{
  "id": "wh_4f3c…",
  "type": "replica.turn_completed",
  "created_at": "2026-05-26T07:31:12.000Z",
  "replica": {
    "id": "11111111-1111-1111-1111-111111111111",
    "name": "fix-auth-bug",
    "status": "active",
    "source": "api",
    "created_at": "2026-05-26T07:29:55.000Z"
  },
  "data": {
    "repository_statuses": [
      {
        "repository": "monorepo",
        "branch": "fix-auth-bug",
        "default_branch": "main",
        "pr_urls": ["https://github.com/o/r/pull/482"]
      }
    ],
    "pr_urls": ["https://github.com/o/r/pull/482"]
  }
}
```

Delivery is retried up to 3× with exponential backoff on network errors, 5xx, and 429 responses. 4xx responses (other than 429) are treated as permanent failures and not retried. Configure your endpoint to respond `2xx` within 10 seconds.

To verify the signature in Node:

```js theme={null}
import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(rawBody, signatureHeader, secret) {
  const expected = `sha256=${createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')}`;
  return signatureHeader?.length === expected.length
    && timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}
```

## Key Concepts

### Environments

Workspaces are created from environments. Each environment can be bound to a repository or repository set and carries the runtime configuration for the workspace (variables, files, skills, MCPs, warm hooks). The full environment management surface is available via the API — see [Environments API](#environments-api) below.

### Chat Management

Each workspace can have multiple chat sessions with different coding agents:

```bash theme={null}
# List chats
curl "https://api.tryreplicas.com/v1/replica/{id}/chats" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Create a new chat
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/chats" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "provider": "cursor", "title": "Refactoring" }'

# Send to a specific chat
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Continue the refactoring", "chat_id": "CHAT_ID" }'

# List available slash commands for a chat
curl "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/slash-commands" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The slash commands endpoint returns built-in Replicas slash commands and agent-provided commands, including Claude skills, Codex ASP skills, Cursor commands, Opencode commands, and Pi prompt templates. Pi skills can also be invoked directly with `/skill:<name>`.

### Pull Request Management

Update a linked GitHub pull request directly without sending an agent message:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/pull-requests/update" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prUrl": "https://github.com/owner/repository/pull/123",
    "action": "convert_to_draft"
  }'
```

Use `close` to close the pull request, `convert_to_draft` for an open pull request, or `mark_ready_for_review` for a draft. The pull request must be linked to the workspace and open. A successful request returns `{ "success": true }`.

### Queue Management

Messages queue automatically when the agent is busy. You can inspect, edit, clear, reorder, and remove queued messages:

```bash theme={null}
# Get the current queue for a chat
curl "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/queue" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Edit a queued message before it is processed
curl -X PATCH "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/queue/{messageId}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Fix the failing tests and add coverage" }'

# Remove a message from the queue
curl -X DELETE "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/queue/{messageId}" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Clear all queued messages
curl -X DELETE "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/queue" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Reorder a queued message (move to a new position)
curl -X PATCH "https://api.tryreplicas.com/v1/replica/{id}/chats/{chatId}/queue/reorder" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "messageId": "MSG_ID", "position": 0 }'
```

Editing only affects messages still waiting in the queue. The request returns the updated [`QueueMutationResponse`](/features/api) with `success` and the current `queue`.

The queue endpoint returns:

```json theme={null}
{
  "chatId": "CHAT_ID",
  "processing": true,
  "queue": [
    {
      "id": "msg_123",
      "message": "Fix the failing tests",
      "queuedAt": "2025-01-01T00:00:00.000Z",
      "senderDisplayName": "Connor"
    }
  ]
}
```

### Mode Flags

Set [`plan_mode`](/features/workspaces/plan-mode), `goal_mode`, or [`fast_mode`](/features/workspaces/fast-mode) to enable mode-specific behavior. `goal_mode` is only available for Codex. Leading slash commands (`/plan`, `/goal`, `/fast`) are also accepted at the start of `message`; Replicas strips them from the sent message and combines them with these flags.

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "/fast Refactor the auth module",
    "plan_mode": true,
    "goal_mode": true
  }'
```

Also supported in `POST /v1/replica` when creating a replica.

### Thinking Level

Control how much reasoning the agent applies with `thinking_level`:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Architect a new microservice for payments",
    "thinking_level": "max"
  }'
```

| Level       | Claude                         | Codex         | Cursor        | Opencode                                | Pi                        | Description                                               |
| ----------- | ------------------------------ | ------------- | ------------- | --------------------------------------- | ------------------------- | --------------------------------------------------------- |
| `low`       | `low`                          | `low`         | `low`         | native variant when supported           | `low`                     | Minimal thinking, fastest responses                       |
| `medium`    | `medium`                       | `medium`      | `medium`      | native variant when supported           | `medium`                  | Moderate reasoning depth                                  |
| `high`      | `high`                         | `high`        | `high`        | native variant when supported           | `high`                    | Deep reasoning                                            |
| `xhigh`     | `xhigh`                        | `xhigh`       | `xhigh`       | native variant when supported           | `xhigh`                   | Extended effort for long-running work                     |
| `max`       | `max`                          | `xhigh`       | `max`         | strongest native variant when supported | strongest supported level | Maximum effort                                            |
| `ultra`     | Not supported                  | `ultra`       | Not supported | Not supported                           | Not supported             | Codex Ultra reasoning with proactive multi-agent behavior |
| `ultracode` | `xhigh` plus dynamic workflows | Not supported | Not supported | Not supported                           | Not supported             | Claude Code automatic workflow orchestration              |

Provider defaults when omitted: Claude = `high`, Codex = `medium`, Cursor = `medium`, Opencode = `medium`, Pi = model default.
Opencode thinking levels use the selected model's native variants when available; models without a matching variant use Opencode's model default.
`ultra` is Codex-only, and `ultracode` is Claude Code-only.

Also supported in `POST /v1/replica` when creating a replica.

### Images

Attach images (screenshots, diagrams) to messages:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/replica/{id}/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Fix the layout issue shown in this screenshot",
    "images": [{
      "type": "image",
      "source": {
        "type": "base64",
        "media_type": "image/png",
        "data": "BASE64_DATA"
      }
    }]
  }'
```

### Chat History

Read the message history for a chat (replaces the deprecated `/read` endpoint):

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}/history?chat_id={chatId}&limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

History is paginated from the end, newest first. `limit` returns the most recent events; `eventsStartIndex` is where that page begins in the full history, and `has_more` tells you whether earlier events exist. To walk backwards, pass the previous `eventsStartIndex` as `beforeEvent`:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}/history?chat_id={chatId}&limit=50&beforeEvent=120" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Page until `has_more` is `false`. `total` is the event count of the whole history, so `total - eventsStartIndex` is how far back you have read. Indexes are stable while you page because new events append to the end.

<Warning>
  Omitting `limit` returns the entire history in one response. Long-running workspaces accumulate large tool outputs, so always set a `limit` in automated clients.
</Warning>

Codex workspaces also return `codexAspTranscript`, whose `turns` page the same way using `beforeTurn` and `turnsStartIndex`.

### Organization Conversation Export

Organization admins can analyze retained conversations across every workspace without waking sleeping or archived workspaces. The index requires an organization API key or an organization-admin session; personal API keys cannot enumerate it. Transcript reads use the existing organization access controls of [Chat History](#chat-history).

List conversations, optionally limiting the export to an environment:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/organization/conversations?environment_id={environmentId}&limit=100" \
  -H "Authorization: Bearer YOUR_ORG_API_KEY"
```

The response includes workspace, environment, creator, agent, and chat metadata. Pass each `next_cursor` back as `cursor` until it is `null`, then read each conversation with the existing [Chat History](#chat-history) endpoint using its `workspace_id` and `chat_id`. The cursor preserves the initial workspace and environment filters and uses immutable artifact creation order, so active transcript updates cannot skip or duplicate conversations while you page. You may omit the original filters on later requests; if supplied, they must remain unchanged. Filter the returned `updated_at` values locally when building incremental exports.

<Warning>
  Chat and workspace deletion take effect immediately, and deleted content is never returned to preserve an earlier export snapshot. If chats or workspaces are deleted or restored while paging, restart the export to obtain a consistent `total` and include any newly restored content.
</Warning>

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{workspaceId}/history?chat_id={chatId}&limit=100" \
  -H "Authorization: Bearer YOUR_ORG_API_KEY"
```

Page older events with `beforeEvent` and Codex turns with `beforeTurn`, as with [Chat History](#chat-history). Deleted chats, deleted workspaces, conversations excluded by [Data Retention](/admin/data-retention), and older workspaces whose engine predates transcript persistence are not returned. Active conversations are exported after a turn finishes and its transcript is persisted.

### Hooks

View warm and start hook execution logs:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}/hooks" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Canvas

Read files the agent drops into the workspace [Canvas](/features/workspaces/canvas) (`~/.replicas/canvas/`). Supported kinds: `markdown`, `html`, `image`, `video`, `audio`, `other`. Items over 5MB are listed but their content is not returned; use [`replicas media upload`](/features/cli) to share larger media. When [Data Retention](/admin/data-retention) is enabled, Canvas items remain available after the workspace sleeps.

List items:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}/canvas" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Each item: `{ filename, kind, sizeBytes }`.

Get a single item:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/replica/{id}/canvas/{filename}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Text kinds (`markdown`, `html`) return `content` (UTF-8 string). Binary kinds return `base64`. Items over the size cap return `tooLarge: true` with no payload.

### Media

List uploaded workspace media, optionally filtering by `image`, `video`, `audio`, or `html`:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/workspaces/{workspaceId}/media?kind=html&page=1&limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Get an expiring download URL for a media item:

```bash theme={null}
curl "https://api.tryreplicas.com/v1/media/{mediaId}/url" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `/v1/media/{mediaId}/preview-url` instead when the browser should render the object inline, including self-contained HTML in a sandboxed iframe. Both endpoints return `{ url, expires_in_seconds }`. For a pull request, use [`replicas media upload --access organization`](/features/cli#canvas-vs-replicas-media-upload) to create a stable link that checks Replicas sign-in and organization membership. HTML pages cannot be shared publicly; `--access public` remains available for image, video, and audio media.

## Environments API

Environments are the primitive that ties together a repository binding plus the runtime configuration (variables, files, skills, MCPs, warm hooks) applied to every workspace created from them. See [Environments](/features/environments) for feature details.

Every organization has a singleton **Global** environment that applies to every workspace. You can address it in any URL by passing the literal string `global` instead of a UUID — there's no need to look up its ID first.

```bash theme={null}
# These are equivalent once you know the UUID
curl ".../v1/environments/global"           -H "Authorization: Bearer KEY"
curl ".../v1/environments/<global-uuid>"    -H "Authorization: Bearer KEY"
```

### List Environments

```bash theme={null}
curl "https://api.tryreplicas.com/v1/environments?scope=all" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns environments with counts of attached variables / files / skills / MCPs. `scope=org` returns team environments, `scope=user` returns your personal environments, and `scope=all` returns both. If omitted, the API defaults to `org`. Responses include `source_environment_id`; source-backed personal environments resolve `repository_id`, `repository_set_id`, and `system_prompt` from their source team environment.

### Get an Environment

```bash theme={null}
curl "https://api.tryreplicas.com/v1/environments/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Or address the org's Global environment directly:
curl "https://api.tryreplicas.com/v1/environments/global" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The response shape matches list results. See [Environments](/features/environments) for the full personal environment inheritance model.

### Create an Environment

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/environments" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "staging",
    "description": "Staging deploys",
    "scope": "org",
    "repository_id": "REPO_UUID",
    "system_prompt": "You target staging only. Never push to main.",
    "mobile_testing_enabled": true
  }'
```

`scope` defaults to `org`. Set `scope: "user"` to create a personal environment visible only to the authenticated user. For team environments, `source_environment_id` copies an existing environment's variables, files, skills, registries, and MCPs into the new environment. For personal environments, `source_environment_id` must reference a team environment, not Global or another personal environment, and creates a source-backed personal environment that inherits from the source instead of copying it. Inherited repository binding, system prompt, and warm pools are locked; personal files, skills, registries, MCPs, warm hooks, and start hooks are additive. Personal variables can only override inherited keys when an admin marks the inherited variable overrideable. Environment responses include `source_environment_id` when an environment inherits from a source. `repository_id` and `repository_set_id` are mutually exclusive; both can be omitted if you want an unbound environment. Set `mobile_testing_enabled` on a team environment to enable [mobile testing](/features/mobile-testing); enabling it requires the free trial, Team, or Enterprise and returns `PLAN_UPGRADE_REQUIRED` otherwise.

### Update an Environment

```bash theme={null}
curl -X PATCH "https://api.tryreplicas.com/v1/environments/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "staging-eu",
    "system_prompt": "Region: eu-west-1.",
    "mobile_testing_enabled": true
  }'
```

The Global environment's metadata cannot be edited via PATCH (only its nested resources like variables and files). PATCH cannot change `repository_id`, `repository_set_id`, `system_prompt`, or `mobile_testing_enabled` on source-backed personal environments. Those environments may instead set `personal_preferences`, free-form text appended after the inherited system prompt; it is only valid on personal environments. `mobile_testing_enabled` can only be set on team environments and is described in [mobile testing](/features/mobile-testing).

### Delete an Environment

```bash theme={null}
curl -X DELETE "https://api.tryreplicas.com/v1/environments/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns 409 when an automation still references the environment, when personal environments inherit from it, or when called against the Global environment.

### Variables

```bash theme={null}
# List
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/variables" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Create
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/variables" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "key": "DATABASE_URL", "value": "postgres://..." }'

# Update
curl -X PATCH "https://api.tryreplicas.com/v1/environments/{environmentId}/variables/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "value": "postgres://new-host/db" }'

# Delete
curl -X DELETE "https://api.tryreplicas.com/v1/environments/{environmentId}/variables/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Values are encrypted at rest. `{environmentId}` accepts `global` for the Global environment. Team and Global variables include `personal_override_allowed`; dashboard admins can set it on create/update to allow source-backed personal environments to override that specific key. Locked inherited variable overrides return 409.

### Files

Files are placed inside workspaces at the configured path. Max content size is 64 KB.

```bash theme={null}
# Create
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/files" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AGENTS",
    "path": "~/AGENTS.md",
    "content": "# Project conventions\n..."
  }'
```

Same `PATCH` / `DELETE` / `GET` shape as variables.

### Skills

Skills come from [skills.sh](https://skills.sh). Search the catalog, then enable a skill on a specific environment.

```bash theme={null}
# Search the catalog
curl "https://api.tryreplicas.com/v1/environment-skills/search?q=docker" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Enable a skill on an environment
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/skills" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "docker",
    "slug": "docker",
    "source": "https://skills.sh/skill/docker"
  }'

# List enabled skills
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/skills" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Disable a skill
curl -X DELETE "https://api.tryreplicas.com/v1/environments/{environmentId}/skills/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Skill registries

Add GitHub repositories as skill registries so their skills install into workspaces at provisioning time. Pre-warmed workspaces refresh registries from GitHub and reinstall discovered skills when claimed, so registry changes are picked up before use.

```bash theme={null}
# List registries for an environment
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/skills-registries" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Add a registry
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/skills-registries" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com/org/skills-repo"
  }'

# Remove a registry
curl -X DELETE "https://api.tryreplicas.com/v1/environments/{environmentId}/skills-registries/{skillsRegistryId}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### MCPs

```bash theme={null}
# List MCPs
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/mcps" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Create a stdio MCP
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/mcps" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "linear",
    "transport": "stdio",
    "config": {
      "command": "npx",
      "args": ["-y", "@linear/mcp"],
      "env": { "LINEAR_API_KEY": "..." }
    }
  }'

# Create an http MCP
curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/mcps" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "internal-tools",
    "transport": "http",
    "config": {
      "url": "https://mcp.example.com",
      "headers": { "Authorization": "Bearer ..." }
    }
  }'
```

`transport` may be `stdio`, `http`, or `sse`. `PATCH` and `DELETE` work on `/v1/environments/{environmentId}/mcps/{id}`.

### Warm Hooks

Each environment has at most one active warm hook (a shell script that runs while pre-warming workspaces). The Global environment's warm hook applies to every pool.

```bash theme={null}
# Read the active warm hook + warm pool config for an environment
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/warm-hooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Read the per-repo warm hooks defined in `replicas.json` / `replicas.yaml` for the env's bound repositories
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/warm-hooks/repository-hooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Test a script without saving (useful while iterating)
curl -X POST "https://api.tryreplicas.com/v1/environments/global/warm-hooks/test" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "#!/usr/bin/env bash\nset -euo pipefail\nbun install\n" }'

# Save without testing — persists and activates the hook immediately
curl -X POST "https://api.replicas.dev/v1/environments/global/warm-hooks/save" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "#!/usr/bin/env bash\nset -euo pipefail\nbun install\n" }'

# Save and test — only persists the new active version when the test succeeds
curl -X POST "https://api.tryreplicas.com/v1/environments/global/warm-hooks/save-test" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "#!/usr/bin/env bash\nset -euo pipefail\nbun install\n" }'

# Stream save & test with SSE (recommended — avoids gateway timeouts)
curl -N -X POST "https://api.replicas.dev/v1/environments/global/warm-hooks/save-test/stream" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{ "content": "#!/usr/bin/env bash\nset -euo pipefail\nbun install\n", "mode": "save_test" }'
# Streams SSE events: progress, output, complete (or error)

# Enable / disable the warm pool for an environment
curl -X PUT "https://api.tryreplicas.com/v1/environments/{environmentId}/warm-pools" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/warm-pools/refresh" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl -X POST "https://api.tryreplicas.com/v1/environments/{environmentId}/warm-pool-snapshots/{snapshotId}/restore" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Warm pools are enabled by default on team environments created via `POST /v1/environments` (`scope: "org"`, the default). Personal environments (`scope: "user"`) start with warm pools disabled. Existing environments are unaffected. Source-backed personal environments inherit their source team's warm hook and may save a personal warm hook through the same mutation endpoints; during testing and pre-warming, the Global hook runs first, followed by the source hook and then the personal hook. Warm pool mutations remain locked to the source environment and return 409.

The refresh endpoint invalidates the current warm-pool generation and immediately starts reconciling its replacement. Refreshes are limited to one every two minutes per environment.

The warm-hook state response includes retained `snapshots`, one entry per captured version. `is_current` marks the version being built or served and `is_fallback` marks the previous version that remains available during the rebuild. Restoring re-installs a retained version without rerunning the warm hook, moving `is_current` onto it. It does not change the currently saved hook script.

There are three mutation endpoints: test-only (runs without persisting), save-only (persists and activates immediately without testing), and save-and-test (persists only if the test passes). The test and save-test endpoints spin up a real isolated sandbox and run your script there. The streaming endpoint (`POST .../warm-hooks/save-test/stream`) returns Server-Sent Events so the connection stays alive during long-running hooks — use it instead of the synchronous save-test endpoint to avoid gateway timeouts. Events include `progress` (status messages), `output` (captured stdout/stderr), and `complete` (final `exit_code`, `timed_out`, and the saved `warm_hook` record on success). The `mode` field can be `"save_test"` (default, persists on success) or `"test_only"`.

### Start Hooks

Each environment has at most one active start hook (a shell script that runs at workspace startup, before repository-level start hooks). The Global environment's start hook applies to every workspace. See [Start Hooks](/features/environments#start-hooks) for feature details.

For a source-backed personal environment, the dashboard fetches its inherited hook from `source_environment_id` and displays it as read-only while the personal environment endpoint manages a separate additive hook. Testing and workspace startup run the Global, source, and personal hooks in that order.

```bash theme={null}
# Read the active start hook for an environment
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/start-hooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Read per-repo start hooks defined in `replicas.json` / `replicas.yaml` for the env's bound repositories
curl "https://api.tryreplicas.com/v1/environments/{environmentId}/start-hooks/repository-hooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Save - persists and activates the start hook immediately. Empty content clears it.
curl -X POST "https://api.tryreplicas.com/v1/environments/global/start-hooks/save" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "#!/usr/bin/env bash\nnpm run dev &\n" }'

# Test without saving (synchronous - returns the full result once the hook finishes)
curl -X POST "https://api.tryreplicas.com/v1/environments/global/start-hooks/test" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "#!/usr/bin/env bash\nnpm run dev &\n" }'

# Test with streaming output (provisions a sandbox, runs the script, tears down)
curl -N -X POST "https://api.tryreplicas.com/v1/environments/global/start-hooks/test/stream" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{ "content": "#!/usr/bin/env bash\nnpm run dev &\n" }'
```

The synchronous test endpoint runs the script in an isolated sandbox and returns `{ test: { exit_code, output, timed_out } }` once the hook finishes - use it from CLI tooling and short-lived clients. The streaming endpoint emits SSE events (`progress`, `output`, `complete`, `error`) and is recommended for long-running hooks to avoid gateway timeouts. The Global environment can be addressed as `"global"` in any URL, no UUID lookup required.

## Automations API

Automations let you trigger replicas on a schedule or in response to GitHub or GitLab events. The full CRUD is available via the API. See [Automations](/features/automations) for feature details.

Automations default to `scope: "org"`. Set `scope: "user"` when creating an automation with a personal API key or JWT auth to make it personal to that user inside the current organization. Org API keys cannot read, edit, run, or delete personal automations.

### List Automations

```bash theme={null}
curl "https://api.tryreplicas.com/v1/automations?page=1&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `scope=user` to list your personal automations, or `scope=all` to list org automations plus your personal automations.

### Create an Automation

Create a cron-triggered automation that runs every weekday at 9am:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "daily-code-review",
    "scope": "user",
    "prompt": "Review open PRs and leave comments on code quality issues",
    "environment_id": "ENVIRONMENT_UUID",
    "triggers": [
      {
        "type": "cron",
        "config": {
          "schedule": "0 9 * * 1-5",
          "timezone": "America/New_York"
        }
      }
    ]
  }'
```

Create a GitHub-triggered automation that fires when a PR is opened, and pin it to Claude with Opus 4.8 (1M) and `high` thinking:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "pr-review",
    "prompt": "Review this PR for bugs and suggest improvements",
    "environment_id": "ENVIRONMENT_UUID",
    "triggers": [
      {
        "type": "github",
        "config": {
          "event": "pull_request.opened"
        }
      }
    ],
    "workspace_lifecycle_policy": "archive_when_done",
    "workspace_size": "small",
    "agent_provider": "claude",
    "model": "claude-opus-4-8",
    "thinking_level": "high"
  }'
```

The automation runs against the repository (or repository set) bound to the chosen environment. See [Environments](/features/environments) for how to obtain an `environment_id`.

Use `"type": "gitlab"` with events like `"merge_request.opened"` for GitLab project automations:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "mr-review",
    "prompt": "Review this merge request for bugs and suggest improvements",
    "environment_id": "ENVIRONMENT_UUID",
    "triggers": [
      {
        "type": "gitlab",
        "config": {
          "event": "merge_request.opened"
        }
      }
    ]
  }'
```

Optional `workspace_size` picks the compute envelope (and per-minute price) for every workspace the automation fires off. Accepts `small` (2 vCPU, 8 GB, 20 GB; \$0.008/min) or `large` (4 vCPU, 16 GB, 32 GB; \$0.016/min). Defaults to `small`. The same field is accepted on `PATCH /v1/automations/:id`.

Personal automation runs create workspaces with the automation owner's `user_id`, but the workspace source remains `automation`. They are billed as automation metered usage, not seat usage.

`agent_provider`, `model`, and `thinking_level` are all optional. Omit any of them to inherit the organization's default agent and the agent's own defaults. Valid `agent_provider` values are `claude`, `codex`, `cursor`, `opencode`, and `pi`. `model` must be one of the models supported by the chosen provider (e.g. `claude-fable-5`, `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-haiku-4-5` for Claude; `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.2` for Codex; `claude-fable-5`, `claude-opus-4-8`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `composer-2.5`, `grok-4.5` and other Cursor models for Cursor; active Aster IDs such as `kimi-k3`, `glm-5.2`, and `gpt-oss-120b-fast`, OpenRouter model slugs such as `z-ai/glm-5.2`, or active IDs from the OpenCode Go catalog). OpenRouter slugs are limited to the models enabled for the organization; see `GET /v1/openrouter/models`. `thinking_level` is one of `low`, `medium`, `high`, `xhigh`, `max`, `ultra` (Codex only), or `ultracode` (Claude Code only).

Optional `debounce_seconds` sets a per-automation debounce window (0-86400 seconds, where 0 or null disables debouncing). When greater than 0, bursty trigger events update one pending run and the latest payload fires after the automation stops receiving events for the configured window. GitHub and GitLab events keep separate pending runs per repository and pull or merge request. Accepts integers or null. Defaults to null (disabled). The same field is accepted on `PATCH /v1/automations/:id`.

Optional `github_check_names` takes up to 10 unique [GitHub checks](/features/automations#github-checks) (100 characters each) that the automation reports its verdict on. Requires a `pull_request.opened` or `pull_request.synchronize` trigger. Defaults to an empty array. The same field is accepted on `PATCH /v1/automations/:id`; pass `[]` to stop creating checks.

### Get an Automation

```bash theme={null}
curl "https://api.tryreplicas.com/v1/automations/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Update an Automation

```bash theme={null}
curl -X PATCH "https://api.tryreplicas.com/v1/automations/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false
  }'
```

`agent_provider`, `model`, and `thinking_level` are also patchable. Send `null` for any field to clear the override and fall back to the default. Note that changing `agent_provider` without also providing a new `model` clears the stored model, since the previous model may not be valid for the new provider.

### Delete an Automation

```bash theme={null}
curl -X DELETE "https://api.tryreplicas.com/v1/automations/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Report a GitHub Check

Reports a run's verdict on one of its [GitHub checks](/features/automations#github-checks). Requires in-workspace credentials, since the calling workspace is what identifies the run that owns the check. Normally invoked through `replicas automation check`.

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations/checks/{check_run_id}" \
  -H "Authorization: Bearer WORKSPACE_ENGINE_SECRET" \
  -H "X-Workspace-Id: WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{"token": "OWNERSHIP_TOKEN", "conclusion": "success", "title": "No duplicated logic", "summary": "Reviewed the diff."}'
```

`token` is the ownership token the run was given for that check, which names the run the verdict came from. `conclusion` is `success` or `failure`. The response reports `reported: false` when a newer run of the automation has taken the check over and the verdict was discarded.

### Manually Trigger an Automation

Works for automations with a cron trigger:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations/{id}/trigger" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Automations with a `pull_request.command` trigger can instead be run against a specific pull request by passing a `pr` target:

```bash theme={null}
curl -X POST "https://api.tryreplicas.com/v1/automations/{id}/trigger" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pr": {"repository_id": "REPOSITORY_UUID", "number": 123}}'
```

### List Execution History

```bash theme={null}
curl "https://api.tryreplicas.com/v1/automations/{id}/executions?page=1&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Each execution reports `workspace_deleted`. Automation workspaces are removed once their [lifecycle policy](/features/automations#how-it-works) expires, so runs outlive the workspaces they created. When `workspace_deleted` is `true`, treat `workspace_id` as a historical reference; the workspace is gone and no longer retrievable.

## Workspace Lifecycle

| Status      | Description                                                                                                                                                                                                                                                                        |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `preparing` | Workspace is being created and initialized                                                                                                                                                                                                                                         |
| `active`    | Workspace is running and ready for messages                                                                                                                                                                                                                                        |
| `sleeping`  | Workspace is paused (auto-wakes on interaction)                                                                                                                                                                                                                                    |
| `archived`  | Workspace is paused for retention (auto-wakes on interaction)                                                                                                                                                                                                                      |
| `error`     | Setup/provisioning failed, a wake/resume attempt failed, or the underlying sandbox died. `POST /v1/workspaces/:id/wake` accepts `error` workspaces for retry and powers the dashboard **Retry** flow. See the [workspaces overview](/features/workspaces/overview) for next steps. |

When you interact with a sleeping or archived workspace, it wakes automatically. The response will include `waking: true`. When a warm pool is configured for the target repository or repository set, expect setup times under 10 seconds. Otherwise, expect 10-60 seconds depending on repository size.

Engine-proxy endpoints (messages, chats, history, canvas, logs, previews, events) return **409 Conflict** when the workspace is in `sleeping`, `archived`, or `error`, so clients can branch on that status instead of retrying indefinitely. `POST /v1/replica/{id}/wake` accepts `sleeping`, `archived`, and retryable `error` workspaces; read the workspace's `status` field from `GET /v1/replica/:id` before deciding whether to wake or show support guidance.

## API Versioning

`POST /v1/replica` supports an optional dated version header:

```
X-Replicas-Api-Version: 2026-05-17
```

| Header value | Behavior                                                                                                                                                                                                                                    |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| *(omitted)*  | **Legacy.** Request blocks until the workspace reaches `active`, then returns. Engine details are populated in the response.                                                                                                                |
| `2026-05-17` | **Fire-and-forget.** Request returns immediately with a `preparing` workspace. The initial message is still delivered to the agent in the background; poll `GET /v1/replica/:id` or stream `GET /v1/replica/:id/events` to follow progress. |

Pin a specific version when you want stable behavior across future API changes. We will continue to ship dated versions for breaking changes and announce sunset dates ahead of removing prior contracts.

## Prerequisites

Before using the API:

1. [Add your repository](/features/workspaces/repository-configuration) in the dashboard
2. [Configure credentials](/admin/credentials) for your coding agent

## Use Cases

* **CI/CD Integration** - Trigger replicas from GitHub Actions or other pipelines
* **Batch Operations** - Create multiple replicas for parallel task execution
* **Custom Workflows** - Build internal tools that leverage AI coding agents
* **Monitoring** - Stream events and poll workspace state for dashboards

## Billing

API workspaces are metered separately from your seat subscription. See [Billing](/admin/billing) for rates, rounding, and plan details.

## API Reference

See the [API Reference](/api-reference) tab for complete endpoint documentation with request/response schemas.
