Skip to content

API Reference

The SAM API runs on a Cloudflare Worker at api.{domain}. All authenticated endpoints require a valid BetterAuth session cookie.

Task agents can call wait_for_subtasks with a stable workflow-step waitKey, unique same-project task IDs, an optional condition of all (the default) or any, and an optional bounded wakeAfterSeconds. The agent must persist the workflow state and key before calling, reuse the key after a lost response, and end its turn after registration. ProjectData then reconciles selected task terminal state and durably wakes the same canonical caller session exactly once, including after session sleep and runtime replacement. Automatic wake prompts carry only trusted task IDs and statuses; agents fetch peer-authored output explicitly as untrusted data. Servers without durable prompt delivery reject registration so clients can use bounded foreground polling as a compatibility fallback.

Private feedback-project agents can also call list_incident_queue, get_incident, claim_incident, and resolve_incident. These tools are scoped server-side to the effective private feedback project setting (Admin → Integrations runtime value first, then PLATFORM_FEEDBACK_PROJECT_ID fallback); callers cannot provide a project id. claim_incident and resolve_incident require a task-scoped MCP token, use bounded leases/CAS tokens, and return only private redacted incident evidence labelled as untrusted. resolve_incident accepts structured ship-or-track fields for resolved outcomes: fixPrUrl, dispatchedTaskId, or linkedRecordId; rejected outcomes require a justification note instead.

Project eventing uses a pull loop over the canonical ProjectData project_event_* tables. Agents create a short-lived subscription with create_project_event_subscription, using v1 exact/set filters for source, eventType, subjectType, subjectId, and severity; recover existing subscriptions with list_project_event_subscriptions; inspect or cancel with get_project_event_subscription and cancel_project_event_subscription. Project, task, session, workspace, owner, and agent identity come from the verified MCP token, not tool arguments.

After subscribing, call list_subscription_events with the subscriptionId to replay missed or queued matches. The list response is payload-free: it returns summaries, delivery IDs, delivery state, hasMore, and an opaque nextCursor that is valid only for the same subscription. Call get_event only when a summary needs full stored event details, then call ack_event_delivery after processing each returned deliveryId; ack is idempotent. V1 records matches, delivery decisions, and pull acknowledgements only. It does not inject prompts, steer runtimes, interrupt sessions, spawn tasks, or expose human/UI controls.

Start GitHub OAuth flow. Redirects to GitHub for authorization.

End the current session.

Returns the current authenticated session and user info.

Create a new workspace.

Body:

{
"installationId": "12345",
"repository": "owner/repo",
"branch": "main",
"vmSize": "medium",
"displayName": "My Workspace"
}

List all workspaces for the authenticated user.

Get workspace details including status, node info, and URLs.

Permanently stop a running workspace and delete any retained persistent-session snapshot. Use sleep when the same chat must be resumable.

Checkpoint the workspace’s agent HOME, harness identity, and repository work in progress, verify the snapshot, and put the session to sleep. VM compute is stopped only after SAM re-verifies the durable manifest and every artifact the manifest still claims. A complete snapshot restores the full state; a degraded-but-verified snapshot can still sleep and will surface reduced restore state on wake. If an accepted final checkpoint stops reporting progress, SAM records an explicit degraded snapshot instead of leaving idle compute awake indefinitely. Sending a follow-up in the same chat wakes the session during the seven-day retention window.

Restart a stopped or errored workspace. Provisions a new VM and recreates the container. A restart can cancel an unclaimed pending deletion, but returns 409 once a deletion attempt has started or if the workspace identity changes before runtime recreation.

Rebuild a running, recovering, or errored workspace on its assigned node. Returns 202 with { "status": "rebuilding" } after the exact workspace transition is claimed. Rebuild uses the same deletion fence as restart: it cannot cancel or cross a deletion attempt that has already started, and the VM request is refused if the workspace identity or status changes.

Permanently request deletion of a workspace, its retained session snapshot, and associated resources. A confirmed deletion returns 200 with { "success": true, "deletionStatus": "confirmed" }. If VM deletion is not yet proven, the endpoint returns 202 with { "success": true, "deletionStatus": "pending", "workspaceStatus": "stopping", "reason": "..." }. The 202 response is not deletion proof: SAM keeps the workspace quarantined and retries from durable state until VM absence/success or strict provider/container termination is confirmed. The same 202 is returned for an idempotent repeat while that exact durable attempt is already in flight, or when VM proof arrived but a concurrent state write requires terminalization to converge on a later retry. If the exact deletion target is missing, active, or reassigned before a durable attempt is retained, the endpoint returns 409 with deletionStatus: "rejected"; it never labels that rejection as a pending deletion.

Get the provisioning progress log for a workspace.

Create a new agent session in a workspace. The agent (Claude Code, Codex, Gemini CLI, etc.) is determined by the selected agent profile.

List active agent sessions for a workspace.

POST /api/workspaces/:id/agent-sessions/:sessionId/stop

Section titled “POST /api/workspaces/:id/agent-sessions/:sessionId/stop”

Stop a running agent session.

List all nodes for the authenticated user.

