Skip to content

Agent tokens

View as Markdown

First-class tokens for AI agents, with scopes, environments, a spend budget, expiry and an approval channel.

Operation Method and path
List agent tokens GET /v1/workspaces/{workspace}/agent-tokens
Create an agent token POST /v1/workspaces/{workspace}/agent-tokens
Get an agent token GET /v1/workspaces/{workspace}/agent-tokens/{token_id}
Change an agent token’s scopes, environments, budget or channel PATCH /v1/workspaces/{workspace}/agent-tokens/{token_id}
Revoke an agent token DELETE /v1/workspaces/{workspace}/agent-tokens/{token_id}
GET /v1/workspaces/{workspace}/agent-tokens
  • Operation: listAgentTokens
  • Scopes: tokens:read
  • Paginated: ?limit= and ?cursor=

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
status query active, expired, revoked

Responses

Status Meaning Body
200 OK A page of AgentToken objects. AgentTokenList

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/agent-tokens \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"data": [
{
"id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk",
"workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"name": "claude-code-on-stewart-laptop",
"description": "Claude Code on Stewart's MacBook",
"prefix": "guv_agt_Qm4x",
"scopes": [
"projects:read",
"deploy:preview",
"deploy:staging",
"logs:read",
"secrets:write-only",
"db:branch"
],
"projects": null,
"environments": [
"preview",
"staging"
],
"budget": {
"spend_increase_per_day": {
"amount": "10.00",
"currency": "GBP",
"display": "£10.00"
}
},
"approval_channel": [
"push",
"email"
],
"status": "active",
"summary": [
"Can deploy to staging and previews.",
"Cannot touch production without your approval.",
"Can set secrets but never read them.",
"Can raise spend by up to £10.00 a day."
],
"created_by": {
"type": "user",
"id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us",
"display": "Stewart Webb"
},
"expires_at": "2026-11-22T09:00:00Z",
"last_used_at": "2026-10-23T13:58:00Z",
"revoked_at": null,
"created_at": "2026-10-23T09:00:00Z"
}
],
"next_cursor": "string",
"has_more": false
}
POST /v1/workspaces/{workspace}/agent-tokens

Only humans can create agent tokens. The token value is returned once, with ready-made setup snippets.

  • Operation: createAgentToken
  • Scopes: tokens:write
  • CLI: guv tokens create-agent
  • Idempotency-Key: required; supports ?dry_run=true

Parameters

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

Request body (application/json, required): AgentTokenCreate

Field Type Description
name * string
description string
scopes * array of Scope
projects array of string or null
environments * array of string
budget AgentTokenBudget
expires_in string Lifetime, at most 365d. Default 30d.
approval_channel array of ApprovalChannel Default ["push","email"].

Responses

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

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

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces/acme/agent-tokens \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "claude-code-on-stewart-laptop",
"scopes": [
"projects:read",
"deploy:preview",
"deploy:staging",
"logs:read",
"secrets:write-only",
"db:branch"
],
"environments": [
"preview",
"staging"
],
"budget": {
"spend_increase_per_day": {
"amount": "10.00",
"currency": "GBP"
}
},
"expires_in": "30d",
"approval_channel": [
"push",
"email"
]
}'

Example response

{
"id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk",
"workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"name": "claude-code-on-stewart-laptop",
"description": "Claude Code on Stewart's MacBook",
"prefix": "guv_agt_Qm4x",
"scopes": [
"projects:read",
"deploy:preview",
"deploy:staging",
"logs:read",
"secrets:write-only",
"db:branch"
],
"projects": null,
"environments": [
"preview",
"staging"
],
"budget": {
"spend_increase_per_day": {
"amount": "10.00",
"currency": "GBP",
"display": "£10.00"
}
},
"approval_channel": [
"push",
"email"
],
"status": "active",
"summary": [
"Can deploy to staging and previews.",
"Cannot touch production without your approval.",
"Can set secrets but never read them.",
"Can raise spend by up to £10.00 a day."
],
"created_by": {
"type": "user",
"id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us",
"display": "Stewart Webb"
},
"expires_at": "2026-11-22T09:00:00Z",
"last_used_at": "2026-10-23T13:58:00Z",
"revoked_at": null,
"created_at": "2026-10-23T09:00:00Z",
"token": "string",
"setup": {
"env": "export GUV_TOKEN=guv_agt_…",
"mcp_command": "claude mcp add guv --transport http https://mcp.guv.dev --header 'Authorization: Bearer guv_agt_…'"
}
}
GET /v1/workspaces/{workspace}/agent-tokens/{token_id}
  • Operation: getAgentToken
  • Scopes: tokens:read

