Skip to content

Workspaces

View as Markdown

Workspaces own billing, members, projects and agent tokens.

Operation Method and path
List workspaces I belong to GET /v1/workspaces
Create a workspace POST /v1/workspaces
Get a workspace GET /v1/workspaces/{workspace}
Update a workspace PATCH /v1/workspaces/{workspace}
Close a workspace DELETE /v1/workspaces/{workspace}
GET /v1/workspaces
  • Operation: listWorkspaces
  • Scopes: workspaces:read
  • Paginated: ?limit= and ?cursor=

Responses

Status Meaning Body
200 OK A page of Workspace objects. WorkspaceList

Errors: 400, 401, 403, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl https://api.guv.dev/v1/workspaces \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"data": [
{
"id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"slug": "primecarers",
"name": "Primecarers",
"plan": "pro",
"status": "active",
"role": "owner",
"billing_email": "accounts@primecarers.co.uk",
"default_residency": "uk-only",
"require_passkeys": true,
"trial_ends_at": null,
"limits": {
"max_vcpu_per_service": 32,
"max_memory_mb_per_service": 65536,
"max_replicas": 20,
"max_custom_domains_per_service": 20,
"max_volume_gb": 250,
"log_retention_days": 30,
"concurrent_builds": 10
},
"member_count": 3,
"created_at": "2026-10-22T09:00:00Z",
"updated_at": "2026-10-22T09:00:00Z"
}
],
"next_cursor": "string",
"has_more": false
}
POST /v1/workspaces
  • Operation: createWorkspace
  • Scopes: any signed-in principal
  • Idempotency-Key: required; supports ?dry_run=true

Request body (application/json, required): WorkspaceCreate

Field Type Description
name * string
slug string
default_residency Residency

Responses

Status Meaning Body
200 OK Dry run. Nothing was changed; this is what would happen. Plan
201 Created Created. Workspace

Errors: 400, 401, 402, 403, 409, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"slug": "string",
"default_residency": "uk-only"
}'

Example response

{
"id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"slug": "primecarers",
"name": "Primecarers",
"plan": "pro",
"status": "active",
"role": "owner",
"billing_email": "accounts@primecarers.co.uk",
"default_residency": "uk-only",
"require_passkeys": true,
"trial_ends_at": null,
"limits": {
"max_vcpu_per_service": 32,
"max_memory_mb_per_service": 65536,
"max_replicas": 20,
"max_custom_domains_per_service": 20,
"max_volume_gb": 250,
"log_retention_days": 30,
"concurrent_builds": 10
},
"member_count": 3,
"created_at": "2026-10-22T09:00:00Z",
"updated_at": "2026-10-22T09:00:00Z"
}
GET /v1/workspaces/{workspace}
  • Operation: getWorkspace
  • Scopes: workspaces:read

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.

Responses

Status Meaning Body
200 OK OK. Workspace

Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl https://api.guv.dev/v1/workspaces/acme \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"slug": "primecarers",
"name": "Primecarers",
"plan": "pro",
"status": "active",
"role": "owner",
"billing_email": "accounts@primecarers.co.uk",
"default_residency": "uk-only",
"require_passkeys": true,
"trial_ends_at": null,
"limits": {
"max_vcpu_per_service": 32,
"max_memory_mb_per_service": 65536,
"max_replicas": 20,
"max_custom_domains_per_service": 20,
"max_volume_gb": 250,
"log_retention_days": 30,
"concurrent_builds": 10
},
"member_count": 3,
"created_at": "2026-10-22T09:00:00Z",
"updated_at": "2026-10-22T09:00:00Z"
}
PATCH /v1/workspaces/{workspace}
  • Operation: updateWorkspace
  • Scopes: workspaces:write
  • Idempotency-Key: required; supports ?dry_run=true
  • Concurrency: send the ETag you read as If-Match

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.

Request body (application/json, required): WorkspaceUpdate

Field Type Description
name string
slug string
billing_email string (email)
default_residency Residency
require_passkeys boolean

Responses

Status Meaning Body
200 OK OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. Workspace

Errors: 400, 401, 403, 404, 409, 412, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X PATCH https://api.guv.dev/v1/workspaces/acme \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"slug": "string",
"billing_email": "ada@example.co.uk",
"default_residency": "uk-only",
"require_passkeys": false
}'

Example response

{
"id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"slug": "primecarers",
"name": "Primecarers",
"plan": "pro",
"status": "active",
"role": "owner",
"billing_email": "accounts@primecarers.co.uk",
"default_residency": "uk-only",
"require_passkeys": true,
"trial_ends_at": null,
"limits": {
"max_vcpu_per_service": 32,
"max_memory_mb_per_service": 65536,
"max_replicas": 20,
"max_custom_domains_per_service": 20,
"max_volume_gb": 250,
"log_retention_days": 30,
"concurrent_builds": 10
},
"member_count": 3,
"created_at": "2026-10-22T09:00:00Z",
"updated_at": "2026-10-22T09:00:00Z"
}
DELETE /v1/workspaces/{workspace}

Requires confirm=<slug> and a workspace with no live projects. Data is kept for 30 days, then crypto-shredded.

  • Operation: deleteWorkspace
  • Scopes: any signed-in principal
  • 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 ETag you read as If-Match

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
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

Terminal window
curl -X DELETE https://api.guv.dev/v1/workspaces/acme \
-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"
}
}