opsdocsConsole

Ops platform / HTTP API

Projects and environments

Create and read projects, their environments, previews and the events that happened in them, and promote one environment onto another.

Updated 13 Oct 2026View as Markdown

Create and read projects, their environments, previews and the events that happened in them, and promote one environment onto another.

GET /api/v1/catalog

The registered resource types: kind, scope and the spec schema each form is rendered from. Sorted by kind.

StatusMeansBody
200Donearray of CatalogEntry

GET /api/v1/projects

The caller's projects, live ones first, archived after; each by slug.

StatusMeansBody
200Donearray of ProjectResponse

POST /api/v1/projects

Create a project; its production environment comes with it (following branch, deploy mode auto).

Body: CreateProjectRequest

StatusMeansBody
201CreatedProjectResponse
409Slug exists
422Bad or reserved slug, empty display name, bad edge mode or retention

GET /api/v1/projects/{slug}

One project's settings, archived or not.

ParameterInTypeAbout
slugpathstring
StatusMeansBody
200DoneProjectResponse
404No such project

PUT /api/v1/projects/{slug}

Full replace of the editable fields; archived: true archives, false restores. An archived project refuses every write but a restore, which applies the fields and lifts the archive in one call (the audit reads update, then restore).

ParameterInTypeAbout
slugpathstring

Body: UpdateProjectRequest

StatusMeansBody
200DoneProjectResponse
404No such project
409Project is archived and the request keeps it so
422Bad field

DELETE /api/v1/projects/{slug}

Already archived is still 204.

ParameterInTypeAbout
slugpathstring
StatusMeansBody
204Done, with no body
404No such project

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

Production first, then by name, each with its figures.

ParameterInTypeAbout
slugpathstring
StatusMeansBody
200Donearray of EnvironmentResponse
404No such project

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

Add an environment. Kind production is refused (a project has exactly one, created with it) and so is preview (it comes from its pull request).

ParameterInTypeAbout
slugpathstring

Body: CreateEnvironmentRequest

StatusMeansBody
201CreatedEnvironmentResponse
404No such project
409Name exists, kind production or preview, or project archived
422Reserved or bad name, bad kind, deploy mode or quota

PATCH /api/v1/projects/{slug}/environments/{environment}

Replace an environment's branch, deploy mode and quota. A quota below what the environment's services already spend is refused with both figures: the operator scales the services down first.

ParameterInTypeAbout
slugpathstring
environmentpathstring

Body: UpdateEnvironmentRequest

StatusMeansBody
200DoneEnvironmentResponse
404No such project or environment
409Project archived, or the quota is below current usage
422Bad deploy mode or quota

DELETE /api/v1/projects/{slug}/environments/{environment}

Delete an environment and everything in it. The production environment stays with the project, and the environment's name has to be typed back.

ParameterInTypeAbout
slugpathstring
environmentpathstring
confirm (optional)querystring or null
StatusMeansBody
204Done, with no body
404No such project or environment
409Production, archived, unconfirmed, or a resource refused

GET /api/v1/projects/{slug}/environments/{environment}/promote

What promoting from into this environment would change.

ParameterInTypeAbout
slugpathstring
environmentpathstring
from (optional)querystring or null
StatusMeansBody
200DonePromotePlan
404No such project, environment or source environment
422from must name a different environment

POST /api/v1/projects/{slug}/environments/{environment}/promote

Deploy the source's digests into this environment. Always 200 once the guards pass: a service the deploy path refuses is one refused outcome, never the batch's status code.

ParameterInTypeAbout
slugpathstring
environmentpathstring

Body: PromoteRequest

StatusMeansBody
200DonePromoteResult
404No such project, environment or source environment
409Project archived
422from must name a different environment

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

Everything that changed in the project and its resources, newest first. Narrow it by resource type and name.

ParameterInTypeAbout
slugpathstring
limit (optional)queryinteger or null1 to 500, default 100.
type (optional)querystring or nullNarrow to one resource type (project and environment for the registry).
name (optional)querystring or null
StatusMeansBody
200Donearray of EventResponse
404No such project

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

The project's live previews, by pull request number.

ParameterInTypeAbout
slugpathstring
StatusMeansBody
200Donearray of PreviewResponse
404No such project

PATCH /api/v1/projects/{slug}/previews

Replace both preview figures.

ParameterInTypeAbout
slugpathstring

Body: UpdatePreviewSettingsRequest

StatusMeansBody
200DonePreviewSettings
404No such project
409Project archived
422Limit or TTL out of range

DELETE /api/v1/projects/{slug}/previews/{number}

Tear one preview down by hand, before its pull request closes and before its TTL runs out.

ParameterInTypeAbout
slugpathstring
numberpathinteger
StatusMeansBody
204Done, with no body
404No such project or preview
409A resource stopped the cascade

Types

CatalogEntry

One catalog line: the kind, where its instances live, and the spec schema the console renders the form from.

FieldTypeAbout
kindstring
schemaany
scopeScope

ProjectResponse