Get node details including health status and hosted workspaces.

Stop a running node. All workspaces on the node must be stopped first.

Delete a node and clean up DNS records and Hetzner resources.

Add or update a credential (cloud provider token or agent API key).

Body:

{
"provider": "hetzner",
"credentialType": "cloud-provider",
"token": "your-api-token"
}

List all credentials for the authenticated user (tokens are not returned).

Delete a stored cloud-provider credential.

List non-secret compute-provider catalog metadata for cloud-provider credentials the caller can use. The response includes provider-native instance offerings, locations, normalized resource metadata, price metadata when available, and a catalogSource value such as api or static.

Optional query parameters:

ParameterValuesDescription
scopeuser, project, installationSelects the credential scope to inspect. Omit it for the authenticated user’s personal catalog.
projectIdProject IDRequired when scope=project; the caller must have the project secret:read capability.

Installation scope is restricted to superadmins and uses enabled platform compute credentials. User scope uses the caller’s active personal compute credentials. Project scope returns active compute credentials attached to that project after project secret:read authorization, including composable-credential attachments from other project members. Effective default pool summaries expose project → user → installation fallback separately.

If no credentials are visible for the requested scope, the response still returns catalogs: [] with credentialSetupRequired: true and a credentialSetupMessage suitable for setup UI.

Default capacity-pool endpoints expose non-secret pool, source, and concrete candidate metadata. Responses have this shape: effective, effectiveScope, defaults, precedence, reconciledScopes, and policyMutationSupported. Use ensure=true on GET endpoints, or call the matching /reconcile endpoint, to refresh pool metadata from the credential-scoped provider-native catalog. Provider API failures fall back to static curated catalog rows for that provider. Provider catalog offerings expose catalogSource; capacity-pool candidates expose the persisted providerInstanceCatalogSource snapshot.

Read the authenticated user’s default compute pool. Optional ensure=true reconciles it from the user’s active personal compute credentials. Disabled zero-active owned pools remain visible for the editor; they are not selected as effective.

POST /api/capacity-pools/defaults/reconcile

Section titled “POST /api/capacity-pools/defaults/reconcile”

Explicitly reconcile the authenticated user’s default pool from active personal compute credentials.

Update the authenticated user’s owned default-pool policy, candidate statuses, or provider-native catalogAdditions. This endpoint does not mutate project or installation fallback pools.

catalogAdditions reactivates a currently available provider-native offering from the same credential-scoped catalog used by reconciliation. It identifies the active source plus concrete provider/location/instance type; it does not accept secret material:

{
"catalogAdditions": [
{
"sourceId": "cap-source-default:user:user-credential-id",
"provider": "hetzner",
"location": "fsn1",
"providerInstanceType": "cpx62",
"providerInstanceSku": null
}
]
}

GET /api/projects/:id/capacity-pools/defaults

Section titled “GET /api/projects/:id/capacity-pools/defaults”

Read a project’s default pool context. Requires project secret:read. Optional ensure=true reconciles project credentials plus visible fallback summaries. Non-superadmins do not receive installation fallback details.

POST /api/projects/:id/capacity-pools/defaults/reconcile

Section titled “POST /api/projects/:id/capacity-pools/defaults/reconcile”

Explicitly reconcile visible default capacity-pool metadata from existing credentials in the project context. Project-scoped metadata comes from active project compute credentials. Requires project secret:read.

PATCH /api/projects/:id/capacity-pools/defaults

Section titled “PATCH /api/projects/:id/capacity-pools/defaults”

Update only the project-owned default-pool policy, candidate statuses, or provider-native catalogAdditions. Requires project secret:write.

Read the installation default pool. Superadmin only. Optional ensure=true reconciles enabled platform compute credentials.

POST /api/admin/capacity-pools/defaults/reconcile

Section titled “POST /api/admin/capacity-pools/defaults/reconcile”

Explicitly reconcile the installation default pool from enabled platform compute credentials. Superadmin only.

Update only the installation-owned default-pool policy, candidate statuses, or provider-native catalogAdditions. Superadmin only.

List GitHub App installations for the authenticated user.

GET /api/github/repositories?installation_id=:id

Section titled “GET /api/github/repositories?installation_id=:id”

List repositories accessible through a GitHub App installation.

Post-installation redirect handler. Records the installation and redirects to Settings.

List all projects for the authenticated user.

Create a new project linked to a GitHub repository.

Get project details.

Create a task record.

Body:

{
"title": "Fix the login button"
}

POST /api/projects/:projectId/environments/:envId/releases

Section titled “POST /api/projects/:projectId/environments/:envId/releases”

Create a deployment release for an environment.

Preferred body: Docker Compose YAML with Content-Type: text/yaml, application/yaml, text/x-yaml, or application/x-yaml. Compose submissions may use x-sam-routes for routes and x-sam-secret environment values for secret references.

Raw manifest JSON is still accepted for backward compatibility when another content type is used.

Submit an idea for autonomous execution. This is the chat-first path used by the web app; it creates the task, records the first message, and starts execution.

Body:

{
"message": "Fix the login button on the settings page"
}

