Skip to main content

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": "birdeye-secret-id",
  "hostPattern": "public-api.birdeye.so",
  "pathPattern": "/defi/*",
  "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:
  1. Creates a new encrypted version of the secret
  2. Routes automatically use the latest version
  3. 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,
  // ...
});