Skip to main content

Tenant Config (Control Plane)

The tenant control plane config lets platform operators customize the Steward experience for each tenant — which policies are editable, what the UI looks like, which features are enabled, and how approvals work. This is the layer between a raw multi-tenant Steward deployment and a white-labeled platform-specific experience. Base path: GET/PUT /tenants/:id/config
Auth: Tenant-level (X-Steward-Key)

Get Tenant Config

GET /tenants/:id/config
curl https://api.steward.fi/tenants/my-platform/config \
  -H "X-Steward-Key: your-tenant-key"
Response:
{
  "ok": true,
  "data": {
    "tenantId": "my-platform",
    "displayName": "My Platform",
    "policyExposure": {
      "spending-limit": "visible",
      "rate-limit": "enforced",
      "approved-addresses": "hidden"
    },
    "policyTemplates": [...],
    "secretRoutePresets": [...],
    "approvalConfig": {
      "autoExpireSeconds": 86400,
      "approvers": { "mode": "owner" },
      "webhookCallbackEnabled": true
    },
    "featureFlags": {
      "showFundingQR": true,
      "showTransactionHistory": true,
      "showSpendDashboard": true,
      "showPolicyControls": true,
      "showApprovalQueue": true,
      "showSecretManager": false,
      "enableSolana": true,
      "showChainSelector": false,
      "allowAddressExport": true
    },
    "theme": {
      "primaryColor": "#8B5CF6",
      "accentColor": "#A78BFA",
      "backgroundColor": "#0F0F0F",
      "surfaceColor": "#1A1A2E",
      "textColor": "#FAFAFA",
      "colorScheme": "dark"
    }
  }
}
If no config has been saved, returns a default empty config (all features enabled, no policy restrictions). Built-in defaults are available for: milady-cloud, milady-desktop, eliza-cloud.

Update Tenant Config

PUT /tenants/:id/config
Full replace — any fields omitted default to their zero values.
curl -X PUT https://api.steward.fi/tenants/my-platform/config \
  -H "X-Steward-Key: your-tenant-key" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "My Platform",
    "policyExposure": {
      "spending-limit": "visible",
      "rate-limit": "enforced",
      "approved-addresses": "hidden",
      "auto-approve-threshold": "visible",
      "time-window": "hidden"
    },
    "approvalConfig": {
      "autoExpireSeconds": 86400,
      "approvers": { "mode": "owner" },
      "webhookCallbackEnabled": true
    },
    "featureFlags": {
      "showFundingQR": true,
      "showTransactionHistory": true,
      "showSpendDashboard": true,
      "showPolicyControls": true,
      "showApprovalQueue": true,
      "showSecretManager": false,
      "enableSolana": true,
      "showChainSelector": false,
      "allowAddressExport": true
    },
    "theme": {
      "primaryColor": "#FF6B35",
      "colorScheme": "dark"
    }
  }'

Policy Exposure

policyExposure controls which policy types end users can see and edit in the <PolicyControls> component:
ValueBehavior
"visible"Policy is shown and editable
"enforced"Policy is applied but hidden from end users
"hidden"Policy is not shown and not automatically applied
{
  "policyExposure": {
    "spending-limit": "visible",
    "rate-limit": "enforced",
    "approved-addresses": "hidden",
    "auto-approve-threshold": "visible",
    "time-window": "hidden"
  }
}

Policy Templates

Policy templates appear in the <PolicyControls> component as one-click starting points. Define them with customizable fields so users can tune limits without editing raw policy configs:
{
  "policyTemplates": [
    {
      "id": "trading-agent",
      "name": "Trading Agent",
      "description": "For agents that trade on DEXs. Spending limits + approved routers.",
      "icon": "chart-line",
      "policies": [
        {
          "id": "tpl-spend",
          "type": "spending-limit",
          "enabled": true,
          "config": {
            "maxPerTx": "100000000000000000",
            "maxPerDay": "1000000000000000000",
            "maxPerWeek": "5000000000000000000"
          }
        }
      ],
      "customizableFields": [
        {
          "path": "spending-limit.maxPerDay",
          "label": "Daily Spending Limit",
          "type": "currency",
          "default": "1.0",
          "min": "0.01",
          "max": "100"
        }
      ]
    }
  ]
}

Secret Route Presets

Pre-configured route templates shown in the secret manager UI. Saves users from manually entering host/inject details for common APIs:
{
  "secretRoutePresets": [
    {
      "id": "openai",
      "name": "OpenAI API",
      "hostPattern": "api.openai.com",
      "pathPattern": "/*",
      "injectAs": "bearer",
      "injectKey": "Authorization",
      "injectFormat": "Bearer {value}",
      "provisioning": "platform"
    },
    {
      "id": "anthropic",
      "name": "Anthropic API",
      "hostPattern": "api.anthropic.com",
      "pathPattern": "/*",
      "injectAs": "header",
      "injectKey": "x-api-key",
      "injectFormat": "{value}",
      "provisioning": "user"
    }
  ]
}
provisioning: "platform" means the platform provides the credential. provisioning: "user" means the end user provides their own key.

Approval Config

Controls how the approval workflow behaves for this tenant:
{
  "approvalConfig": {
    "autoExpireSeconds": 86400,
    "approvers": { "mode": "owner" },
    "webhookCallbackEnabled": true
  }
}
FieldDescription
autoExpireSecondsHow long pending approvals last before auto-expiry (0 = never)
approvers.modeWho can approve: "owner" (tenant admins), "tenant-admin"
webhookCallbackEnabledWhether to fire tx.pending webhooks for this tenant

Feature Flags

Toggle UI features in @stwd/react components:
FlagDefaultDescription
showFundingQRtrueShow QR code in <WalletOverview>
showTransactionHistorytrueEnable <TransactionHistory> component
showSpendDashboardtrueEnable <SpendDashboard> component
showPolicyControlstrueEnable <PolicyControls> component
showApprovalQueuetrueEnable <ApprovalQueue> component
showSecretManagerfalseShow secret management UI
enableSolanatrueShow Solana address alongside EVM
showChainSelectorfalseShow chain-switching UI
allowAddressExporttrueAllow copying/exporting wallet addresses

Theme Config

Full color and typography control:
{
  "theme": {
    "primaryColor": "#8B5CF6",
    "accentColor": "#A78BFA",
    "backgroundColor": "#0F0F0F",
    "surfaceColor": "#1A1A2E",
    "textColor": "#FAFAFA",
    "mutedColor": "#6B7280",
    "successColor": "#10B981",
    "errorColor": "#EF4444",
    "warningColor": "#F59E0B",
    "borderRadius": 12,
    "fontFamily": "Inter, system-ui, sans-serif",
    "colorScheme": "dark"
  }
}
These map directly to the CSS custom properties in @stwd/react. Any fields not provided fall back to the component library defaults.