opsdocsConsole

Ops platform / HTTP API

Builds and deployments

Connect a repository, follow builds, deploy and roll back services, and read the deployment history.

Updated 13 Oct 2026View as Markdown

Connect a repository, follow builds, deploy and roll back services, and read the deployment history.

GET /api/v1/github/app

The App and the URL that installs it. installations is how many owners it is on, so the page can say "configured but installed nowhere" rather than guessing from an empty repository list.

StatusMeansBody
200DoneGitHubAppResponse
503GitHub App not configured

GET /api/v1/github/repos

Every repository the App's installations can see, by full name (the ConnectRepo picker).

StatusMeansBody
200Donearray of Repo
503GitHub App not configured

GET /api/v1/projects/{slug}/builds

Newest first, for one environment (default production), optionally one service.

ParameterInTypeAbout
slugpathstring
environment (optional)querystring or nullDefault production.
service (optional)querystring or null
limit (optional)queryinteger or null1 to 500, default 50.
StatusMeansBody
200Donearray of BuildResponse
404No such project or environment

POST /api/v1/projects/{slug}/builds

Queue a manual build of a service from the head of a branch: the spec's ref, else the environment's branch, else the source's default branch.

ParameterInTypeAbout
slugpathstring
environment (optional)querystring or nullDefault production.
service (optional)querystring or null
limit (optional)queryinteger or null1 to 500, default 50.

Body: CreateBuildRequest

StatusMeansBody
201CreatedBuildResponse
404No such project, environment, or branch
409App not installed on the owner
422Unknown service, or a service without a source
503GitHub App not configured

GET /api/v1/projects/{slug}/builds/{id}

One build with its latest deployment, its step timings and the GitHub ids.

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
200DoneBuildDetailResponse
404No such project or build

POST /api/v1/projects/{slug}/builds/{id}/cancel

Cancel a queued build (200, now cancelled) or a running one (202, it stops at its next step boundary and then reads cancelled).

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
200Was queued, now cancelledBuildResponse
202Running, stops at its next step boundaryBuildResponse
404No such project or build
409Already finished, or its rollout has started

GET /api/v1/projects/{slug}/builds/{id}/log

The log lines after after (default the start), at most limit (default 500, max 5000); live while the build still runs.

ParameterInTypeAbout
slugpathstring
idpathinteger
after (optional)queryinteger or nullLines after this sequence number; default the start.
limit (optional)queryinteger or null1 to 5000, default 500.
StatusMeansBody
200DoneLogResponse
404No such project or build

POST /api/v1/projects/{slug}/builds/{id}/retry

A fresh queued build of the same commit and service (trigger retry), of the same kind: a publish run's retry resumes it, skipping what already published.

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
201CreatedBuildResponse
404No such project or build

GET /api/v1/projects/{slug}/deployments

The timeline of one environment (default production), optionally one service, newest first.

ParameterInTypeAbout
slugpathstring
environment (optional)querystring or nullDefault production.
service (optional)querystring or null
limit (optional)queryinteger or null1 to 500, default 50.
StatusMeansBody
200Donearray of TimelineRow
404No such project or environment

POST /api/v1/projects/{slug}/resources/service/{name}/deploy

Roll the service to a digest, given directly or as the image a build pushed. Refused unsigned (422) and while a build of the service is between deploying and its verdict (409).

ParameterInTypeAbout
slugpathstring
namepathstring
environment (optional)querystring or nullDefault production.
service (optional)querystring or null
limit (optional)queryinteger or null1 to 500, default 50.

Body: DeployRequest

StatusMeansBody
201CreatedDeploymentResponse
404No such project, environment, service or build
409A rollout is in flight, or the registry is not configured
422Not signed by the ops key, no digest, or a build without an image

POST /api/v1/projects/{slug}/resources/service/{name}/rollback

Roll the service back: to digest, else to the newest healthy digest that is not the current one. The body is optional.

ParameterInTypeAbout
slugpathstring
namepathstring
environment (optional)querystring or nullDefault production.
service (optional)querystring or null
limit (optional)queryinteger or null1 to 500, default 50.

Body: RollbackRequest

StatusMeansBody
201CreatedDeploymentResponse
404No such project, environment or service, or nothing to roll back to
409A rollout is in flight
422The digest is not signed by the ops key

GET /api/v1/projects/{slug}/sources

The project's repositories, by repo, each with the services bound to it.

ParameterInTypeAbout
slugpathstring
StatusMeansBody
200Donearray of SourceResponse
404No such project

POST /api/v1/projects/{slug}/sources

Connect a repository. The installation is the one the App has on the repo's owner unless given; the default branch is what GitHub reports for the repo.

ParameterInTypeAbout
slugpathstring

Body: CreateSourceRequest

StatusMeansBody
201CreatedSourceResponse
404No such project
409Repository already connected, project archived, or App not installed on the owner
422Not an owner/repo
503GitHub App not configured

