Dynamic Secrets
Dynamic Secrets are credentials for third-party services that are leased on-demand for a limited time. Leases are tied to a specific account, and can be renewed to extend their validity, or revoked manually before they expire. Dynamic Secrets reduce the attack surface of your secrets by limiting the lifespan of active credentials and ensuring that each user has their own set of credentials. Dynamic Secrets can be created manually or automatically through integrations with external systems. This guide covers how to fetch metadata for dynamic secrets and leases, generate credentials, and renew or revoke leases via the REST API.
Dynamic Secrets can be fetched via a GET request to the /v1/secrets/dynamic/ endpoint, or as part of the standard Secrets API by including the dynamic or includeDynamic query parameters. Include the lease parameter to generate leases for dynamic secrets in the response.
Get Dynamic Secrets
Retrieve all dynamic secrets in a given environment. You can optionally filter secrets by a specific path and / or name.
Required parameters
- Name
app_id- Type
- string
- Description
Unique identifier for the Phase App you wish to get secrets from.
- Name
env- Type
- string
- Description
The environment name, ex:
development
Optional parameters
- Name
path- Type
- string
- Description
Get dynamic secrets at a specific path.
- Name
id- Type
- string
- Description
The id of a specific secret to fetch.
- Name
name- Type
- string
- Description
The name of a specific secret to fetch.
- Name
lease- Type
- boolean
- Description
Whether to generate leases for dynamic secrets in the response. If not supplied, the
leasefield in the response will benull. Note that generating leases can increase the response latency by several seconds.
- Name
ttl- Type
- number
- Description
The TTL to use when generating leases for dynamic secrets, in seconds. If not supplied, the default TTL defined for the dynamic secret will be used.
Request
curl -G https://api.phase.dev/v1/secrets/dynamic/ \
-H "Authorization: Bearer {token}" \
-d app_id=72b9ddd5-8fce-49ab-89d9-c431d53a9552 \
-d env=development \
-d path=/backend \
-d name=AWS IAM credentials \
-d lease=true
Response
[
{
"id": "e30c989a-e032-4328-8220-5b7e6044808b",
"name": "AWS IAM credentials",
"type": "dynamic",
"description": "",
"environment": "59a5bab7-a43e-427a-933c-a175bd27642b",
"folder": "994053ae-0dbf-4d4d-bdf9-74f862af4f49",
"path": "/test",
"defaultTtl": "01:00:00",
"maxTtl": "1 00:00:00",
"provider": "aws",
"keyMap": [
{
"id": "username",
"keyName": "AWS_USERNAME",
"keyDigest": "b63594e9752ef136f8b35c5f0d9ffb908caed453480b8e0c2628a3ae88810b5a"
},
{
"id": "access_key_id",
"keyName": "AWS_ACCESS_KEY_ID",
"keyDigest": "1ea25dfb2e4f401bc11660b85def2afcc78f5487f64f3dad00381aa37fd1d8ac"
},
{
"id": "secret_access_key",
"keyName": "AWS_SECRET_ACCESS_KEY",
"keyDigest": "bc9b1ec9c3b16c3cf6280c38a425933b536ff99825707e8da0c5151e5b9d0c01"
}
],
"createdAt": "2025-09-04T13:36:48.455604Z",
"updatedAt": "2025-09-11T09:09:39.050701Z",
"deletedAt": null,
"lease": {
"id": "87aef716-9064-4a4a-8079-f5c132693ee2",
"name": "AWS IAM credentials",
"description": "",
"secret": "e30c989a-e032-4328-8220-5b7e6044808b",
"ttl": "01:00:00",
"status": "active",
"credentials": [
{
"key": "AWS_USERNAME",
"value": "kl498xd8f"
},
{
"key": "AWS_ACCESS_KEY_ID",
"value": "AKIAVYOQRZOLGMVWFM2H"
},
{
"key": "AWS_SECRET_ACCESS_KEY",
"value": "S80XfzCZTPd9qEfk08/Y5TbK1b1xO5X7Ex5NQjLc"
}
],
"createdAt": "2025-09-12T07:46:41.729641Z",
"renewedAt": null,
"expiresAt": "2025-09-12T08:46:41.729423Z",
"revokedAt": null,
"deletedAt": null
}
}
]
Dynamic secrets can also be fetched via the standard Secrets API by including the dynamic or includeDynamic query parameters. This is useful for fetching all static and dynamic secrets at a given path. Include the lease parameter to generate leases for dynamic secrets in the response.
Get all secrets (Static & Dynamic)
Request
curl -G https://api.phase.dev/v1/secrets/ \
-H "Authorization: Bearer {token}" \
-d app_id=72b9ddd5-8fce-49ab-89d9-c431d53a9552 \
-d env=development \
-d path=/backend \
-d dynamic=true
Response
[
{
"id": "e30c989a-e032-4328-8220-5b7e6044808b",
"name": "AWS IAM credentials",
"type": "dynamic",
"description": "",
"environment": "59a5bab7-a43e-427a-933c-a175bd27642b",
"folder": "994053ae-0dbf-4d4d-bdf9-74f862af4f49",
"path": "/backend",
"defaultTtl": "01:00:00",
"maxTtl": "1 00:00:00",
"provider": "aws",
"keyMap": [
{
"id": "username",
"keyName": "AWS_USERNAME",
"keyDigest": "b63594e9752ef136f8b35c5f0d9ffb908caed453480b8e0c2628a3ae88810b5a"
},
{
"id": "access_key_id",
"keyName": "AWS_ACCESS_KEY_ID",
"keyDigest": "1ea25dfb2e4f401bc11660b85def2afcc78f5487f64f3dad00381aa37fd1d8ac"
},
{
"id": "secret_access_key",
"keyName": "AWS_SECRET_ACCESS_KEY",
"keyDigest": "bc9b1ec9c3b16c3cf6280c38a425933b536ff99825707e8da0c5151e5b9d0c01"
}
],
"createdAt": "2025-09-04T13:36:48.455604Z",
"updatedAt": "2025-09-11T09:09:39.050701Z",
"deletedAt": null,
"lease": {
"id": "87aef716-9064-4a4a-8079-f5c132693ee2",
"name": "AWS IAM credentials",
"description": "",
"secret": "e30c989a-e032-4328-8220-5b7e6044808b",
"ttl": "01:00:00",
"status": "active",
"credentials": [
{
"key": "AWS_USERNAME",
"value": "kl498xd8f"
},
{
"key": "AWS_ACCESS_KEY_ID",
"value": "AKIAVYOQRZOLGMVWFM2H"
},
{
"key": "AWS_SECRET_ACCESS_KEY",
"value": "S80XfzCZTPd9qEfk08/Y5TbK1b1xO5X7Ex5NQjLc"
}
],
"createdAt": "2025-09-12T07:46:41.729641Z",
"renewedAt": null,
"expiresAt": "2025-09-12T08:46:41.729423Z",
"revokedAt": null,
"deletedAt": null
}
}
]
Leases
Leases are temporary credentials generated for a Dynamic Secret. Each lease has a unique ID, name, TTL (time-to-live), status (active, expired, or revoked), and owner (account). Leases can be renewed to extend their TTL, or revoked manually before they expire.
Get Leases
List all leases for a given dynamic secret. The response will not include credentials.
Required parameters
- Name
secret_id- Type
- string
- Description
Unique identifier for the dynamic secret you wish to get leases for.
Request
curl -G https://api.phase.dev/v1/secrets/dynamic/leases/ \
-H "Authorization: Bearer {token}" \
-d secret_id=72b9ddd5-8fce-49ab-89d9-c431d53a9552
Response
[
{
"id": "87aef716-9064-4a4a-8079-f5c132693ee2",
"name": "AWS IAM credentials",
"description": "",
"secret": "e30c989a-e032-4328-8220-5b7e6044808b",
"ttl": "01:00:00",
"status": "active",
"owner": {
"type": "service_account",
"data": {
"id": "66c4693e-dfda-4ba8-9775-6bee658e4915",
"name": "kube-bot",
"role": {
"id": "7ea21ba5-5df0-461c-8089-409ca0b0fe78",
"name": "Service"
},
"createdAt": "2025-08-12T09:25:13.381252Z",
"updatedAt": "2025-08-12T09:25:13.381259Z",
"deletedAt": null
}
},
"credentials": [],
"createdAt": "2025-09-12T07:46:41.729641Z",
"renewedAt": null,
"expiresAt": "2025-09-12T08:46:41.729423Z",
"revokedAt": null,
"deletedAt": null
},
{
"id": "392e927a-cba1-42d8-ada0-0d237c7f3f15",
"name": "AWS IAM credentials",
"description": "",
"secret": "e30c989a-e032-4328-8220-5b7e6044808b",
"ttl": "01:00:00",
"status": "expired",
"owner": {
"type": "service_account",
"data": {
"id": "66c4693e-dfda-4ba8-9775-6bee658e4915",
"name": "kube-bot",
"role": {
"id": "7ea21ba5-5df0-461c-8089-409ca0b0fe78",
"name": "Service"
},
"createdAt": "2025-08-12T09:25:13.381252Z",
"updatedAt": "2025-08-12T09:25:13.381259Z",
"deletedAt": null
}
},
"credentials": [],
"createdAt": "2025-09-12T06:19:23.153426Z",
"renewedAt": null,
"expiresAt": "2025-09-12T07:19:23.153251Z",
"revokedAt": "2025-09-12T07:20:16.597400Z",
"deletedAt": null
},
{
"id": "091cc7c8-10eb-4024-8a03-de3ba1770e17",
"name": "AWS IAM credentials",
"description": "",
"secret": "e30c989a-e032-4328-8220-5b7e6044808b",
"ttl": "01:00:00",
"status": "revoked",
"owner": {
"type": "organisation_member",
"data": {
"id": "b02fb8ac-3dee-44ff-8616-56dde4389e29",
"username": "rohan.chaturvedi",
"fullName": "Rohan Chaturvedi",
"email": "rohan@phase.dev",
"role": {
"id": "c2b05030-8b2b-4f35-a45a-da7e9be1ddcf",
"name": "Owner"
},
"createdAt": "2025-08-06T08:12:07.361849Z",
"updatedAt": "2025-08-06T08:12:07.361855Z",
"deletedAt": null
}
},
"credentials": [],
"createdAt": "2025-09-11T09:10:39.293837Z",
"renewedAt": null,
"expiresAt": "2025-09-11T10:10:39.293631Z",
"revokedAt": "2025-09-11T09:11:26.711079Z",
"deletedAt": null
}
]
Renew a lease
Renew the TTL for a leased credential.
Required parameters
- Name
app_id- Type
- string
- Description
Unique identifier for the Phase App.
- Name
env- Type
- string
- Description
The environment name, ex:
development
JSON Body
Add the Lease ID and TTL in the request body
Required fields
- Name
lease_id- Type
- string
- Description
Unique identifier for the Lease.
- Name
ttl- Type
- number
- Description
The desired lease duration in seconds. The new TTL cannot exceed the maximum TTL defined for the dynamic secret.
Request
curl --location --request PUT 'https://api.phase.dev/v1/secrets/dynamic/leases/?app_id=72b9ddd5-8fce-49ab-89d9-c431d53a9552&env=development' \
--header 'Authorization: Bearer {token}' \
--header 'Content-Type: application/json' \
--data '{
"lease_id":"fc58f652-818b-47c3-b111-f479367039f6",
"ttl":3600
}'
Response
{
"message": "Lease renewed successfully. Updated expiry: 2025-10-27 12:49:26.611113+00:00"
}
Revoke a lease
Revoke a leased credential.
Required parameters
- Name
app_id- Type
- string
- Description
Unique identifier for the Phase App.
- Name
env- Type
- string
- Description
The environment name, ex:
development
JSON Body
Add the Lease ID and TTL in the request body
Required fields
- Name
lease_id- Type
- string
- Description
Unique identifier for the Lease.
Request
curl --location --request DELETE 'https://api.phase.dev/v1/secrets/dynamic/leases/?app_id=72b9ddd5-8fce-49ab-89d9-c431d53a9552&env=development' \
--header 'Authorization: Bearer {token}' \
--header 'Content-Type: application/json' \
--data '{"lease_id":"fc58f652-818b-47c3-b111-f479367039f6"}'
Response
{
"message": "Lease revoked successfully"
}