Set environment variables
Give an app settings and secrets as environment variables for its build, its replicas or both, and apply them with a deployment.
In the dashboard
Environment variables give an app its settings and secrets, such as a database address or a key for another service. Each variable reaches the build, the running app or both. You set them on the app's Environment tab or through the API. Once you save a value, neither the dashboard nor the API shows it again.
Before you begin
Section titled Before you begin- For an organization's app, you need the owner or admin role in the organization to change variables. Every member can see their names.
- A change reaches the app with its next deployment (Apply a change).
Add a variable
Section titled Add a variable- Open the app from Apps in the dashboard and select the Environment tab.
- Select Add variable….
- In Name, type the name, such as
DATABASE_URL. In Value, type or paste the value. - Leave Secret ticked to hide the value in build logs, or untick it for a plain value (Secret and plain values).
- In Available at, choose Build and runtime, Runtime only or Build only (Where a variable reaches). For an image app, it starts at Runtime only.
- Select Add variable.
A message confirms DATABASE_URL added., and a note under the app's header says which kind of deployment applies it.
Change or delete a variable
Section titled Change or delete a variableTo give a variable a new value, open the menu at the end of its row and select Replace value…. Type the new value, change Secret or Available at if you need to, and select Save variable. Leave Value empty to keep the saved value while you change the other two. A message confirms DATABASE_URL saved.
A name cannot change. To rename a variable, delete it and add it again.
To delete a variable, select Delete variable… in its menu, then Delete variable to confirm. A message confirms DATABASE_URL deleted. Running replicas keep the variable until the next deployment, and the value cannot be recovered.
Read the variable list
Section titled Read the variable list- Name
- The variable's name, and
Secret, hidden in build logsorPlain. - Value
•••• shopfor a value of eight characters or more, whereshopis its last four characters, orSealedfor a shorter one.- Available at
- Build and runtime, Runtime only or Build only.
- Updated
- When the variable last changed.
The card says how many variables the app has out of its limit, such as 12 of 200 variables. Values are sealed and never shown again. With more than six, Search variables finds them by name.
Names and values
Section titled Names and valuesA name has upper-case letters, digits and underscores, does not start with a digit, and has at most 128 characters, such as DATABASE_URL. These names are set by the platform, so you cannot use them:
PORT,TZ,STARTUP,SERVER_MEMORY,SERVER_IPandSERVER_PORT- any name that starts with
CORITAN_orP_SERVER_
A value can be empty, and holds up to 32 KiB. The dashboard does not save an empty value, so set one through the API. An app has up to 200 variables, and their names and values together hold up to 256 KiB.
Where a variable reaches
Section titled Where a variable reachesEach variable has a target:
- Build and runtime
- The build and every replica get it. New variables have this target unless you choose another.
- Runtime only
- Only the replicas get it.
- Build only
- Only the build gets it. Builds explains how a Railpack build and a Dockerfile build read it.
An image app is not built, so only the variables its replicas get reach it. Every replica also gets PORT and the CORITAN_ variables (What your app must do).
Secret and plain values
Section titled Secret and plain valuesA variable is secret unless you say otherwise. A secret value of six characters or more appears as [redacted] in the build log, and a Dockerfile build gets it as a build secret instead of a build argument. A plain value can appear in the build log as it is.
Both kinds are stored encrypted, and neither is ever shown again after you save it. For a value of eight characters or more, the variable shows its last four characters, so you can tell which value is saved. To change a value, replace it.
Apply a change
Section titled Apply a changeReplicas keep the variables they started with. After you change a variable:
- For one that the running app reads, redeploy the app.
- For one that the build reads, redeploy with a rebuild, so the build runs again.
Redeploy shows both. In the dashboard, a note under the app's header says which one: A redeploy applies the saved changes, or A new build applies the saved changes for a variable the build reads. Its Redeploy… button starts it. Through the API, the answer to each change says redeploy_required when a redeploy is needed.
A value that cannot be read
Section titled A value that cannot be readRarely, a saved value can no longer be opened on the platform, and the variable is marked as not readable. The running app starts without it, and a build that needs it fails with The build variable API_KEY cannot be read on this platform. Save it again. Set the variable again with its value.
In the dashboard, the Environment tab says One variable cannot be read, and the variable's value reads Unreadable, set it again. Select Set again… in its menu, type the value, and select Save variable.
Result
Section titled ResultThe Environment tab lists each name with where it is available, whether it is secret, and the hint of its value. The next deployment uses them.
Troubleshooting
Section titled TroubleshootingUse upper-case letters, digits and underscores, not starting with a digit, such as DATABASE_URL.or'database_url' is not a variable name: upper-case letters, digits and underscores, not starting with a digit, at most 128 characters- Change the name, for example to
DATABASE_URL. PORT is set by the platform. Choose another name.orPORT is set by the platform and cannot be changed- The platform sets that name on every replica. Use another name, and read
PORTto know where to listen. API_KEY needs a value- A new variable was saved without a value. Give it one.
The environment is larger than 256 KiB in total- Shorten or delete some values. A large file is better kept in Object Storage and fetched when the app starts.
- A variable does not change in the running app
- Replicas keep the variables they started with. Redeploy the app, with a rebuild for a variable the build reads.
Related
Section titled RelatedWith the API
Section titled With the APIFor an organization's app, send the same requests under /api/v1/orgs/{org_slug}/apps (organization apps reference). In each request, target is both, runtime or build.
List variables
Section titled List variablesGET /api/v1/client/apps/{app_uuid}/env lists the variables by name, without their values:
curl https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/env \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"vars": [
{
"key": "DATABASE_URL",
"secret": true,
"target": "runtime",
"value": null,
"hint": "shop",
"readable": true,
"created_at": "2026-09-20T09:12:00Z",
"updated_at": "2026-09-24T16:40:00Z"
},
{
"key": "NODE_ENV",
"secret": false,
"target": "both",
"value": null,
"hint": null,
"readable": true,
"created_at": "2026-09-20T09:12:00Z",
"updated_at": "2026-09-20T09:12:00Z"
}
]
}
value is always null. hint is the last four characters of a value of eight characters or more, and null otherwise. readable is false when the saved value can no longer be opened.
Set one variable
Section titled Set one variablePUT /api/v1/client/apps/{app_uuid}/env/{key} creates the variable or changes it. The body takes value, secret and target. A new variable needs value. For one that exists, leave value out to keep the saved value while you change secret or target.
curl -X PUT https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/env/STRIPE_KEY \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "sk_live_EXAMPLE0000", "target": "runtime"}'
{
"var": {"key": "STRIPE_KEY", "secret": true, "target": "runtime", "value": null, "hint": "0000", "readable": true},
"created": true,
"redeploy_required": true
}
created is true for a new variable. The example shortens var.
Set many variables
Section titled Set many variablesPUT /api/v1/client/apps/{app_uuid}/env sets up to 200 variables in one request. Each item in vars has a key and the same value, secret and target as above. With "replace": true, every variable not in the list is deleted.
curl -X PUT https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/env \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"vars": [{"key": "NODE_ENV", "value": "production", "secret": false}, {"key": "DATABASE_URL"}], "replace": true}'
{
"created": [],
"updated": ["NODE_ENV"],
"deleted": ["STRIPE_KEY"],
"redeploy_required": true
}
created, updated and deleted name the variables the request touched. DATABASE_URL kept its value because the request left value out. The answer also holds vars, every variable after the change, as in the list above.
Delete a variable
Section titled Delete a variableDELETE /api/v1/client/apps/{app_uuid}/env/{key} deletes one variable and answers {"deleted": "STRIPE_KEY", "redeploy_required": true}. Running replicas keep it until the next deployment.
Errors
Section titled Errors| Status | detail |
Cause |
|---|---|---|
404 |
Variable not found |
The app has no variable with that name. |
422 |
{"message": "PORT is set by the platform and cannot be changed", "field": "key"} |
The name is one the platform sets. |
422 |
{"message": "API_KEY needs a value", "field": "value"} |
A new variable came without value. |
422 |
{"message": "The value of API_KEY is larger than 32 KiB", "field": "value"} |
The value is too long. |
422 |
{"message": "API_KEY appears twice", "field": "key"} |
vars names one variable twice. |
422 |
An app can have at most 200 variables |
The change would leave the app with more than 200. |
422 |
The environment is larger than 256 KiB in total |
The names and values would hold more than 256 KiB. |
API operations on this page
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/client/apps/{app_uuid}/env | List an app's environment variables without their values |
PUT | /api/v1/client/apps/{app_uuid}/env | Set many variables; a variable given without value keeps its saved one |
PUT | /api/v1/client/apps/{app_uuid}/env/{key} | Set one environment variable, creating it when it is new |
DELETE | /api/v1/client/apps/{app_uuid}/env/{key} | Delete one environment variable |
GET | /api/v1/orgs/{org_slug}/apps/{app_uuid}/env | List an app's environment variables without their values |
PUT | /api/v1/orgs/{org_slug}/apps/{app_uuid}/env | Set many variables; a variable given without value keeps its saved one |
PUT | /api/v1/orgs/{org_slug}/apps/{app_uuid}/env/{key} | Set one environment variable, creating it when it is new |
DELETE | /api/v1/orgs/{org_slug}/apps/{app_uuid}/env/{key} | Delete one environment variable |