Integrations
Credentials Management
Store and use API keys and OAuth2 tokens in your integrations
Credentials Management
Credentials are named secrets stored securely in the workspace vault. They are referenced in step code via ctx.credentials.CREDENTIAL_NAME.
Credential Types
| Type | Description |
|---|---|
api_key | A single secret string (API token, bearer key, etc.) |
oauth2 | An OAuth2 connection with client ID/secret, auth URL, token URL, and scopes |
Create a Credential
curl -X POST https://app.headlessops.ai/api/credentials \
-H "Authorization: Bearer iter_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "api_key",
"name": "STRIPE_KEY",
"description": "Stripe production API key (Bearer auth, scopes: charges:read)",
"value": "sk_live_...",
"metadata": { "account_id": "acct_123", "mode": "live" }
}'Naming convention: Use
UPPER_SNAKE_CASEfor credential names.
Credential Apps (Connection Templates)
Credential Apps are reusable templates that pre-fill all non-secret OAuth2 fields. This is the recommended way to create OAuth2 credentials:
# 1. List available apps
curl https://app.headlessops.ai/api/credentials/apps \
-H "Authorization: Bearer iter_YOUR_KEY"
# 2. Create a credential from the template
curl -X POST https://app.headlessops.ai/api/credentials/apps/slack/create-credential \
-H "Authorization: Bearer iter_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "SLACK_PROD", "description": "Slack production workspace" }'Invite Links (External User Flows)
Invite links let external users supply their own credentials without accessing the platform:
| Link Type | Use Case |
|---|---|
api_key_fill | External user pastes their API key |
oauth2_fill | External user enters client ID + secret, then authorizes |
oauth2_authorize | All OAuth2 fields pre-configured, link just triggers authorization |
curl -X POST https://app.headlessops.ai/api/credentials/invites \
-H "Authorization: Bearer iter_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"credentialId": "cred_abc123",
"linkType": "api_key_fill",
"ttl": "48h"
}'Response includes a public url to send to the user.
Using Credentials in Steps
export async function run(input: Record<string, any>, ctx: StepContext) {
// Access the secret value
const apiKey = ctx.credentials.STRIPE_KEY;
// Access metadata
const meta = ctx.credentials.meta.STRIPE_KEY;
const accountId = meta.metadata?.account_id;
const response = await ctx.http.get(
"https://api.stripe.com/v1/charges",
{
headers: { Authorization: `Bearer ${apiKey}` },
timeout: 25000,
}
);
if (!response.ok) throw new Error(`Stripe API returned ${response.status}`);
const data = await response.json();
return data;
}