Data & connectionsGuide

Variables and secrets

A variable is a named value your project’s scripts and flows read when they run — a region, a feature switch, an API key. Change it on the Variables page and the next run uses the new value, without editing or republishing anything. Mark it a secret and it is encrypted and never shown again.

8 min readBefore this: Create a projectOpen in Waiso
What you will learn
  • Create plain variables and secrets, one by one or from a .env file
  • Read them from Python, TypeScript, JavaScript, C and C++
  • Know how project and global variables combine
  • Recognise the secrets an integration made and follow the change history

Plain variables and secrets

Every variable has a name in UPPER_SNAKE_CASE (a letter first, then A–Z, 0–9 and _), a value and an optional description. The Hide as secret switch decides what kind it is:

AspectPlainSecret
StoredAs text — “Value stored in plain text, visible to admins”Encrypted (AES-256-GCM) — “Value encrypted, never returned in plain text”
On the pageThe value is shownOnly the name; Reveal value shows it once and logs that it did
In a flow run’s recordRecorded as it isRecorded as •••
Good forRegions, base addresses, switches, timeoutsPasswords, tokens, API keys
Variables & SecretsProject-scoped environment variables and encrypted secrets
Copy from globalImport .envNew variable
Search variables…Ctrl KAllVariablesSecretsFrom integrations
PG_SHOP_DB_PASSWORDfrom shop_db TypesecretValue••••••Updated6 min ago
REPORT_TITLEPlain value, readable by scripts and flowsTypeplainValueDaily salesUpdated11 h ago
S3_SHOP_FILES_ACCESS_KEY_IDfrom shop_files TypesecretValue••••••Updated11 h ago
S3_SHOP_FILES_SECRET_ACCESS_KEYfrom shop_files TypesecretValue••••••Updated11 h ago
SHOP_API_KEYEncrypted at rest, never shown in logsTypesecretValue••••••Updated11 h ago
Plain values are shown, secrets show only their name; integration-made secrets carry the provider’s icon.

Create variables

  1. New variable

    On Variables, click New variable. Type the Name and Value, and a Description if a teammate will wonder what it is for.

  2. Decide if it is a secret

    Turn on Hide as secret for anything that grants access. The button changes to Save secret.

  3. Or import a .env file

    Import .env takes a pasted file — each KEY=VALUE line becomes a variable. The preview counts what will be created; Overwrite existing variables decides whether names that already exist are replaced or skipped, and the summary reports created, skipped and errors.

A row’s ⋯ menu has Edit, Copy name and View change history. Editing a secret leaves the value box empty — leave blank to keep current — so you can fix a description without retyping the secret. Select several rows to delete them together.

Read variables in code

Every variable the project can see — plain and secret — is an environment variable of the script’s process, under the same name. No SDK call, no import: read it the way the language reads any environment variable.

config_check.py
import os

def main():
    region = os.environ.get("REPORT_REGION", "us")
    key = os.environ["BILLING_API_KEY"]
    return {"region": region, "keyLength": len(key)}
Expected outputSuccessWith BILLING_API_KEY set to a 32-character secret and no REPORT_REGION
{
  "region": "us",
  "keyLength": 32
}

In flows

A flow step’s input can be bound straight to a variable with the Variable binding, or read in an expression as vars.NAME. The value is read when the step runs, and a secret bound this way is recorded as •••. Details in Bindings.

Project and global variables

A project variable is seen only by that project’s runs. A global variable is shared by every project of the workspace and is managed by admins. A run sees both; when a project variable and a global one share a name, the project’s wins. Admins also get Copy from global on the project page, which copies chosen global variables into the project so it can change them on its own.

Variables made by integrations

Saving an integration stores its credentials as secrets named after it — PG_MAIN_DB_PASSWORD, S3_FILES_SECRET_ACCESS_KEY, AI_CLAUDE_API_KEY. They appear under From integrations with the provider’s icon and a from … link that opens the connection. They are ordinary variables: your code can read them, and you may edit, rename or delete them. Editing the value re-keys the connection; renaming it does not break the connection, which finds its credential by what it is; deleting it leaves the connection reporting credential_missing until you enter the value again.

Change history

View change history opens the variable’s audit log — values are never shown here. Each entry says who did what and when:

  • Created, Value updated, a field updated (the name, the description), Deleted — by the person who did it.
  • Value revealed — someone pressed Reveal value on a secret. The reveal itself says This reveal has been logged to the change history.
  • Created by integration, Updated by integration, Deleted by integration — the connection saved, renamed or deleted its own variable; System when nobody pressed a button.

The log survives a delete, so “who removed BILLING_API_KEY?” always has an answer. It records changes, not old values: to undo an edit, set the value again.

Rules and limits

  • Every value reaches code as text. Convert numbers and switches yourself (int(os.environ["RETRIES"]), Number(process.env.RETRIES)).
  • A changed value is picked up by the next run that starts; a run already going keeps the value it started with.
  • Reading, creating and deleting variables follow the person’s access to Variables in the project (Team access).