Managing Secrets
This guide covers creating encrypted credentials, configuring injection routes, and rotating keys — all without redeploying agent containers.
Prerequisites
- Tenant-level API key (secrets require tenant auth)
- API credentials to store (OpenAI key, Anthropic key, etc.)
Creating a Secret
const response = await fetch("https://api.steward.fi/secrets", {
method: "POST",
headers: {
"X-Steward-Key": "your-tenant-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "openai-prod",
value: "sk-proj-abc123...",
description: "Production OpenAI API key",
expiresAt: "2027-01-01T00:00:00Z", // optional
}),
});
const { data } = await response.json();
console.log(data.id); // "550e8400-..."
console.log(data.name); // "openai-prod"
// Note: the value is NEVER returned in responses
Creating a Route
Routes tell the proxy how to inject credentials when an agent makes a request:
// Route for OpenAI
await fetch("https://api.steward.fi/secrets/routes", {
method: "POST",
headers: {
"X-Steward-Key": "your-tenant-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
secretId: "550e8400-...", // the secret ID from above
hostPattern: "api.openai.com",
pathPattern: "/*",
injectAs: "header",
injectKey: "Authorization",
injectFormat: "Bearer {value}",
priority: 0,
enabled: true,
}),
});
Common Route Examples
{
"secretId": "openai-secret-id",
"hostPattern": "api.openai.com",
"pathPattern": "/*",
"injectAs": "header",
"injectKey": "Authorization",
"injectFormat": "Bearer {value}"
}
{
"secretId": "anthropic-secret-id",
"hostPattern": "api.anthropic.com",
"pathPattern": "/*",
"injectAs": "header",
"injectKey": "x-api-key",
"injectFormat": "{value}"
}
{
"secretId": "legacy-api-id",
"hostPattern": "api.legacy-service.com",
"pathPattern": "/*",
"injectAs": "query",
"injectKey": "apiKey",
"injectFormat": "{value}"
}
Listing Secrets
curl https://api.steward.fi/secrets \
-H "X-Steward-Key: your-key"
{
"ok": true,
"data": [
{
"id": "550e8400-...",
"name": "openai-prod",
"description": "Production OpenAI API key",
"version": 1,
"createdAt": "2026-03-26T12:00:00Z"
},
{
"id": "660f9500-...",
"name": "anthropic-prod",
"description": "Anthropic production key",
"version": 2,
"createdAt": "2026-03-20T10:00:00Z"
}
]
}
Rotating a Secret
When you need to update a credential (e.g., API key rotation), use the rotate endpoint:
curl -X POST https://api.steward.fi/secrets/550e8400-.../rotate \
-H "X-Steward-Key: your-key" \
-H "Content-Type: application/json" \
-d '{ "value": "sk-proj-new-key-xyz..." }'
This:
- Creates a new encrypted version of the secret
- Routes automatically use the latest version
- No container redeployment needed — agents keep making the same proxy calls
Deleting a Secret
curl -X DELETE https://api.steward.fi/secrets/550e8400-... \
-H "X-Steward-Key: your-key"
Deleting a secret will cause proxy requests that depend on it to fail with 403. Make sure no active routes reference the secret before deletion.
Managing Routes
List Routes
curl https://api.steward.fi/secrets/routes \
-H "X-Steward-Key: your-key"
Update a Route
curl -X PUT https://api.steward.fi/secrets/routes/route-id \
-H "X-Steward-Key: your-key" \
-H "Content-Type: application/json" \
-d '{ "enabled": false }'
Delete a Route
curl -X DELETE https://api.steward.fi/secrets/routes/route-id \
-H "X-Steward-Key: your-key"
Priority-Based Routing
When multiple routes match a request, the one with the highest priority wins:
// Trading API gets a privileged credential (priority 10)
await createRoute({
secretId: "trading-api-prod",
hostPattern: "api.example.com",
pathPattern: "/v2/trading/*",
priority: 10,
// ...
});
// Everything else gets read-only credential (priority 0)
await createRoute({
secretId: "api-read-only",
hostPattern: "api.example.com",
pathPattern: "/*",
priority: 0,
// ...
});