08. Variables and Secrets¶
A feature for keeping API keys out of your workflows. You manage them on the Variables screen in the sidebar.
There are two kinds¶
| Secrets | Variables (plain) | |
|---|---|---|
| How it is stored | Encrypted | Plain text |
| On screen | The value is masked (you cannot see it again) | The value is visible |
| Reference | ${secrets.KEY} |
${vars.KEY} |
| What goes in it | API keys, tokens, passwords | Domains, channel IDs, thresholds |
They cannot cross over. You cannot pull a secret out with ${vars.*}, nor the other way round.
The structure exists to keep a sensitive value from leaking through a plain-text path by accident.
Creating one¶
- Go to Variables in the sidebar.
- Pick the Secrets tab or the Variables tab.
- Press the create button and fill it in.
| Field | Description |
|---|---|
| Key | The name you will reference. For example: OPENAI_API_KEY |
| Value | The actual value |
| Description | A note about what it is for (optional) |
Once created, pressing the copy button in the list copies it straight out as ${secrets.OPENAI_API_KEY}. Just paste that into your YAML.
Naming convention: uppercase letters and underscores are recommended (
OPENAI_API_KEY,SLACK_CHANNEL_ID). The name is used verbatim in expressions, so avoid spaces and special characters.
Using them¶
- id: ai
type: CALL
integration: llm_chat
input:
apiContract: OPENAI_CHAT
model: gpt-4o-mini
apiKey: "${secrets.OPENAI_API_KEY}" # ← a secret
userPrompt: "..."
- id: fetch
type: CALL
integration: http_request
input:
uri: "${vars.API_BASE_URL}/orders" # ← a plain variable, can be mixed into a string
method: GET
authenticate:
authMethod: HEADERS
data:
Authorization: "Bearer ${secrets.MY_API_TOKEN}"
Changing a secret's value¶
Once saved, a secret can never be viewed again. To change the value, type a new one over it. If you leave the value blank in the edit dialog and save, the existing value is kept and only the description changes.
Good practice¶
✅ Do this¶
apiKey: "${secrets.OPENAI_API_KEY}"
uri: "${vars.SHOP_API_BASE}/v1/orders"
channel: "${vars.ALERT_CHANNEL_ID}"
❌ Don't do this¶
apiKey: "sk-proj-abc123..." # the key written straight into YAML
uri: "https://api.myshop.com/v1/orders" # change the domain and you edit every workflow
If you write a key into YAML, it leaks along with the workflow whenever you copy or share it. A workflow definition is text that is visible on screen and can be copied as-is.
Commonly used variables¶
| Key | Kind | Example value |
|---|---|---|
OPENAI_API_KEY |
Secret | sk-proj-... |
ANTHROPIC_API_KEY |
Secret | sk-ant-... |
SHOP_API_TOKEN |
Secret | Your store's API token |
WEBHOOK_SECRET |
Secret | The webhook signature key (see below) |
API_BASE_URL |
Variable | https://api.myshop.com |
ALERT_CHANNEL_ID |
Variable | C0123ABCDEF |
VIP_THRESHOLD |
Variable | 100000 |
The one secret with a reserved name — WEBHOOK_SECRET¶
Most variables can be named whatever you like, but eeumsae recognizes WEBHOOK_SECRET by name.
Register a secret under that name and every webhook trigger in that workspace starts requiring a signature. Requests with a missing or wrong signature do not run.
| Where | Variables → Secrets tab |
| Key | WEBHOOK_SECRET (exactly this name) |
| Value | Any long random string (for example the output of openssl rand -hex 32) |
| Scope | Every webhook workflow in the workspace |
⚠️ Registering it as a plain variable does not turn verification on. Create it on the Secrets tab.
⚠️ The moment you add it, existing webhook calls stop working. If webhooks are already live, add the signature header on the calling side first, then register this.
How to build the signature and which headers to use → 03. Setting Up Triggers
Things to watch out for¶
- They are per workspace. If you have several workspaces, you have to register them in each one.
- If you rename one, every workflow referencing the old name errors out at execution time. Check where it is used before renaming.
- If you delete one, workflows referencing it fail with
ExpressionResolveExceptionfrom their next execution.
Next → 09. Datasets