Under heavy development
StitchAPI
GuidesAuth

Secret resolvers

Resolve secrets lazily at call time with env() and keychain() instead of hard-coding them.

Every auth strategy takes a secret as a reference, not a value, and resolves it at call time — reach for env() and keychain() so the declaration carries a capability, not a credential you have to commit.

Example

import { , , ,  } from 'stitchapi';

// env() reads process.env.API_TOKEN when the stitch is called, not now.
const  = ({
    : 'https://api.example.com',
    : '/me',
    : (('API_TOKEN')),
});

// keychain() resolves from ~/.stitch/secrets.json, falling back to the env var.
const  = ({
    : 'https://api.example.com',
    : '/billing',
    : (('BILLING_TOKEN')),
});

The token is never read at declaration time, so the secret never enters the stitch's source — only the name of where to find it does.

Options

A secret is a string | (() => string). Every strategy — bearer, apiKey, basic, oauth2 — accepts one and resolves it the moment a request goes out, so the same declaration works across processes and machines without baking a value in.

env(name) returns a thunk that reads process.env[name] at call time and throws missing env var <name> if it is unset — failing loudly at the call rather than silently sending an empty token.

keychain(name) is a lightweight keychain over a JSON file: it reads ~/.stitch/secrets.json if present and the key is there, otherwise falls back to the environment variable of the same name, and throws if neither has it.

Why call-time resolution matters: the value is fetched only when a call is made, so you never commit a secret and the stitch holds a capability rather than the credential itself — the capability boundary the product is built on. You can pass a plain string (discouraged — that hard-codes the value), or any () => string thunk of your own, so plugging in a vault or secrets manager is just supplying a different resolver.

A plain-string secret is read at declaration time and lives in your source and history. Prefer env() or keychain() so the value is resolved at call time instead.

See also

On this page