API reference: Pipelines
Cushy pipelines API: application build/deploy pipelines and infrastructure pipelines that drive the real Terraform lifecycle, with runs, stages, logs and the second-operator approval handoff.
The deploy control plane. A pipeline carries a kind: an application pipeline builds an application Git repo and deploys it to an optional Terraform workspace (source → build → deploy — real with an enrolled deploy agent, recorded without one); an infrastructure pipeline drives its target workspace's REAL Terraform lifecycle (plan → approve → apply through the same engine, honoring the workspace's approval policy and the account's provisioning opt-in). Every Terraform workspace auto-creates an infrastructure pipeline (provision-<workspace>), and every apply attempt on the workspace is reflected 1:1 as a pipeline run — success and failure — so the two views line up. Reads are open to members; create/run/approve/delete need mutate_infra; cross-org ids 404.
/api/pipelinesSessionList your org's pipelines with kind, source/target and last-run state.
{ "pipelines": [ { "id": 2, "name": "provision-web-tier", "kind": "infrastructure",
"targetWorkspaceId": 7, "targetWorkspaceName": "web-tier", "criticality": "production",
"lastRun": { "number": 1, "state": "succeeded" } } ] }| Status | When |
|---|---|
401 | Not signed in. |
/api/pipelinesmutate_infraCreate a pipeline. An application pipeline needs an application-type git connection + repo; an infrastructure pipeline needs a target workspace (no app source). Returns 201.
| Name | In | Required | Description |
|---|---|---|---|
name | body | yes | Pipeline name. |
kind | body | no | application (default) | infrastructure. |
appGitConnectionId / appRepo | body | no | Application source (kind application; the connection must be repo_type=application). |
targetWorkspaceId | body | no | Terraform workspace (required for kind infrastructure; optional deploy target for application). |
strategy | body | no | Deploy strategy label (e.g. rolling). |
| Status | When |
|---|---|
400 | Wrong source type for the kind, or a missing required field. |
403 | Role lacks mutate_infra (Viewer). |
404 | Cross-org connection/workspace ids. |
/api/pipelines/{id}/runmutate_infraRun the pipeline. Application: source → build → deploy with per-stage logs. Infrastructure: plan (policy/cost gates — a failure ends the run at the plan stage) → approve (a standard workspace self-approves; a PRODUCTION workspace pauses awaiting a second operator) → apply. Optional { vars } override the plan variables for an infrastructure run.
{ "run": { "id": 9, "number": 2, "state": "running", "awaitingApproval": true, "stages": [ … ] } }| Status | When |
|---|---|
403 | Role lacks mutate_infra. |
404 | No such pipeline in your org. |
/api/pipelines/{id}/runs/{runId}/approvemutate_infra (approver ≠ author on production)Complete a paused production-workspace run: a SECOND operator approves the underlying Terraform run (separation of duties is never bypassed — the plan author gets 403) and the apply proceeds.
| Status | When |
|---|---|
403 | The approver is the plan's author (production), or the role lacks mutate_infra. |
404 | No such pipeline/run in your org. |
GET /api/pipelines/{id} returns the pipeline with its runs (each with the executing agent, commit sha and per-stage {seq,level,line} logs plus command/exitCode/durationMs) and the releases history; PATCH /api/pipelines/{id} updates an application pipeline's deploy config (branch, dockerfilePath, containerPort, hostPort, healthPath, testCommand, env); DELETE /api/pipelines/{id} removes it (cascading its deploy jobs + releases). Audits: pipeline.created/run_started/awaiting_approval/run_succeeded/run_failed/deleted/deploy_config_updated.
Deploy agents (real application deploys)
A deploy agent is a process the customer runs on their own Linux or Windows machine (see Deploy an application). It authenticates with a one-time enrollment token (cc_agt_…, SHA-256 at rest), heartbeats, and long-polls for jobs scoped to its own organization. POST /api/pipelines/{id}/run with { "runner": "agent" } queues a real clone → build → deploy → health-verify on one of your enrolled agents.
/api/deploy/agentsSessionThe org's agent fleet with liveness. The enrollment token (and its hash) is NEVER returned.
{ "agents": [ { "id": 3, "name": "build-box-1", "os": "linux", "arch": "x64",
"version": "1.0.0", "capabilities": ["git","docker","node"],
"lastSeenAt": "2026-08-09T01:42:08Z", "online": true, "revokedAt": null } ] }| Status | When |
|---|---|
401 | Not signed in. |
/api/deploy/agentsmanage_cloud_accountsEnroll an agent and return its ONE-TIME token (shown once; only the SHA-256 is stored). Gated on manage_cloud_accounts because an agent receives the org's repository credential.
| Name | In | Required | Description |
|---|---|---|---|
name | body | yes | A name for the machine (unique per org). |
{ "agent": { "id": 3, "name": "build-box-1", "online": false }, "token": "cc_agt_…" }| Status | When |
|---|---|
400 | Invalid name. |
403 | Role lacks manage_cloud_accounts. |
409 | That agent name is already enrolled, or the org is at the agent limit. |
/api/deploy/agents/{id}manage_cloud_accountsRevoke the agent's token immediately (the row is kept for audit). Its next call gets the same generic 401 as an unknown token.
| Status | When |
|---|---|
403 | Role lacks manage_cloud_accounts. |
404 | No such agent in your org. |
/api/pipelines/{id}/diagnosticsSessionTroubleshooting facts for an application pipeline: agents online, git-connection health, a real Dockerfile probe on the build branch, port mapping + health path, the last run's failing stage/exit code/command, the live release, and a blockers list.
| Status | When |
|---|---|
400 | The pipeline is an infrastructure pipeline. |
404 | No such pipeline in your org. |
/api/pipelines/{id}/rollbackmutate_infraRe-deploy an earlier release's exact image ({ releaseId }) — deploy + verify only, no clone and no rebuild.
| Status | When |
|---|---|
400 | Missing releaseId. |
403 | Role lacks mutate_infra. |
404 | No such pipeline/release in your org. |
409 | No agent is online, a deploy is already in flight, or the release has no image. |
The agent-side protocol (Authorization: Bearer cc_agt_…, never a cookie) is POST /api/agent/heartbeat, POST /api/agent/jobs/claim (atomic lease — two agents can never run one job), POST /api/agent/jobs/{id}/stage (streamed stdout/stderr + command + exit code + duration) and POST /api/agent/jobs/{id}/complete (terminal state + release, or the real error). Credentials are injected only into the claim response, never persisted in the job, and are redacted server-side out of every stored log line. Audits: deploy.agent_enrolled/agent_revoked/job_queued/released/rollback_started/rolled_back/rbac_denied.