Configuration
ScaiControl reads its configuration from environment variables via backend/src/scaicontrol/config.py (Pydantic BaseSettings). The complete set:
Core#
| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
mysql+asyncmy://… |
Async DB URL. Production points at a MariaDB Galera cluster; dev uses aiosqlite |
REDIS_URL |
redis://localhost:6379/0 |
Queue + cache + short-lived state |
LOG_LEVEL |
INFO |
Backend log verbosity |
PORTAL_URL |
http://localhost:5173 |
Used in invoice PDFs (logo + asset URLs) and email links |
API_URL |
http://localhost:8000 |
Self-reference for callbacks |
S3 (PDFs, uploads)#
| Variable | Purpose |
|---|---|
S3_BUCKET |
Bucket name |
S3_REGION |
AWS region (or compatible service region) |
S3_ENDPOINT_URL |
Optional; set for MinIO / non-AWS providers |
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY |
Credentials. Omit on AWS to use instance role |
S3_PREFIX |
Key prefix for ScaiControl objects (e.g. uploads) |
UPLOAD_MAX_SIZE_MB |
50 |
ScaiKey (identity)#
| Variable | Purpose |
|---|---|
SCAIKEY_ISSUER |
OIDC issuer URL |
SCAIKEY_CLIENT_ID |
Confidential client ID for the portal |
SCAIKEY_CLIENT_SECRET |
Client secret (or vault path below) |
SCAIKEY_CLIENT_SECRET_VAULT_PATH |
ScaiVault path for the secret |
SCAIKEY_WEBHOOK_SECRET |
Inbound webhook signing secret |
SCAIKEY_WEBHOOK_SECRET_VAULT_PATH |
Or via vault |
SCAIKEY_JWKS_CACHE_TTL |
3600 (seconds) for JWKS rotation |
Payment providers#
Stripe#
| Variable | Purpose |
|---|---|
STRIPE_API_KEY / STRIPE_API_KEY_VAULT_PATH |
Secret key |
STRIPE_PUBLISHABLE_KEY |
Frontend-visible publishable key |
STRIPE_WEBHOOK_SECRET / STRIPE_WEBHOOK_SECRET_VAULT_PATH |
Webhook signing secret |
Mollie#
| Variable | Purpose |
|---|---|
MOLLIE_API_KEY / MOLLIE_API_KEY_VAULT_PATH |
API key |
MOLLIE_WEBHOOK_SECRET / MOLLIE_WEBHOOK_SECRET_VAULT_PATH |
Inbound webhook secret |
Crypto (Coinbase Commerce)#
| Variable | Purpose |
|---|---|
CRYPTO_API_KEY / CRYPTO_API_KEY_VAULT_PATH |
Coinbase Commerce API key |
CRYPTO_WEBHOOK_SECRET / CRYPTO_WEBHOOK_SECRET_VAULT_PATH |
Webhook secret |
CRYPTO_ACCEPTED_COINS |
BTC,ETH,USDC,USDT (comma-separated) |
CRYPTO_SETTLEMENT_CURRENCY |
EUR |
ScaiSend (email)#
| Variable | Purpose |
|---|---|
SCAISEND_API_URL |
https://scaisend.scailabs.ai/ |
SCAISEND_API_KEY |
Inline API key (dev) |
SCAISEND_API_KEY_VAULT_PATH |
Vault path (production) |
ScaiControl reads vault path first; falls back to inline. Empty config → email sends become no-ops (logged warning, no error).
ScaiVault (secrets)#
| Variable | Purpose |
|---|---|
SCAIVAULT_API_URL |
ScaiVault base URL |
SCAIVAULT_API_KEY |
Auth key |
Service registry / heartbeats#
| Variable | Default | Purpose |
|---|---|---|
REGISTRY_HEARTBEAT_MONITOR_INTERVAL |
60 |
Monitor interval in seconds |
REGISTRY_HEARTBEAT_GRACE_MULTIPLIER |
3 |
Grace period as multiplier of the service's own heartbeat_interval_seconds |
REGISTRY_HEARTBEAT_DEGRADED_THRESHOLD |
3 |
Consecutive failures → degraded |
REGISTRY_HEARTBEAT_UNREACHABLE_THRESHOLD |
10 |
Consecutive failures → unreachable |
AUTO_APPROVED_APP_IDS |
first-party slugs | Services that skip pending-approval gate |
Operator branding#
| Variable | Purpose |
|---|---|
OPERATOR_LEGAL_NAME |
E.g. ScaiLabs B.V. — used in fallback email "From" name and seller snapshots when partner config is missing |
Visma e-Accounting (optional)#
| Variable | Purpose |
|---|---|
VISMA_EACCOUNTING_CLIENT_ID / VISMA_EACCOUNTING_CLIENT_SECRET (+ vault path) |
OAuth |
Vault precedence#
For every *_VAULT_PATH + plain-secret pair, ScaiControl resolves in this order:
- Vault path → ScaiVault lookup → returned value
- Plain env variable → returned value as-is
- Neither → the integration is "unconfigured"; calls degrade gracefully (warning log, no crash)
This lets you run the same image in dev (inline secrets in .env) and production (vault paths) without code changes.
Health & readiness#
GET /api/v1/health returns {"status":"ok"}. No DB roundtrip; suitable for liveness probes. There's no separate readiness endpoint today — for now the DB connection is checked lazily on first query.