Environments
Isolated copies of a project (production, staging, previews) with their own network, variables and secrets.
| Operation | Method and path |
|---|---|
| List environments | GET /v1/projects/{project}/environments |
| Create an environment | POST /v1/projects/{project}/environments |
| Get an environment | GET /v1/projects/{project}/environments/{environment} |
| Update an environment (including protection) | PATCH /v1/projects/{project}/environments/{environment} |
| Delete an environment | DELETE /v1/projects/{project}/environments/{environment} |
List environments
Section titled “List environments”GET /v1/projects/{project}/environments- Operation:
listEnvironments - Scopes:
projects:read - Paginated:
?limit=and?cursor=
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
kind |
query | production, staging, preview, development |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
A page of Environment objects. | EnvironmentList |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/environments \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "data": [ { "id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "production", "kind": "production", "branch": "main", "pull_requests": false, "pull_request": null, "parent_environment_id": null, "ttl": null, "expires_at": null, "protection": { "require_approval": true, "approver_roles": [ "owner", "admin" ], "allowed_branches": [ "main" ] }, "databases_mode": "new", "spend_cap": null, "status": "active", "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-22T09:30:00Z" } ], "next_cursor": "string", "has_more": false}Create an environment
Section titled “Create an environment”POST /v1/projects/{project}/environmentsProvisions an isolated private network and, per databases_mode, databases. Returns an operation.
- Operation:
createEnvironment - Scopes:
projects:write - CLI:
guv env create - Idempotency-Key: required; supports
?dry_run=true
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
Request body (application/json, required): EnvironmentCreate
| Field | Type | Description |
|---|---|---|
name * |
string | |
kind |
production, staging, preview, development |
|
branch |
string | |
clone_from |
string | Environment to copy services, plain variables and settings from. Secrets are not copied. |
pull_requests |
boolean | |
ttl |
string | |
protection |
EnvironmentProtection | |
databases_mode |
new, branch, branch-masked |
|
spend_cap |
Money |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Dry run. Nothing was changed; this is what would happen. | Plan |
202 Accepted |
Accepted. The work continues in the background; follow the operation. | Operation |
Errors: 400, 401, 402, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/projects/shopfront/environments \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "kind": "production", "branch": "string", "clone_from": "string", "pull_requests": false, "ttl": "string", "protection": { "require_approval": false, "approver_roles": [ "owner", "admin" ], "allowed_branches": [ "string" ] }, "databases_mode": "new", "spend_cap": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }}'Example response
{ "id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "kind": "deployment.create", "status": "running", "summary": "Deploying web to production", "workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "resource": { "type": "deployment", "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "url": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }, "progress": { "current_step": "build", "completed_steps": 1, "total_steps": 6, "percent": 20 }, "steps": [ { "name": "resolve", "title": "Reading your settings", "status": "succeeded", "attempt": 1, "started_at": "2026-10-23T14:02:00Z", "finished_at": "2026-10-23T14:02:01Z" }, { "name": "build", "title": "Building your app", "status": "running", "attempt": 1, "started_at": "2026-10-23T14:02:01Z", "finished_at": null } ], "created_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "created_at": "2026-10-23T14:02:00Z", "links": { "self": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op", "events": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op/events", "resource": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }}Get an environment
Section titled “Get an environment”GET /v1/projects/{project}/environments/{environment}- Operation:
getEnvironment - Scopes:
projects:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
environment * |
path | string | Environment id (env_…) or name. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | Environment |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/environments/production \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "production", "kind": "production", "branch": "main", "pull_requests": false, "pull_request": null, "parent_environment_id": null, "ttl": null, "expires_at": null, "protection": { "require_approval": true, "approver_roles": [ "owner", "admin" ], "allowed_branches": [ "main" ] }, "databases_mode": "new", "spend_cap": null, "status": "active", "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-22T09:30:00Z"}Update an environment (including protection)
Section titled “Update an environment (including protection)”PATCH /v1/projects/{project}/environments/{environment}Weakening protection on production always needs a human.
- Operation:
updateEnvironment - Scopes:
projects:write - Approval: In environments with protection turned on (usually production), changes by agents and by roles outside
approver_rolesreturnapproval_required. - Idempotency-Key: required; supports
?dry_run=true - Concurrency: send the
ETagyou read asIf-Match
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
environment * |
path | string | Environment id (env_…) or name. |
Request body (application/json, required): EnvironmentUpdate
| Field | Type | Description |
|---|---|---|
name |
string | |
branch |
string or null | |
pull_requests |
boolean | |
ttl |
string or null | |
protection |
EnvironmentProtection | |
databases_mode |
new, branch, branch-masked |
|
spend_cap |
Money or any or null |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. |
Environment |
Errors: 400, 401, 403, 404, 409, 412, 422, 429, 500, as problem+json with a stable code.
Example
curl -X PATCH https://api.guv.dev/v1/projects/shopfront/environments/production \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "branch": "string", "pull_requests": false, "ttl": "string", "protection": { "require_approval": false, "approver_roles": [ "owner", "admin" ], "allowed_branches": [ "string" ] }, "databases_mode": "new", "spend_cap": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }}'Example response
{ "id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "production", "kind": "production", "branch": "main", "pull_requests": false, "pull_request": null, "parent_environment_id": null, "ttl": null, "expires_at": null, "protection": { "require_approval": true, "approver_roles": [ "owner", "admin" ], "allowed_branches": [ "main" ] }, "databases_mode": "new", "spend_cap": null, "status": "active", "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-22T09:30:00Z"}Delete an environment
Section titled “Delete an environment”DELETE /v1/projects/{project}/environments/{environment}Requires confirm=<name>. Databases and volumes are soft-deleted for 7 days. Agents need approval except for preview environments they created.
- Operation:
deleteEnvironment - Scopes:
projects:delete - Approval: Always needs a human approval with a passkey, whoever asks, including agents with full scopes.
- Idempotency-Key: required; supports
?dry_run=true - Concurrency: send the
ETagyou read asIf-Match
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
environment * |
path | string | Environment id (env_…) or name. |
confirm |
query | string | Typed confirmation for destructive actions. Must equal the resource name (or slug/hostname). Missing or wrong values return confirmation_required. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Dry run. Nothing was changed; this is what would happen. | Plan |
202 Accepted |
Accepted. The work continues in the background; follow the operation. | Operation |
Errors: 400, 401, 403, 404, 409, 412, 422, 429, 500, as problem+json with a stable code.
Example
curl -X DELETE https://api.guv.dev/v1/projects/shopfront/environments/production \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)"Example response
{ "id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "kind": "deployment.create", "status": "running", "summary": "Deploying web to production", "workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "resource": { "type": "deployment", "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "url": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }, "progress": { "current_step": "build", "completed_steps": 1, "total_steps": 6, "percent": 20 }, "steps": [ { "name": "resolve", "title": "Reading your settings", "status": "succeeded", "attempt": 1, "started_at": "2026-10-23T14:02:00Z", "finished_at": "2026-10-23T14:02:01Z" }, { "name": "build", "title": "Building your app", "status": "running", "attempt": 1, "started_at": "2026-10-23T14:02:01Z", "finished_at": null } ], "created_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "created_at": "2026-10-23T14:02:00Z", "links": { "self": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op", "events": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op/events", "resource": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }}