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: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
Thename field must not contain whitespace (e.g. fix-auth-bug, not fix auth bug).
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 finishessleep_when_done- workspace sleeps when the agent finishes, keeping history availabledelete_after_inactivity- workspace is deleted after a period of inactivity. Not available to automations, whose workspaces archive instead so each run stays inspectable
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
4. Check Status
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.
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.
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
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 return404 because engine updates are not retroactive.
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: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
200 OK with { "success": true }. IDs that never existed or belong to another organization return 404.
9. Stream Events (SSE)
10. Webhook Callbacks (alternative to polling)
Passwebhook_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 pollingGET /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 firesreplica.deleted.replica.error: the workspace enterederrorstate and remains queryable. The payload includes the failure message, andGET /v1/workspaces/:id/statusreturns the same message in itserrorfield. Some wake/resume errors can be retried with the wake endpoint.
replica.turn_completed body:
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:/skill:<name>.
Pull Request Management
Update a linked GitHub pull request directly without sending an agent message: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:QueueMutationResponse with success and the current queue.
The queue endpoint returns:
Mode Flags
Setplan_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.
POST /v1/replica when creating a replica.
Thinking Level
Control how much reasoning the agent applies withthinking_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):
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:
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.
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: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.
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:
{ filename, kind, sizeBytes }.
Get a single item:
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 byimage, video, audio, or html:
/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 stringglobal instead of a UUID — there’s no need to look up its ID first.
List Environments
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
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
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
Variables
{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.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.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 fromsource_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.
{ 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 toscope: "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
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:high thinking:
environment_id.
Use "type": "gitlab" with events like "merge_request.opened" for GitLab project automations:
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 throughreplicas 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:pull_request.command trigger can instead be run against a specific pull request by passing a pr target:
List Execution History
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:- Add your repository in the dashboard
- 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