GET /api/v1/projects/{slug}/sources/saves/{id}

One save: its verdict, its pull request, and what the evaluator printed.

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
200DoneSaveResponse
404No such project or save

POST /api/v1/projects/{slug}/sources/saves/{id}/merge

Merge the save's pull request. Only an open save merges; GitHub's refusal (a conflict, a required check not green, a repository that allows squash only) is a 409 carrying GitHub's reason.

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
200DoneSaveResponse
404No such project or save
409Not an open pull request, or GitHub refuses the merge
503GitHub App not configured

POST /api/v1/projects/{slug}/sources/scan

What a repository deploys. Any other repository is scanned inline as it always was: every Dockerfile, its exposed port and healthcheck, plus a release entry per migrate or release stage. Reads through the project's source when the repo is connected, else through the installation on the repo's owner.

ParameterInTypeAbout
slugpathstring

Body: ScanSourceRequest

StatusMeansBody
200Guessed from the Dockerfilesarray of DetectedService
202The repository declares itself; poll the scanScanQueuedResponse
404No such project, or GitHub knows no such repo or ref
409App not installed on the owner
422Not an owner/repo
503GitHub App not configured

GET /api/v1/projects/{slug}/sources/scans/{id}

One scan: its verdict, the declaration it produced, and the evaluator's output.

ParameterInTypeAbout
slugpathstring
idpathinteger
StatusMeansBody
200DoneScanResponse
404No such project or scan

DELETE /api/v1/projects/{slug}/sources/{id}

Disconnect a repository. Builds keep their history; a Service that still builds from the repo blocks the disconnect.

ParameterInTypeAbout
slugpathstring
idpathstring (uuid)
StatusMeansBody
204Done, with no body
404No such project or source
409A Service still builds from the repository

GET /api/v1/projects/{slug}/sources/{id}/file

One file's text (or a binary's base64) and blob sha at a ref, through the App.

ParameterInTypeAbout
slugpathstring
idpathstring (uuid)
path (optional)querystring
ref (optional)querystringBranch, tag or sha; default the source's default branch.
StatusMeansBody
200DoneStudioFileResponse
404No such project, source or ref
409Source not installed
413Text over 1 MiB, or any file over 5 MiB
422Not a repository path, or a directory
503GitHub App not configured

GET /api/v1/projects/{slug}/sources/{id}/saves

A source's saves, newest first (the last 20).

ParameterInTypeAbout
slugpathstring
idpathstring (uuid)
StatusMeansBody
200Donearray of SaveResponse
404No such project or source

POST /api/v1/projects/{slug}/sources/{id}/saves

Poll GET …/sources/saves/{id}.

ParameterInTypeAbout
slugpathstring
idpathstring (uuid)

Body: CreateSaveRequest

StatusMeansBody
202Accepted, and carried on in the backgroundSaveQueuedResponse
404No such project or source
409Source not installed, or project archived
422No message, a path that is not the repository's, a path twice, text and base64 both or base64 that is not, more than 200 changes, 8 MiB of content or 5 MiB in one binary file

GET /api/v1/projects/{slug}/sources/{id}/tree

The whole tree at a ref, and the refs the studio offers.

ParameterInTypeAbout
slugpathstring
idpathstring (uuid)
ref (optional)querystringBranch, tag or sha; default the source's default branch.
StatusMeansBody
200DoneStudioTree
404No such project, source or ref
409Source not installed
503GitHub App not configured

GET /api/v1/signing/public-key

The ops cosign public key as PEM, for out of band cosign verify --key.

StatusMeansBody
200PEMtext/plain bytes
404Image signing not configured

Types

GitHubAppResponse

FieldTypeAbout
html_urlstring
install_urlstring<html_url>/installations/new, where a person installs it on an owner.
installationsintegerHow many owners the App is installed on right now.
slugstring

Repo

FieldTypeAbout
default_branchstring
full_namestringowner/repo.
privateboolean

BuildResponse

FieldTypeAbout
authorstringThe commit author's GitHub login.
branch (optional)string or null
cache_hit (optional)number or null0 to 1, from the build's progress lines.
commit_shastring
environmentstring
error (optional)string or null
failure_kind (optional)string or nullchecks, build, memory (killed for memory), scan, push, sign, deploy, health, publish or internal.
finished_at (optional)string or null
github_check_run_id (optional)integer or null
idinteger
image_digest (optional)string or null
image_ref (optional)string or null
image_size_bytes (optional)integer or null
kindstringimage, a service's image build, or publish, a tag's packages published (steps clone, plan, crates, layers, locales).
messagestringFirst line of the commit message.
projectstring
queued_atstring
repostring
requested_bystringgithub for a push, the operator email otherwise.
servicestring
source_id (optional)string (uuid) or null
started_at (optional)string or null
statusstringqueued, cloning, checks, building, scanning, pushing, signing, deploying, publishing, healthy, published, failed, rolled_back or cancelled.
step_timingsarray of object[{step, started_at, finished_at?, ok?, note?}] in run order.
triggerstringpush, manual or retry.

