Auth & Configuration

Multi-user auth, runtime config, and licensing.

Authentication

Stockyard has a built-in auth system for multi-user deployments. Users get sk-sy- API keys that route requests through the proxy with per-user provider key resolution.

# Create a user (returns an API key)
curl -X POST http://localhost:4200/api/auth/signup \
  -d '{"email":"alice@example.com","name":"Alice"}'

# Use the key to make requests
curl http://localhost:4200/v1/chat/completions \
  -H "Authorization: Bearer sk-sy-..." \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'

# Add a provider key to your account
curl -X PUT http://localhost:4200/api/auth/me/providers/openai \
  -H "Authorization: Bearer sk-sy-..." \
  -d '{"api_key":"sk-proj-..."}'

Key resolution order: user’s own provider key → global provider. Users can bring their own keys without sharing them.

Configuration

Stockyard works with zero configuration. All 76 middleware modules are registered on boot with sensible defaults. You can toggle modules on/off at runtime via the API:

# List all modules
curl http://localhost:4200/api/proxy/modules

# Disable a module
curl -X PUT http://localhost:4200/api/proxy/modules/toxicfilter \
  -d '{"enabled": false}'

# Re-enable it
curl -X PUT http://localhost:4200/api/proxy/modules/toxicfilter \
  -d '{"enabled": true}'

Module state persists in the embedded SQLite database. Changes take effect immediately — no restart needed.

License & Pro

Stockyard is free for self-hosted use with 76 modules, 16 core apps, and unlimited requests. Paid tiers unlock 150 standalone tools. Individual tool licenses from $0.99/mo, or Stockyard Complete at $29/mo. Set a license key to activate:

# Set your license key
export STOCKYARD_LICENSE_KEY="SY-eyJ..."

# Restart Stockyard (or set the env var before first start)
stockyard

# Verify your tier and usage
curl http://localhost:4200/api/license

License keys are available at stockyard.dev/pricing. Pro and Enterprise keys unlock unlimited requests, unlimited users, and extended retention. All features and modules are available on every tier.

API Key Types

Stockyard uses two kinds of keys:

Key TypePrefixPurpose
Admin keysy_admin_Full access to all API endpoints, module toggles, user management
User keysy_Proxy requests, own usage data, provider key management

Admin keys are set via environment variable or config file. User keys are generated via the signup endpoint.

Creating Users

curl -X POST http://localhost:4200/api/auth/signup \
  -H "Authorization: Bearer sy_admin_..." \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com", "plan": "free"}'

Response:

{
  "user_id": "usr_abc123",
  "email": "dev@example.com",
  "api_key": "sy_live_k8x...",
  "plan": "free",
  "created_at": "2026-02-28T12:00:00Z"
}

Provider Key Management

Users bring their own provider keys. Store them via the API:

# Add an OpenAI key for the current user
curl -X PUT http://localhost:4200/api/auth/me/providers/openai \
  -H "Authorization: Bearer sy_live_k8x..." \
  -H "Content-Type: application/json" \
  -d '{"api_key": "sk-proj-..."}'

Provider keys are encrypted with AES-256-GCM before being written to SQLite. They are decrypted only in-memory when making outbound API calls. Keys never appear in logs, traces, or API responses.

Encryption at Rest

All provider API keys (OpenAI, Anthropic, etc.) are encrypted using AES-256-GCM before touching disk. The encryption key is resolved in this order:

# Option 1: Bring your own encryption key (recommended for production)
export STOCKYARD_ENCRYPTION_KEY="your-secret-passphrase"

# Option 2: Auto-generated (default)
# If no env var is set, a random 32-byte key is generated on first boot
# and persisted in the stockyard_secrets table.

Existing plaintext keys are automatically migrated to encrypted format on startup. The ciphertext format is enc: + base64(nonce || ciphertext || tag) — each encryption uses a unique random nonce, so the same key produces different ciphertexts each time.

