# Secrets and Variables

> Store API keys, tokens and shared values once at workspace level, and reference them from any workflow without exposing the plaintext.

Secrets and variables store API keys, tokens and shared values once at workspace level, referenced by name from any workflow. Secrets are encrypted at rest, so sensitive values are never hardcoded into a workflow.

## Finding them

Open your workspace and choose the **Variables** tab. Secrets and variables share that one page. The table's **Type** column tells them apart.

## Creating a secret

1. Open the **Variables** tab in your workspace.
2. Click **Create new** and choose **Secret**.
3. Enter a **Key**. Letters, numbers and underscores only: a hyphen, dot or space is rejected. Glow upper-cases whatever you type, so `stripe_api_key` is stored as `STRIPE_API_KEY`. References are upper-cased before lookup too, so `{{ $secret.stripe_api_key }}` still resolves. Writing the key in capitals is a convention, not a requirement, and it keeps what you type matching what is stored. Name it for the service and the job: `STRIPE_API_KEY`, `SLACK_WEBHOOK_URL`.
4. Enter the **Value**: the sensitive data you want to store.
5. Click **Save**.

The value is encrypted immediately. Once saved, the value is never displayed in the UI again.

## Referencing secrets in workflows

To use a secret inside a workflow step, reference it as `{{ $secret.KEY_NAME }}`:

```
{{ $secret.KEY_NAME }}
```

For example, if you created a secret with the key `STRIPE_API_KEY`, you would reference it as:

```
{{ $secret.STRIPE_API_KEY }}
```

Non-secret team variables use the same shape with `$var`: `{{ $var.REGION }}`.

This works in any step field that supports dynamic values: HTTP request headers, code blocks, AI prompt configurations, and more. The **Syntax** column on the Variables tab shows the exact reference for each key, so you can copy it rather than type it.

> **The double braces and the `$` are both required.** A reference Glow does not
> recognise is passed through as literal text, so `secrets.STRIPE_API_KEY`
> written without them arrives at the other service as those exact characters.
> In an `Authorization` header, that comes back as a `401`. Copy the reference
> from the **Syntax** column rather than typing it.

> **Tip:** Use clear, consistent naming conventions for your secrets. A pattern
> like `SERVICE_PURPOSE` makes each one's job obvious: `GITHUB_ACCESS_TOKEN`,
> `SENDGRID_API_KEY`.

## Rotating a secret

**A secret's value cannot be edited.** The dialog says so when you create one: _"Secret values cannot be edited once created. Delete and recreate to change value."_ The row offers only **Delete**, where a variable offers **Edit** and **Delete**. The stored value is never readable again, including by us.

To change a secret, replace it:

1. Open the **Variables** tab in your workspace.
2. Delete the existing secret.
3. Create a new one **using the same key**.

Keeping the key identical means every `{{ $secret.KEY }}` already in your workflows keeps resolving. Nothing needs re-editing or re-deploying.

> **Rotate when the workflows using it are quiet.** Between the delete and the
> create there is no value under that key, and a run reaching that step in the
> gap fails there. For a busy workflow, switch it to **Draft** first so triggers
> stop firing, rotate, then switch it back to **Live**.

## Updating a variable

Non-secret variables _are_ editable in place, since their values stay readable:

1. Open the **Variables** tab in your workspace.
2. Find the variable and click **Edit**.
3. Enter the new value and save.

The new value is picked up by every step that runs from that point on, including steps still to come in a run already under way. The value is read when the step executes, not when the run starts.

## Deleting a secret

1. Open the **Variables** tab in your workspace.
2. Find the secret you want to remove.
3. Click **Delete** and confirm.

Before deleting, check that no active workflows reference the secret. A workflow that references a deleted secret fails at the step where the missing secret is used.

## Security notes

- Secret values are **encrypted at rest** and are never exposed in the UI after creation.
- When a stored result or error contains the exact value of a Glow Secret, standard run processing replaces it with `[REDACTED]`. Paste-sensitive values stored directly in step fields do not carry the same protection.
- Secrets are **scoped to a team**. Members of other teams cannot access them.
- Secrets **stay in the workspace they were created in**. A workflow moved to another workspace arrives with each secret key created empty, for that team to fill in its own value.
- Only **Admins and Managers** can create, update, or delete secrets. Members can view secret keys (names) but not their values.

## What's Next?

- Compare connections, secrets, workspace variables, files, and literals in [Where Data Lives](/manage/workspace-settings/where-data-lives).
- Reference a secret correctly inside a step using the [Variable Reference Syntax](/reference/variable-syntax).
- Hold run-scoped values that do not belong in a secret with [Custom Variables](/build/action-steps/custom-variables).