CreateBuildRequest

FieldTypeAbout
ref (optional)string or nullThe branch to build the head of; default the spec's ref, else the environment's branch, else the source's default branch.
servicestring

BuildDetailResponse

FieldTypeAbout
buildBuildResponse
deployment (optional)null or DeploymentResponse
githubGithubIds
timingsarray of objectbuild.step_timings, the timeline's own copy.

LogResponse

FieldTypeAbout
linesarray of LogLineResponse
livebooleanThe build is still running: poll again.
nextintegerPass as after for the next page: the last sequence returned, or the after given when there was nothing new.

TimelineRow

One line of the Deployments page: a build with its latest deployment, or a deployment without a build (a digest deployed by hand).

FieldTypeAbout
atstring
authorstring
build (optional)null or BuildSummary
commitstringThe commit sha; the digest for a hand deployed image without one.
deployment (optional)null or DeploymentSummary
failure_kind (optional)string or nullThe timeline chip: checks, build, scan, push, sign, deploy, health or internal.
messagestring
servicestring
statestringqueued, building, checks, scanning, pushing, signing, deploying, healthy, unhealthy, rolling_back, rolled_back, failed, refused or cancelled.
state_textstring

DeployRequest

{digest} or {build_id}: the manifest digest to roll to, or the build whose pushed image it is.

FieldTypeAbout
build_id (optional)integer or null
digest (optional)string or null

DeploymentResponse

FieldTypeAbout
authorstring
build_id (optional)integer or null
commit_sha (optional)string or null
created_atstring
created_bystring
environmentstring
finished_at (optional)string or null
github_deployment_id (optional)integer or null
github_status_id (optional)integer or null
idinteger
image_digeststring
messagestring
previous_digest (optional)string or null
projectstring
rolloutstring
rollout_note (optional)string or null
servicestring
triggerstring

RollbackRequest

FieldTypeAbout
digest (optional)string or nullThe digest to return to; default the newest healthy one before the current.

SourceResponse

FieldTypeAbout
connected_atstring
declared (optional)null or DeclaredNames
default_branchstring
idstring (uuid)
installation_idintegerThe App installation the repo is reached through; 0 until installed.
last_event_at (optional)string or nullWhen the last webhook delivery for this repo arrived; null = never.
repostringGitHub owner/repo.
servicesarray of string

CreateSourceRequest

FieldTypeAbout
installation_id (optional)integer or nullResolved from the App's installations by the repo's owner when absent.
repostring

SaveResponse

FieldTypeAbout
branch (optional)string or null
commit_sha (optional)string or null
created_atstring
error (optional)string or null
filesarray of SaveFileResponseWhat the save changes, by path.
finished_at (optional)string or null
idinteger
logstringWhat the evaluator printed.
merge_sha (optional)string or null
merged_at (optional)string or null
merged_by (optional)string or null
messagestring
pull_number (optional)integer or null
pull_url (optional)string or null
ref (optional)string or nullThe branch the edit was made on; null = the default branch.
repostring
requested_bystring
scan_id (optional)integer or nullThe scan the merge queued of the default branch.
source_id (optional)string (uuid) or null
statusstringqueued, running, open (the pull request exists), merged, closed (on GitHub, unmerged) or failed.

ScanSourceRequest

FieldTypeAbout
ref (optional)string or nullBranch, tag or sha; default the repo's default branch.
repostringGitHub owner/repo; a connected source of the project, or any repo an installation can see.

DetectedService

FieldTypeAbout
args (optional)map of stringBuild arguments; a declaration carries them, a Dockerfile scan cannot know them.
contextstringThe build context, relative to the repository root.
dockerfilestring
healthcheck (optional)string or nullThe path a HEALTHCHECK probes, when it names a URL.
kindstringservice (long running) or release (a migrate/release stage).
namestring
port (optional)integer or nullThe last EXPOSEd port.
target (optional)string or nullA named stage to build (--target); null = the final stage.
volumes (optional)array of DeclaredVolume

ScanQueuedResponse

What POST /sources/scan answers for a repository that declares itself: the scan to poll.

FieldTypeAbout
scan_idinteger
statusstringqueued.

ScanResponse

FieldTypeAbout
error (optional)string or null
git_refstring
hooksanyEvent → the steps it fires.
idinteger
logstringWhat the evaluator printed.
reconciled (optional)null or Reconciled
repostring
servicesarray of DetectedServiceThe declared services, in the shape the Dockerfile scan has always answered.
statusstringqueued, running, succeeded or failed.
stepsarray of DeclaredStepResponse