Security model: Provider keys are only decrypted server-side when creating outbound provider connections. The GET /api/auth/me/providers endpoint returns provider names and status but never the key values. The ProviderKey JSON struct has no api_key field.

Key Rotation

Rotate a user’s API key without downtime:

# Admin: rotate a user's key
curl -X POST http://localhost:4200/api/auth/users/usr_abc123/keys/key_id/rotate \
  -H "Authorization: Bearer sy_admin_..."

Response includes the new key. The old key is immediately revoked.

{
  "old_key_id": "key_abc",
  "new_key": "sy_live_new...",
  "new_key_id": "key_def",
  "rotated_at": "2026-02-28T12:00:00Z"
}

Config File Authentication

Set the admin key and default provider keys in stockyard.yaml:

admin_key: "${STOCKYARD_ADMIN_KEY}"

providers:
  openai:
    api_key: "${OPENAI_API_KEY}"
    org_id: "org-..."           # optional
  anthropic:
    api_key: "${ANTHROPIC_API_KEY}"
  groq:
    api_key: "${GROQ_API_KEY}"
Security: Always use environment variable references (${...}) in config files. Never hardcode API keys. Stockyard expands these at startup.

Usage Tracking

Each user can check their own usage:

curl http://localhost:4200/api/auth/me/usage \
  -H "Authorization: Bearer sy_live_k8x..."
{
  "user_id": "usr_abc123",
  "period": "2026-02",
  "requests": 1247,
  "tokens_in": 892400,
  "tokens_out": 234100,
  "cost_usd": 4.82
}

Multi-Tenant Setup

Run Stockyard for multiple teams or customers. Each user gets isolated usage tracking and provider keys:

# Create users for different teams
curl -X POST http://localhost:4200/api/auth/signup \
  -H "Authorization: Bearer sy_admin_..." \
  -H "Content-Type: application/json" \
  -d '{"email": "team-a@example.com", "plan": "team"}'

curl -X POST http://localhost:4200/api/auth/signup \
  -H "Authorization: Bearer sy_admin_..." \
  -H "Content-Type: application/json" \
  -d '{"email": "team-b@example.com", "plan": "team"}'

Enable the tenantwall module to enforce strict isolation between tenants, ensuring one team cannot access another team’s data or quota.

Admin User Management

Admins can list users and manage their keys:

# List all users
curl http://localhost:4200/api/auth/users \
  -H "Authorization: Bearer sy_admin_..."

# Create a new API key for a user
curl -X POST http://localhost:4200/api/auth/users/usr_abc/keys \
  -H "Authorization: Bearer sy_admin_..."

# Set a provider key on behalf of a user
curl -X PUT http://localhost:4200/api/auth/users/usr_abc/providers/openai \
  -H "Authorization: Bearer sy_admin_..." \
  -H "Content-Type: application/json" \
  -d '{"api_key": "sk-proj-..."}'
BYOK model: Stockyard never stores provider keys in plaintext. Keys are encrypted at rest and never appear in logs, traces, or API responses.

Security Best Practices

Follow these practices for production deployments:

PracticeImplementation
Rotate keys regularlyUse the /rotate endpoint on a schedule
Use env vars for secrets${STOCKYARD_ADMIN_KEY} in config files
Separate admin and user keysNever use sy_admin_ keys for proxy requests
Enable IP allowlistingUse ipfence module to restrict access by IP
Monitor key usageCheck /api/auth/me/usage for anomalies

Plans & Billing

Query available plans:

curl http://localhost:4200/api/plans
{
  "plans": [
    {"id": "free", "name": "Free", "requests_per_month": 1000, "price_usd": 0},
    {"id": "pro", "name": "Pro", "requests_per_month": 50000, "price_usd": 29},
    {"id": "team", "name": "Team", "requests_per_month": 500000, "price_usd": 99}
  ]
}
Self-hosted: When running Stockyard on your own infrastructure, plans are enforced locally. No external billing service is required.

For detailed API reference with all auth endpoints, see the API Reference.

Explore: Proxy-only mode · Self-hosted proxy · OpenAI-compatible