Environment variables and secrets
Each value belongs to a project, and either to one environment or to all of them (environment: null). A value set for an environment overrides the project-wide one with the same name.
Changes take effect on the next deploy; every write says so with "appliesOn": "next_deploy".
Environment variables
| Request | Who | What it does |
|---|---|---|
GET /v1/projects/{projectId}/env |
Owners, admins, developers, tokens with env:read |
Lists variables with their values. ?environment=production returns what that environment sees, overrides applied. |
PUT /v1/projects/{projectId}/env/{key} |
Owners, admins, developers, tokens with env:write |
{ "value", "environment"? }. Creates or replaces. |
DELETE /v1/projects/{projectId}/env/{key} |
Same as PUT |
{ "environment"? }, or no body for the project-wide value. Removes it, or 404 if there’s nothing to remove. |
{ "variables": [{ "key": "PUBLIC_SITE_NAME", "value": "Cookbook", "environment": null, "updatedAt": "2026-10-27T12:00:00.000Z" }] }
Without ?environment=, the list has one entry per value, sorted by key, so a key set both project-wide and for production appears twice.
Secrets
No route ever returns a secret’s value. Values are encrypted with the project’s own key before they’re stored, and are decrypted only to hand them to your app at deploy.
| Request | Who | What it does |
|---|---|---|
GET /v1/projects/{projectId}/secrets |
Owners, admins, developers, tokens with env:read |
Lists secret names, never values. Same ?environment= as above. |
PUT /v1/projects/{projectId}/secrets/{key} |
Owners, admins, developers, tokens with env:write |
{ "value", "environment"? }. Creates or replaces. |
DELETE /v1/projects/{projectId}/secrets/{key} |
Same as PUT |
{ "environment"? }. Removes it. |
{ "secrets": [{ "key": "STRIPE_SECRET_KEY", "environment": null, "updatedAt": "2026-10-23T12:00:00.000Z" }] }
Rules for both
- Names: upper-case letters, digits and underscores, starting with a letter, at most 64 characters. Names starting
FS_are reserved. Anything else is400 validation_failed. - Values: at most 5 KB.
- An environment that doesn’t exist in the project is
404 not_found. - Every
PUTandDELETEis in the audit log (env_var.set,env_var.deleted,secret.set,secret.deleted) with the name and environment, never the value. - Viewers can’t read either list.
- A deploy token reaches only its own project. One made for a single environment can read only that environment (
?environment=is required).
As Markdown: api/environment.md