Secrets
Write-only secrets. Reads return names and metadata only.
| Operation | Method and path |
|---|---|
| List secrets (names and metadata only) | GET /v1/projects/{project}/environments/{environment}/secrets |
| Set a secret (write-only) | POST /v1/projects/{project}/environments/{environment}/secrets |
| Get a secret’s metadata | GET /v1/projects/{project}/environments/{environment}/secrets/{secret} |
| Unset a secret | DELETE /v1/projects/{project}/environments/{environment}/secrets/{secret} |
| Rotate a secret to a new value | POST /v1/projects/{project}/environments/{environment}/secrets/{secret}/rotate |
List secrets (names and metadata only)
Section titled “List secrets (names and metadata only)”GET /v1/projects/{project}/environments/{environment}/secrets- Operation:
listSecrets - Scopes:
variables:read - CLI:
guv secrets list - 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. |
service |
query | string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
A page of SecretMetadata objects. | SecretMetadataList |
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/secrets \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "data": [ { "id": "sec_01jbx2m9k7q4r8t5v6w3y0z1sc", "name": "stripe-secret-key", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": null, "version": 3, "injected_as": null, "build": false, "description": "Stripe live secret key", "display": "••••••• (set 2 min ago by Stewart Webb)", "set_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "referenced_by": [ { "service": "web", "variable": "STRIPE_SECRET_KEY" } ], "last_used_at": "2026-10-23T14:04:00Z", "last_used_by_deployment_id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "decrypts_last_7_days": 14, "created_at": "2026-10-01T09:00:00Z", "updated_at": "2026-10-23T14:00:00Z" } ], "next_cursor": "string", "has_more": false}Set a secret (write-only)
Section titled “Set a secret (write-only)”POST /v1/projects/{project}/environments/{environment}/secretsEncrypts immediately with the environment’s data key; the value is never stored in plaintext, logged or returned. Setting an existing name creates a new version.
- Operation:
setSecret - Scopes:
secrets:write-only - CLI:
guv secrets set - 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. |
Request body (application/json, required): SecretSetRequest
| Field | Type | Description |
|---|---|---|
name * |
string | |
value * |
string | Never logged, never stored in plaintext, never returned. Write-only: never returned. |
service |
string | Service name or id. Omit for a secret shared by the environment. |
build |
boolean | Default false. |
description |
string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. |
SecretMetadata |
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/secrets \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "value": "string", "service": "string", "build": false, "description": "string"}'Example response
{ "id": "sec_01jbx2m9k7q4r8t5v6w3y0z1sc", "name": "stripe-secret-key", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": null, "version": 3, "injected_as": null, "build": false, "description": "Stripe live secret key", "display": "••••••• (set 2 min ago by Stewart Webb)", "set_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "referenced_by": [ { "service": "web", "variable": "STRIPE_SECRET_KEY" } ], "last_used_at": "2026-10-23T14:04:00Z", "last_used_by_deployment_id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "decrypts_last_7_days": 14, "created_at": "2026-10-01T09:00:00Z", "updated_at": "2026-10-23T14:00:00Z"}Get a secret’s metadata
Section titled “Get a secret’s metadata”GET /v1/projects/{project}/environments/{environment}/secrets/{secret}- Operation:
getSecret - Scopes:
variables: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. |
secret * |
path | string | Secret name. |
service |
query | string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | SecretMetadata |
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/secrets/stripe-secret-key \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "id": "sec_01jbx2m9k7q4r8t5v6w3y0z1sc", "name": "stripe-secret-key", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": null, "version": 3, "injected_as": null, "build": false, "description": "Stripe live secret key", "display": "••••••• (set 2 min ago by Stewart Webb)", "set_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "referenced_by": [ { "service": "web", "variable": "STRIPE_SECRET_KEY" } ], "last_used_at": "2026-10-23T14:04:00Z", "last_used_by_deployment_id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "decrypts_last_7_days": 14, "created_at": "2026-10-01T09:00:00Z", "updated_at": "2026-10-23T14:00:00Z"}Unset a secret
Section titled “Unset a secret”DELETE /v1/projects/{project}/environments/{environment}/secrets/{secret}Fails with conflict while a running deployment references it, unless ?force=true.
- Operation:
unsetSecret - Scopes:
secrets:write-only - CLI:
guv secrets unset - 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. |
secret * |
path | string | Secret name. |
service |
query | string | |
force |
query | boolean |
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
curl -X DELETE https://api.guv.dev/v1/projects/shopfront/environments/production/secrets/stripe-secret-key \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)"Rotate a secret to a new value
Section titled “Rotate a secret to a new value”POST /v1/projects/{project}/environments/{environment}/secrets/{secret}/rotate- Operation:
rotateSecret - Scopes:
secrets:write-only - CLI:
guv secrets rotate - 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. |
secret * |
path | string | Secret name. |
service |
query | string |
Request body (application/json, required): SecretRotateRequest
| Field | Type | Description |
|---|---|---|
value * |
string | Write-only: never returned. |
redeploy |
boolean | Redeploy services that use the secret once the new version is stored. Default false. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. |
SecretMetadata |
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/secrets/stripe-secret-key/rotate \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "value": "string", "redeploy": false}'Example response
{ "id": "sec_01jbx2m9k7q4r8t5v6w3y0z1sc", "name": "stripe-secret-key", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "service_id": null, "version": 3, "injected_as": null, "build": false, "description": "Stripe live secret key", "display": "••••••• (set 2 min ago by Stewart Webb)", "set_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "referenced_by": [ { "service": "web", "variable": "STRIPE_SECRET_KEY" } ], "last_used_at": "2026-10-23T14:04:00Z", "last_used_by_deployment_id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "decrypts_last_7_days": 14, "created_at": "2026-10-01T09:00:00Z", "updated_at": "2026-10-23T14:00:00Z"}