Parameters

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

Responses

Status Meaning Body
200 OK OK. AgentToken

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/agent-tokens/tok_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk",
"workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"name": "claude-code-on-stewart-laptop",
"description": "Claude Code on Stewart's MacBook",
"prefix": "guv_agt_Qm4x",
"scopes": [
"projects:read",
"deploy:preview",
"deploy:staging",
"logs:read",
"secrets:write-only",
"db:branch"
],
"projects": null,
"environments": [
"preview",
"staging"
],
"budget": {
"spend_increase_per_day": {
"amount": "10.00",
"currency": "GBP",
"display": "£10.00"
}
},
"approval_channel": [
"push",
"email"
],
"status": "active",
"summary": [
"Can deploy to staging and previews.",
"Cannot touch production without your approval.",
"Can set secrets but never read them.",
"Can raise spend by up to £10.00 a day."
],
"created_by": {
"type": "user",
"id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us",
"display": "Stewart Webb"
},
"expires_at": "2026-11-22T09:00:00Z",
"last_used_at": "2026-10-23T13:58:00Z",
"revoked_at": null,
"created_at": "2026-10-23T09:00:00Z"
}

Change an agent token’s scopes, environments, budget or channel

Section titled “Change an agent token’s scopes, environments, budget or channel”
PATCH /v1/workspaces/{workspace}/agent-tokens/{token_id}
  • Operation: updateAgentToken
  • Scopes: tokens: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.
token_id * path string Agent token id.

Request body (application/json, required): AgentTokenUpdate

Field Type Description
name string
description string
scopes array of Scope
projects array of string or null
environments array of string
budget AgentTokenBudget
approval_channel array of ApprovalChannel

Responses

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

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/agent-tokens/tok_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"scopes": [
"deploy:staging"
],
"projects": [
"string"
],
"environments": [
"string"
],
"budget": {
"spend_increase_per_day": {
"amount": "7.42",
"currency": "GBP",
"display": "£7.42"
},
"max_deploys_per_hour": 1
},
"approval_channel": [
"push"
]
}'

Example response

{
"id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk",
"workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"name": "claude-code-on-stewart-laptop",
"description": "Claude Code on Stewart's MacBook",
"prefix": "guv_agt_Qm4x",
"scopes": [
"projects:read",
"deploy:preview",
"deploy:staging",
"logs:read",
"secrets:write-only",
"db:branch"
],
"projects": null,
"environments": [
"preview",
"staging"
],
"budget": {
"spend_increase_per_day": {
"amount": "10.00",
"currency": "GBP",
"display": "£10.00"
}
},
"approval_channel": [
"push",
"email"
],
"status": "active",
"summary": [
"Can deploy to staging and previews.",
"Cannot touch production without your approval.",
"Can set secrets but never read them.",
"Can raise spend by up to £10.00 a day."
],
"created_by": {
"type": "user",
"id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us",
"display": "Stewart Webb"
},
"expires_at": "2026-11-22T09:00:00Z",
"last_used_at": "2026-10-23T13:58:00Z",
"revoked_at": null,
"created_at": "2026-10-23T09:00:00Z"
}
DELETE /v1/workspaces/{workspace}/agent-tokens/{token_id}
  • Operation: revokeAgentToken
  • Scopes: tokens: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.
token_id * path string Agent token id.

Responses

Status Meaning Body
200 OK Dry run. Nothing was changed; this is what would happen. Plan
204 No Content Done. No body. none

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/agent-tokens/tok_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"