Secrets and connections
Credentials stay out of your code. The gateway adds them to the requests that need them.
Stand-ins
When a secret has hosts, secrets.NAME in your code is a stand-in, a string like slsec_STRIPE_KEY_1d48…. Use it wherever the key goes, including in vendor SDKs. The gateway replaces it with the real value on requests to those hosts only.
PUT /v1/secrets/STRIPE_KEY
{ "value": "sk_live_…", "hosts": ["api.stripe.com"] }
// In the workflow:
const stripe = new Stripe(secrets.STRIPE_KEY);
- Where it swaps
Headers (including inside
Authorization: Basic), the query string, and JSON, form or text bodies up to 1 MiB, over https. - Wrong host
A stand-in sent to any other host stops the request with
403and an audit entry. - Bound to the run
A stand-in is valid only in the run that made it. One pasted into a webhook payload, or copied from another run, stays plain text.
- Echoes
If a host echoes the value back, your code sees
[redacted]. - Unknown names
Reading a secret without hosts, or a misspelled name, throws. Deploys list the names your code reads and warn about missing ones.
Connections
Use a connection when an admin should control how a credential is sent. A connection has hosts and an auth template. A workflow links the connections it uses, and the gateway applies the template to every request to those hosts, replacing any value the code set. If an SDK requires an API key, pass a placeholder. See Connections for the full reference.
Connection · stripe
in use- Hosts
api.stripe.com- Header
Authorization- Template
Bearer {{ secret.STRIPE_KEY }}- Secrets
STRIPE_KEY· write-only- Workflows
- refund-check
Last used 21:41:10 · GET api.stripe.com · 200
PUT /v1/connections/twilio
{ "hosts": ["api.twilio.com"],
"template": { "headers": {
"Authorization": "{{ basic(secret.TWILIO_SID, secret.TWILIO_TOKEN) }}" } } }
PUT /v1/workflows/notify/connections
{ "connections": ["twilio"] }
headersHeader name → template.
Host,Content-Lengthand similar headers are reserved.queryQuery parameter → template.
pathThe whole path. Expression output is percent-encoded.
body.json · body.formJSON pointer or form field → template. The request must send the matching content type.
Expressions: {{ secret.NAME }}, {{ var.NAME }} (a var), {{ request.method|host|path|query|body }} (body only in headers), ~ to concatenate, | to pipe, and the functions base64 base64url hex urlencode json lower upper trim sha256 hmac_sha256 hmac_sha512 basic now now_ms uuid. See Expressions. When two connections cover one host, pick one per request with the header x-shiftlabs-connection: <name>. The gateway removes this header before sending.
Secret and var names are uppercase letters, digits and underscores, starting with a letter. Secrets are write-only. No endpoint returns their values. See the security page for how the gateway handles them.