#Secrets
A secret (an API key, a provider token) is stored write-only and is never returned by any API again. Your workflows and apps don't read secrets directly — they read a reference you wire into their activation config. There are three moves, always in this order.
Authenticate with a Personal Access Token (HTTP Basic auth) — enter it once in the Authorize bar above and every Try it below uses it.
#1. Store the value
Store a value under an UPPER_SNAKE name. It defaults to tenant scope; pass a
different scope (and a scope_id for team / company / app) to target one.
Re-storing the same name overwrites it (rotation).
POST/access/secretsStore a secret valueAPI docs ↗Try it
The value is encrypted at rest and never comes back out of the API — GET /access/secrets lists names only, and no role or grant can retrieve a stored value.
Values surface only inside a running workflow/app action.
#2. Wire a reference into activation config
Put a scoped reference — {{ secrets.<scope>.<NAME> }} — into a named slot of
the activation config (a workflow's config env, or an app's config). The
presence of that reference in config is the read authorization: there is no
separate "read secret" permission, and a workflow/app may resolve only the
references its tenant wired into config (a reference arriving any other way — form
input, an action result — is refused).
For a workflow, wire it into the tenant config env:
PUT/workflows/{id}/configWire a secret into a workflow's envAPI docs ↗Try it
For an app, wire it into the app config (or an integration / principal config):
PUT/apps/{specId}/configWire a secret into an app's configAPI docs ↗Try it
#3. Read the config key from the definition
The workflow/job/action body or the app spec reads the config key — never
secrets.*. A workflow action references config.env.PROVIDER_API_KEY; an app spec
references the config slot you wired (e.g. config.app.provider_token). At run time
the wired reference resolves, the value is injected into server-side execution only,
and it is scrubbed out of any output or response.
A
{{ secrets.* }}reference may live ONLY in config. Putting one in a workflow definition or app spec is rejected on save (SECRET_REF_IN_DEFINITION). A bare, scope-less{{ secrets.NAME }}is always rejected — every reference must name a scope, so a user'sSTRIPE_KEYand the tenant'sSTRIPE_KEYcan never collide or leak.
#Scopes
A reference always names the scope it reads from:
| Scope | Reference | Resolves to |
|---|---|---|
tenant |
{{ secrets.tenant.NAME }} |
the tenant-wide value |
company |
{{ secrets.company.NAME }} |
the caller's own company (implicit at run time) |
user |
{{ secrets.user.NAME }} |
the caller's own user — one wired reference serves every user with their own value |
app |
{{ secrets.app.NAME }} |
the current app activation (implicit) |
team |
{{ secrets.team.<TEAM_ID>.NAME }} |
a specific team (always an explicit team id) |
The implicit scopes (user / company / app) make the same wired reference
resolve to a different value per caller, so a reference can never leak across users,
companies, or apps. When you store a team / company / app secret via the API,
pass its scope_id; tenant and user are derived from you.
#Rotate, list, and delete
- Rotate —
PUT /access/secretswith the samenameand a newvalue(or just re-POST). Wired references pick up the new value on the next run. - List (names only) —
GET /access/secrets(optionally?scope=company). - Delete —
DELETE /access/secrets/{name}(add?scope=&scope_id=for a non-tenant scope).
#API reference
Every secret operation, with full schemas and an interactive console, is in the API reference.