Variables and LiquidSecrets

Secrets

Copy page

Store API keys, tokens, passwords and webhook URLs once, encrypted, and use them in any step or function without ever showing them in the run history.

A secret is a value you store once and use by name: an API key, a token, an SFTP password, a Slack webhook URL. The value is encrypted, never shown again after you save it, and kept out of the run history.

Create a secret

  1. Open Secrets in the app menu and select Create secret.
  2. Enter a Name: letters, numbers and underscores, for example ORDER_API_TOKEN. The name cannot be changed after creation.
  3. Enter the Value.
  4. Optional: a Description, so your colleagues know what it is for.
  5. Save.

To replace a value, open the secret and enter a new one. The stored value is hidden and cannot be read back, not in the app and not over the API.

The Secrets page: a table with ERP_API_KEY, SFTP_PASSWORD and SLACK_WEBHOOK_URL, their values masked, a description and the update date, and a Create secret button
The Secrets page. Values are never shown again after you save them.

Use it in a step

In any field:

Bearer {{ secrets.ORDER_API_TOKEN }}

Typical places: the Webhook URL of a Slack message, an Authorization header of an HTTP request or a Download file step, Username, Password and Private key of a File transfer step.

Use it in code

In a function or in code written in a step, read it as secrets.NAME:

export default async function (input, ctx) {
  const res = await ctx.fetch("https://api.example.com/orders", {
    method: "POST",
    headers: { authorization: `Bearer ${secrets.ORDER_API_TOKEN}` },
    body: JSON.stringify(input.event.payload),
  })
  return { status: res.status }
}

How secrets are protected

  • Values are encrypted with a dedicated key management service, on top of the encrypted database.
  • A secret is only loaded for a step that mentions it.
  • The filled-in input of a step is never stored. In the run history, in test results and in the debugger, secret values are masked in a step's output and in error messages.
  • A workflow variable may hold a secret: variables are worked out again for each step and are not stored with the run.
  • The Developer API lists secrets by name with hasValue. A value is never returned at any access level.

Where secrets must not go

Some fields are stored with the run on purpose, so the editor refuses a secret there:

  • Input (JSON) of a Run function step. The code reads secrets.NAME itself.
  • Payload (JSON) of a Start another workflow step. The started workflow reads its own secrets.

And two habits to avoid:

  • Do not write a secret into a Log message or return it from code. Masking catches the exact value, but not a value your code has changed, for example encoded or cut.
  • Do not type a password into a step as plain text. For the File transfer step the editor enforces this: a workflow with a plain-text login cannot be turned on.

Who can see and use secrets

Everyone with access to the app in your Shopify admin can use every secret in a workflow and can replace or delete it. Nobody can read a stored value.

Deleting a secret

A step that reads a deleted secret gets an empty value, and usually fails at the other system with an authentication error. Before you delete a secret, search your workflows for its name. Over the Developer API, a workflow's requirements list the secrets it names. See Developer API and MCP.