FieldTypeAbout
archived_at (optional)string or null
created_atstring
display_namestring
obs_retention_daysinteger
preview_limitintegerHow many previews this project may hold open at once (0 switches them off). Read only here: PATCH /previews writes it.
preview_ttl_daysintegerHow many days a preview lives after its last push. Read only here.
signing_identity (optional)string or nullThe cosign certificate identity regexp deploys verify against.
slugstring
source_repo (optional)string or null
updated_atstring

CreateProjectRequest

FieldTypeAbout
branch (optional)stringThe branch the production environment follows (default main).
display_namestring
obs_retention_days (optional)integer1 to 400, default 14.
signing_identity (optional)string or null
slugstring^[a-z0-9][a-z0-9-]{0,62}$.
source_repo (optional)string or null

UpdateProjectRequest

Full replace of the editable fields; archived flips the archive state.

FieldTypeAbout
archived (optional)boolean
display_namestring
obs_retention_daysinteger
signing_identity (optional)string or null
source_repo (optional)string or null

EnvironmentResponse

FieldTypeAbout
branch (optional)string or nullThe branch this environment follows; null = promote only.
created_atstring
deploy_modestringauto or manual.
kindstringproduction, staging, development or preview.
latest_build_id (optional)integer or nullThe newest build of the environment; null before the first.
namestring
overlaystringThe encrypted overlay this environment's services join.
projectstring
quotaQuota
servicesinteger
updated_atstring
usageUsage
worst_state (optional)null or StatusState

CreateEnvironmentRequest

FieldTypeAbout
branch (optional)string or null
deploy_mode (optional)stringauto or manual (default).
kindstringstaging, development or preview (production comes with the project).
namestring^[a-z0-9][a-z0-9-]{0,62}$.
quota (optional)null or Quota

UpdateEnvironmentRequest

Full replace of the editable fields, as UpdateProjectRequest is for a project. name and kind are immutable; branch: null means promote only.

FieldTypeAbout
branch (optional)string or null
deploy_modestring
quotaQuota

PromotePlan

FieldTypeAbout
changingintegerHow many of services have will_change.
fromstring
servicesarray of PromoteService
tostring

PromoteRequest

FieldTypeAbout
fromstringThe environment the digests come from.

PromoteResult

FieldTypeAbout
deployedinteger
fromstring
refusedinteger
servicesarray of PromoteOutcome
skippedinteger
tostring

EventResponse

FieldTypeAbout
actionstringcreate, update, delete, archive or restore.
actorstringOperator email, api-token for the static bearer, migration for seeds.
atstring
diffany{"before": ..., "after": ...}.
environment (optional)string or null
idinteger
namestring
typestring

PreviewResponse

FieldTypeAbout
base_refstringThe branch the pull request targets: the specs are cloned from the environment that follows it.
created_atstring
database (optional)string or nullsample_pr48; null when the base environment kept no template.
environmentstringpreview-48, always preview- + number.
expires_at (optional)string or null
head_refstring
head_shastring
hostname (optional)string or null
last_push_atstring
latest_build_id (optional)integer or nullThe newest build of the preview environment; null before the first.
numberinteger
projectstring
reason (optional)string or null
repostring
statestringcreating, ready, failed, refused, tearing_down or torn_down.
titlestring
updated_atstring
worst_state (optional)null or StatusState

UpdatePreviewSettingsRequest

A full replace of both figures, as every other write in this area is.

FieldTypeAbout
preview_limitinteger
preview_ttl_daysinteger

PreviewSettings

What the Quota section seeds its two fields from, and what the PATCH answers with. ProjectResponse carries the same pair read only, so the page needs no second GET.

FieldTypeAbout
preview_limitintegerHow many previews a project may hold at once; 0 switches previews off.
preview_ttl_daysintegerDays after the LAST PUSH, never after creation, so an actively reviewed pull request does not lose its preview mid review.

Scope

One of: "environment" or "project".

Quota

What an environment may spend.

FieldTypeAbout
cpunumber
memory_mbinteger

StatusState

One of: "ready" or "pending" or "error".

Usage

What the environment's services already spend, and how many there are.

FieldTypeAbout
cpunumber
memory_mbinteger
servicesinteger

PromoteService

FieldTypeAbout
build_id (optional)integer or null
commit_sha (optional)string or nullThe source deployment's commit, for the console's line.
servicestring
skip_reason (optional)string or nullWhy it will not change; null when it will.
source_digest (optional)string or nullThe source's current digest; null when the source never deployed it.
source_rollout (optional)string or nullThe source deployment's rollout: rolling, healthy, unhealthy, rolled_back or failed. Null when the source never deployed it.
target_digest (optional)string or nullWhat the target runs today; null before its first deployment.
will_changeboolean

PromoteOutcome

FieldTypeAbout
deployment_id (optional)integer or null
digest (optional)string or nullThe digest that was deployed, or would have been.
outcomestringdeployed, skipped or refused.
reason (optional)string or nullWhy it was skipped or refused; null for deployed.
servicestring