These endpoints proxy file operations to the workspace’s VM agent, accessed through a project chat session.

GET /api/projects/:id/sessions/:sessionId/files/list

Section titled “GET /api/projects/:id/sessions/:sessionId/files/list”

List files in a workspace directory.

GET /api/projects/:id/sessions/:sessionId/files/view

Section titled “GET /api/projects/:id/sessions/:sessionId/files/view”

View the contents of a file in the workspace.

POST /api/projects/:id/sessions/:sessionId/files/upload

Section titled “POST /api/projects/:id/sessions/:sessionId/files/upload”

Upload files to the workspace container (multipart form data).

GET /api/projects/:id/sessions/:sessionId/files/download

Section titled “GET /api/projects/:id/sessions/:sessionId/files/download”

Download a file from the workspace container.

GET /api/projects/:id/sessions/:sessionId/files/raw

Section titled “GET /api/projects/:id/sessions/:sessionId/files/raw”

Stream a binary file (images, etc.) with MIME detection and ETag support.

GET /api/projects/:id/sessions/:sessionId/git/status

Section titled “GET /api/projects/:id/sessions/:sessionId/git/status”

Get git status of the workspace repository.

GET /api/projects/:id/sessions/:sessionId/git/diff

Section titled “GET /api/projects/:id/sessions/:sessionId/git/diff”

Get git diff output for the workspace repository.

Generate a short-lived JWT for WebSocket terminal access.

Body:

{
"workspaceId": "ws-abc123"
}

Response:

{
"token": "eyJhbG...",
"expiresAt": 1730000000000,
"workspaceUrl": "https://ws-abc123.example.com"
}

The client opens the terminal WebSocket at wss://ws-abc123.example.com/terminal/ws/multi?token=... using the returned token.

Public health check endpoint. Returns { "status": "healthy", "timestamp": "..." } (or "degraded" with a 503 when critical bindings are unavailable). No version or internal details are exposed.

JSON Web Key Set for JWT verification by VM Agents.

Download the VM Agent binary. Query params: os (linux), arch (amd64, arm64).

Used by cloud-init during VM (BYOC) provisioning. The Cloudflare Container instant-session runtime does not call this endpoint — its vm-agent binary is baked into the container image at deploy time.

POST /api/projects/:projectId/sessions/start

Section titled “POST /api/projects/:projectId/sessions/start”

Start an Instant chat session. Returns 202 with { status: 'starting', runtime, taskId, sessionId, workspaceId, nodeId, workspaceUrl } as soon as the records exist; the container launch, repository clone, agent start, and first prompt continue in the background, so a client disconnect no longer strands the session.

Because the launch is asynchronous, the response does not carry agentSessionId, acpSessionId, or launch timings — poll the session or connect to its stream for live state.

This endpoint is Instant-only. It returns 409 (Selected profile resolves to VM runtime; use task submission instead.) whenever the runtime resolves to VM — because the profile pins vm, because the caller has their own or a project cloud credential, or because CF_CONTAINER_ENABLED is not true for the deployment. Use POST /api/projects/:id/tasks/submit for VM work.

See Reporting Issues for the user-facing flow and the operator configuration these endpoints depend on.

Report whether in-app issue reporting is available on this deployment. Returns { "enabled": false } when no effective private feedback project is configured, or when the effective setting does not name an existing project — the UI hides both entry points in that case.

Submit an issue report. Returns 201 with the grouped incident’s private draft Idea ideaId, its status, and attachedRefKeys listing the technical references that were actually stored. Repeated matching reports update the same grouped incident/Idea instead of creating one Idea per occurrence.

Body fields: title, description, consentToAttachRefs, and an optional refs object (sessionId, taskId, nodeId, errorId, diagnosisId). References are only stored when consentToAttachRefs is true, and each is re-checked against the caller’s access first — unauthorized references are dropped silently rather than rejecting the request, so attachedRefKeys may be shorter than what was sent.

Rate-limited to 20 submissions per clock hour per user (RATE_LIMIT_REPORT_ISSUE_POST); exceeding it returns 429.

POST /api/admin/observability/feedback-triage

Section titled “POST /api/admin/observability/feedback-triage”

Superadmin only. Runs a platform-error triage sweep immediately instead of waiting for the hourly cron. The feedback project itself is configured from Admin → Integrations or the environment fallback; this endpoint remains the manual way to verify automated triage without waiting up to an hour.

These endpoints require an approved, authenticated superadmin. The switches are availability brakes: an absent KV key or KV read error means enabled (fail-open), so a transient KV outage does not silently halt recovery work.

Read the cron-sweep and Durable Object alarm switches. The response includes cronSweepsEnabled, doAlarmsEnabled, the resolved KV keys, the in-memory cache TTL, the disabled-alarm retry interval, and semantics: "fail-open".

Update either or both switches. At least one field is required and every provided value must be boolean.

{
"cronSweepsEnabled": false,
"doAlarmsEnabled": false
}

Disabling the alarm switch does not drop alarm chains: each affected Durable Object re-arms at the reported safe retry interval and resumes normally after the switch is enabled again.