Skip to main content
The Replica API lets you programmatically create workspaces, send messages to coding agents, manage chats, and monitor workspace state.
The Replica API and 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.

Authentication

Organization admins can generate org API keys from Organization → Settings → API Keys. You can generate personal API keys from Personal → API Keys. Include it as a Bearer token in requests:
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

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:

2. Create a Replica

The name field must not contain whitespace (e.g. fix-auth-bug, not fix auth bug).
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; 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. 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, whose workspaces archive instead so each run stays inspectable
Optional size picks the compute envelope and per-minute price for this replica: 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. 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 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

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

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

5. Archive a Workspace

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

7. List Mobile Testing Instances

List active iOS simulators and Android emulators associated with a workspace:
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

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)

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:
webhook_url accepts either a bare URL string ("https://...") or an object { url, secret }. The platform POSTs a JSON body for every event with these headers: 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:
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:

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

Chat Management

Each workspace can have multiple chat sessions with different coding agents:
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:
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:
Editing only affects messages still waiting in the queue. The request returns the updated QueueMutationResponse with success and the current queue. The queue endpoint returns:

Mode Flags

Set plan_mode, goal_mode, or 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.
Also supported in POST /v1/replica when creating a replica.

Thinking Level

Control how much reasoning the agent applies with thinking_level:
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:

Chat History

Read the message history for a chat (replaces the deprecated /read endpoint):
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:
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.
Omitting limit returns the entire history in one response. Long-running workspaces accumulate large tool outputs, so always set a limit in automated clients.
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. List conversations, optionally limiting the export to an environment:
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 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.
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.
Page older events with beforeEvent and Codex turns with beforeTurn, as with Chat History. Deleted chats, deleted workspaces, conversations excluded by 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:

Canvas

Read files the agent drops into the workspace 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 to share larger media. When Data Retention is enabled, Canvas items remain available after the workspace sleeps. List items:
Each item: { filename, kind, sizeBytes }. Get a single item:
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:
Get an expiring download URL for a media item:
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 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 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.

List Environments

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

The response shape matches list results. See Environments for the full personal environment inheritance model.

Create an Environment

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; enabling it requires the free trial, Team, or Enterprise and returns PLAN_UPGRADE_REQUIRED otherwise.

Update an Environment

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.

Delete an Environment

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

Variables

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.
Same PATCH / DELETE / GET shape as variables.

Skills

Skills come from skills.sh. Search the catalog, then enable a skill on a specific environment.

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.

MCPs

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

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:
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:
The automation runs against the repository (or repository set) bound to the chosen environment. See Environments for how to obtain an environment_id. Use "type": "gitlab" with events like "merge_request.opened" for GitLab project automations:
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 (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

Update an Automation

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

Report a GitHub Check

Reports a run’s verdict on one of its 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.
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:
Automations with a pull_request.command trigger can instead be run against a specific pull request by passing a pr target:

List Execution History

Each execution reports workspace_deleted. Automation workspaces are removed once their lifecycle policy 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

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:
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 in the dashboard
  2. Configure 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 for rates, rounding, and plan details.

API Reference

See the API Reference tab for complete endpoint documentation with request/response schemas.