Services
Web services, private services, workers and cron jobs. A service is defined once per project and has an instance in each environment.
| Operation | Method and path |
|---|---|
| List services (project-level definitions) | GET /v1/projects/{project}/services |
| Create a service | POST /v1/projects/{project}/services |
| Get a service’s base settings | GET /v1/projects/{project}/services/{service} |
| Update a service’s base settings | PATCH /v1/projects/{project}/services/{service} |
| Delete a service from every environment | DELETE /v1/projects/{project}/services/{service} |
| Services as they run in an environment | GET /v1/projects/{project}/environments/{environment}/services |
| A service in one environment (effective settings, status, URLs) | GET /v1/projects/{project}/environments/{environment}/services/{service} |
| Set this environment’s overrides for a service | PATCH /v1/projects/{project}/environments/{environment}/services/{service} |
| Restart the running deployment | POST /v1/projects/{project}/environments/{environment}/services/{service}/restart |
List services (project-level definitions)
Section titled “List services (project-level definitions)”GET /v1/projects/{project}/services- Operation:
listServices - 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). |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
A page of Service objects. | ServiceList |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/services \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "data": [ { "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "web", "kind": "web", "managed_by_manifest": true, "source": { "kind": "git", "repo": "primecarers/platform", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ] }, "build": { "builder": "railpack" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "timeout_seconds": 10 }, "resources": { "cpu": 2, "memory_mb": 2048 }, "replicas": { "min": 2, "max": 6, "scale_on": { "cpu_percent": 70, "concurrency": 80 } }, "sleep_when_idle": false, "private": false, "cron": null, "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-23T10:00:00Z" } ], "next_cursor": "string", "has_more": false}Create a service
Section titled “Create a service”POST /v1/projects/{project}/servicesCreates the definition and an instance in every environment. Nothing runs until the first deployment.
- Operation:
createService - Scopes:
projects:write - 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): ServiceCreate
| Field | Type | Description |
|---|---|---|
name * |
string | |
source |
ServiceSource | |
build |
BuildSettings | |
start |
string or null | Start command. Detected when empty. |
pre_deploy |
string or null | Runs once per deployment in a separate VM before traffic moves; failure stops the rollout. |
port |
integer or null | |
healthcheck |
Healthcheck or any or null | |
resources |
ServiceResources | |
replicas |
Replicas | |
sleep_when_idle |
boolean | Scale to zero after 10 idle minutes; the first request wakes it in 1–3 s. |
private |
boolean | No public domain; reachable only on the environment’s private network. |
cron |
CronSettings or any or null | |
restart_policy |
object | |
deploy |
object | |
volumes |
array of VolumeMount |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Dry run. Nothing was changed; this is what would happen. | Plan |
201 Created |
Created. | Service |
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/services \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ]}'Example response
{ "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "web", "kind": "web", "managed_by_manifest": true, "source": { "kind": "git", "repo": "primecarers/platform", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ] }, "build": { "builder": "railpack" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "timeout_seconds": 10 }, "resources": { "cpu": 2, "memory_mb": 2048 }, "replicas": { "min": 2, "max": 6, "scale_on": { "cpu_percent": 70, "concurrency": 80 } }, "sleep_when_idle": false, "private": false, "cron": null, "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-23T10:00:00Z"}Get a service’s base settings
Section titled “Get a service’s base settings”GET /v1/projects/{project}/services/{service}- Operation:
getService - 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). |
service * |
path | string | Service id (svc_…) or name. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | Service |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/services/web \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "web", "kind": "web", "managed_by_manifest": true, "source": { "kind": "git", "repo": "primecarers/platform", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ] }, "build": { "builder": "railpack" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "timeout_seconds": 10 }, "resources": { "cpu": 2, "memory_mb": 2048 }, "replicas": { "min": 2, "max": 6, "scale_on": { "cpu_percent": 70, "concurrency": 80 } }, "sleep_when_idle": false, "private": false, "cron": null, "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-23T10:00:00Z"}Update a service’s base settings
Section titled “Update a service’s base settings”PATCH /v1/projects/{project}/services/{service}JSON Merge Patch. Changes apply on the next deployment of each environment. Projects managed by guv.yaml return a manifest_patch fix suggesting a PR instead, unless ?force=true.
- Operation:
updateService - Scopes:
projects:write - CLI:
guv services update - 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). |
service * |
path | string | Service id (svc_…) or name. |
force |
query | boolean | Edit even though the project is managed by guv.yaml (creates drift). |
Request body (application/json, required): ServiceConfig
| Field | Type | Description |
|---|---|---|
source |
ServiceSource | |
build |
BuildSettings | |
start |
string or null | Start command. Detected when empty. |
pre_deploy |
string or null | Runs once per deployment in a separate VM before traffic moves; failure stops the rollout. |
port |
integer or null | |
healthcheck |
Healthcheck or any or null | |
resources |
ServiceResources | |
replicas |
Replicas | |
sleep_when_idle |
boolean | Scale to zero after 10 idle minutes; the first request wakes it in 1–3 s. |
private |
boolean | No public domain; reachable only on the environment’s private network. |
cron |
CronSettings or any or null | |
restart_policy |
object | |
deploy |
object | |
volumes |
array of VolumeMount |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. |
Service |
Errors: 400, 401, 402, 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/services/web \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ]}'Example response
{ "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "name": "web", "kind": "web", "managed_by_manifest": true, "source": { "kind": "git", "repo": "primecarers/platform", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ] }, "build": { "builder": "railpack" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "timeout_seconds": 10 }, "resources": { "cpu": 2, "memory_mb": 2048 }, "replicas": { "min": 2, "max": 6, "scale_on": { "cpu_percent": 70, "concurrency": 80 } }, "sleep_when_idle": false, "private": false, "cron": null, "created_at": "2026-10-22T09:30:00Z", "updated_at": "2026-10-23T10:00:00Z"}Delete a service from every environment
Section titled “Delete a service from every environment”DELETE /v1/projects/{project}/services/{service}- Operation:
deleteService - 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). |
service * |
path | string | Service id (svc_…) 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/services/web \ -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" }}Services as they run in an environment
Section titled “Services as they run in an environment”GET /v1/projects/{project}/environments/{environment}/services- Operation:
listServiceInstances - 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). |
environment * |
path | string | Environment id (env_…) or name. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
A page of ServiceInstance objects. | ServiceInstanceList |
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/services \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "data": [ { "service_id": "string", "environment_id": "string", "name": "string", "kind": "web", "status": "no_deployment", "status_text": "Live. 2 of 2 copies healthy.", "effective": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": {} }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ {} ] }, "overrides": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": {} }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ {} ] }, "current_deployment": { "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "service_name": "web", "environment_name": "production", "status": "active", "status_text": "Live since 14:05", "trigger": { "kind": "git_push", "actor": { "type": "github", "id": "stewartwebb", "display": "stewartwebb pushed to main" } }, "source": { "kind": "git", "commit": { "sha": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", "branch": "main", "message": "Fix rota export", "author": "Stewart Webb" } }, "build_id": "bld_01jbx2m9k7q4r8t5v6w3y0z1bd", "image": { "digest": "sha256:4b1f0e9d8c7b6a5948372615f4e3d2c1b0a9f8e7d6c5b4a3928170f6e5d4c3b2", "signed": true }, "rollback_of": null, "operation_id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "url": "https://www.primecarers.co.uk", "failure": null, "created_at": "2026-10-23T14:02:00Z", "started_at": "2026-10-23T14:02:01Z", "active_at": "2026-10-23T14:05:12Z", "finished_at": "2026-10-23T14:05:12Z", "duration_ms": 191000 }, "urls": { "public": [ "https://web-primecarers-k7q4.guv.run", "https://www.primecarers.co.uk" ], "internal_host": "web.guv.internal" }, "replicas": { "desired": 1, "running": 1 }, "last_error": { "message": "string", "explanation_url": "string" }, "cost_today": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }, "updated_at": "2026-10-22T13:05:00Z" } ], "next_cursor": "string", "has_more": false}A service in one environment (effective settings, status, URLs)
Section titled “A service in one environment (effective settings, status, URLs)”GET /v1/projects/{project}/environments/{environment}/services/{service}- Operation:
getServiceInstance - 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. |
service * |
path | string | Service id (svc_…) or name. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | ServiceInstance |
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/services/web \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "service_id": "string", "environment_id": "string", "name": "string", "kind": "web", "status": "no_deployment", "status_text": "Live. 2 of 2 copies healthy.", "effective": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ] }, "overrides": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ] }, "current_deployment": { "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "service_name": "web", "environment_name": "production", "status": "active", "status_text": "Live since 14:05", "trigger": { "kind": "git_push", "actor": { "type": "github", "id": "stewartwebb", "display": "stewartwebb pushed to main" } }, "source": { "kind": "git", "commit": { "sha": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", "branch": "main", "message": "Fix rota export", "author": "Stewart Webb" } }, "build_id": "bld_01jbx2m9k7q4r8t5v6w3y0z1bd", "image": { "digest": "sha256:4b1f0e9d8c7b6a5948372615f4e3d2c1b0a9f8e7d6c5b4a3928170f6e5d4c3b2", "signed": true }, "rollback_of": null, "operation_id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "url": "https://www.primecarers.co.uk", "failure": null, "created_at": "2026-10-23T14:02:00Z", "started_at": "2026-10-23T14:02:01Z", "active_at": "2026-10-23T14:05:12Z", "finished_at": "2026-10-23T14:05:12Z", "duration_ms": 191000 }, "urls": { "public": [ "https://web-primecarers-k7q4.guv.run", "https://www.primecarers.co.uk" ], "internal_host": "web.guv.internal" }, "replicas": { "desired": 1, "running": 1 }, "last_error": { "message": "string", "explanation_url": "string" }, "cost_today": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }, "updated_at": "2026-10-22T13:05:00Z"}Set this environment’s overrides for a service
Section titled “Set this environment’s overrides for a service”PATCH /v1/projects/{project}/environments/{environment}/services/{service}- Operation:
updateServiceInstance - 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. |
service * |
path | string | Service id (svc_…) or name. |
Request body (application/json, required): ServiceInstanceUpdate
| Field | Type | Description |
|---|---|---|
overrides |
ServiceConfig |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. |
ServiceInstance |
Errors: 400, 401, 402, 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/services/web \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "overrides": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ] }}'Example response
{ "service_id": "string", "environment_id": "string", "name": "string", "kind": "web", "status": "no_deployment", "status_text": "Live. 2 of 2 copies healthy.", "effective": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ] }, "overrides": { "source": { "kind": "git", "repo": "string", "root": "apps/web", "watch": [ "apps/web/**", "packages/ui/**", "pnpm-lock.yaml" ], "image": "ghcr.io/acme/api:1.4.2", "registry_credentials_secret": "string" }, "build": { "builder": "railpack", "dockerfile": "services/api/Dockerfile", "context": "string" }, "start": "pnpm --filter web start", "pre_deploy": "pnpm --filter db migrate deploy", "port": 3000, "healthcheck": { "type": "http", "path": "/healthz", "port": 1, "timeout_seconds": 10, "interval_seconds": 10, "start_timeout_seconds": 300 }, "resources": { "cpu": 1, "memory_mb": 1024 }, "replicas": { "min": 1, "max": 1, "scale_on": { "cpu_percent": 10, "memory_percent": 10, "concurrency": 1 } }, "sleep_when_idle": false, "private": false, "cron": { "schedule": "0 2 * * *", "timezone": "Europe/London", "timeout_seconds": 1, "concurrency_policy": "forbid" }, "restart_policy": { "mode": "on_failure", "max_retries": 10 }, "deploy": { "overlap_seconds": 20, "auto_rollback": false }, "volumes": [ { "volume": "string", "mount_path": "/data" } ] }, "current_deployment": { "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "service_name": "web", "environment_name": "production", "status": "active", "status_text": "Live since 14:05", "trigger": { "kind": "git_push", "actor": { "type": "github", "id": "stewartwebb", "display": "stewartwebb pushed to main" } }, "source": { "kind": "git", "commit": { "sha": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", "branch": "main", "message": "Fix rota export", "author": "Stewart Webb" } }, "build_id": "bld_01jbx2m9k7q4r8t5v6w3y0z1bd", "image": { "digest": "sha256:4b1f0e9d8c7b6a5948372615f4e3d2c1b0a9f8e7d6c5b4a3928170f6e5d4c3b2", "signed": true }, "rollback_of": null, "operation_id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "url": "https://www.primecarers.co.uk", "failure": null, "created_at": "2026-10-23T14:02:00Z", "started_at": "2026-10-23T14:02:01Z", "active_at": "2026-10-23T14:05:12Z", "finished_at": "2026-10-23T14:05:12Z", "duration_ms": 191000 }, "urls": { "public": [ "https://web-primecarers-k7q4.guv.run", "https://www.primecarers.co.uk" ], "internal_host": "web.guv.internal" }, "replicas": { "desired": 1, "running": 1 }, "last_error": { "message": "string", "explanation_url": "string" }, "cost_today": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }, "updated_at": "2026-10-22T13:05:00Z"}Restart the running deployment
Section titled “Restart the running deployment”POST /v1/projects/{project}/environments/{environment}/services/{service}/restart- Operation:
restartService - Scopes:
deploy:{environment} - CLI:
guv restart - 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
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. |
service * |
path | string | Service id (svc_…) or name. |
Request body (application/json, required): ServiceRestart
| Field | Type | Description |
|---|---|---|
reason |
string |
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, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/projects/shopfront/environments/production/services/web/restart \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "reason": "string"}'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" }}