StudioFileResponse

FieldTypeAbout
base64 (optional)string or nullA binary file's content, base64 (standard alphabet, padded); null for text and for a missing file. A binary over 5 MiB answers 413 instead.
binarybooleanA NUL byte or invalid UTF-8 in the first 8 KiB, or anywhere: the editor shows it read only, text is empty and base64 holds the content.
existsbooleanFalse: no file at the path on the ref (a new file saves with base_sha null).
html_urlstringhttps://github.com/<repo>/blob/<ref>/<path>, for the link beside a field the file owns.
pathstring
refstring
shastringThe blob sha, sent back with a save so a file changed since is refused; empty when the file is missing.
textstringEmpty when the file is missing or binary.

CreateSaveRequest

FieldTypeAbout
changesarray of SaveChange1 to 200 changes, 8 MiB of content at most (text and decoded bytes together), 5 MiB per binary file, each path once.
messagestringThe commit message and the pull request's title; required.
ref (optional)string or nullThe branch the editor opened the files at; default the default branch. The changes are checked and evaluated over this branch's head and the commit's parent is that head, so a save on an open save's ops/studio-<n> carries that save's change with it.

SaveQueuedResponse

FieldTypeAbout
save_idinteger
statusstringqueued.

StudioTree

FieldTypeAbout
default_branchstring
entriesarray of StudioTreeEntryEvery file and directory, in GitHub's order. A submodule is left out: its files are another repository's.
refstringThe ref the tree was read at.
refsarray of StudioRefThe refs a file opens at and a save builds on: the default branch first, then each open save's branch, newest first.
shastringThe commit the ref names.
truncatedbooleanGitHub cut the recursive listing short (past 100 000 entries): entries is a prefix of the tree, and a save of a path it does not list is refused.

GithubIds

The ids GitHub handed back for this build: its check run, and the deployment and status of its latest rollout.

FieldTypeAbout
check_run_id (optional)integer or null
deployment_id (optional)integer or null
status_id (optional)integer or null

LogLineResponse

FieldTypeAbout
atstring
levelstringinfo, warn or error.
linestring
seqinteger
stepstring

BuildSummary

FieldTypeAbout
branch (optional)string or null
cache_hit (optional)number or null
error (optional)string or null
finished_at (optional)string or null
idinteger
image_digest (optional)string or null
kindstringimage or publish.
queued_atstring
requested_bystring
statusstring
triggerstring

DeploymentSummary

FieldTypeAbout
created_atstring
created_bystring
finished_at (optional)string or null
idinteger
image_digeststring
previous_digest (optional)string or null
rolloutstring
rollout_note (optional)string or null
triggerstring

DeclaredNames

FieldTypeAbout
domainsmap of array of stringEnvironment → the domains the file gives a hostname there ("" as above).
hooksmap of array of stringEvent → the steps it fires.
operationalmap of map of array of stringEnvironment → service → the operational keys (replicas, limits, env_group, address) the file SETS there, each locked in that environment's form. "" is every environment without a $<name> block.
servicesarray of string
stepsarray of string

SaveFileResponse

FieldTypeAbout
actionSaveAction
pathstring

DeclaredVolume

FieldTypeAbout
databasestring
path (optional)string

DeclaredStepResponse

FieldTypeAbout
namestring
specany

Reconciled

FieldTypeAbout
createdarray of ReconciledRow
refusedarray of ReconciledRowWrites a type refused, each with its reason.
undeclaredarray of ReconciledRowRows this repository's file no longer declares: left in place, never destroyed.
updatedarray of ReconciledRow

SaveChange

FieldTypeAbout
base64 (optional)string or nullThe new content of a binary file, base64 (standard alphabet, padded), in place of text: never both.
base_sha (optional)string or nullThe sha the file answered when the editor opened it; null for a new file.
moved_from (optional)string or nullFor the add of a move or rename: the path it was moved from, whose git mode the file keeps (a script stays executable). Null otherwise.
pathstringRepository relative: no leading /, no .., never under .git/.
text (optional)string or nullThe new text; null with base64 null deletes the file.

StudioRef

FieldTypeAbout
namestring
pull_number (optional)integer or null
save_id (optional)integer or nullThe open save whose branch this is; null for the default branch.

StudioTreeEntry

FieldTypeAbout
pathstring
shastringThe blob or tree sha: a file's is what a save sends back as base_sha.
size (optional)integer or nullBytes, for a file; null for a directory.
typeStudioEntryType

SaveAction

What a change does to its file, in the words the console lists it with.

One of: "add" or "modify" or "delete".

ReconciledRow

FieldTypeAbout
environment (optional)string or nullnull for a step (project scoped).
kindstringservice, domain, step or docs-reader.
namestring
reason (optional)string or null

StudioEntryType

One of: "blob" or "tree".