Secrets allow your app to securely access API keys and sensitive values. Users provide their own secrets which are encrypted and injected at runtime.
Declaring Secrets
Define required secrets in inf.yml:
1secrets:2 - key: API_KEY3 description: Your API key for the external service4 optional: false56 - key: WEBHOOK_SECRET7 description: Optional webhook signing secret8 optional: trueProperties
| Property | Type | Description |
|---|---|---|
key | string | Environment variable name |
description | string | Shown to users |
optional | boolean | If false, app won't run without it |
Keys that belong to a service
Declare an API key for a service (Acme, OpenAI, fal) under credentials: with its provider instead:
1credentials:2 - provider: acme3 secrets: [ACME_API_KEY]Your app reads ACME_API_KEY the same way. Users see which service the key is for, and the key they paste is saved as that provider's credential, so other apps that need Acme find it too. Use secrets: for values that belong to no service.
Secret key values must not use names reserved for platform settings. Users cannot store those names as workspace secrets.
When a declared key matches exactly one api_key provider's standard API key name (for example a model provider's documented env var), saving the value through the vault, CLI, or API links it to that provider's credential even though the app lists it under secrets: rather than credentials:. OAuth app credential names are never inferred this way. Use a custom key name when you want a plain environment secret with no provider connection.
Accessing Secrets
Secrets are injected as environment variables:
1import os23class App(BaseApp):4 async def setup(self, config):5 self.api_key = os.environ.get("API_KEY")6 self.webhook_secret = os.environ.get("WEBHOOK_SECRET")Common Patterns
External API Access
1secrets:2 - key: OPENAI_API_KEY3 description: OpenAI API key for GPT models4 optional: false1from openai import OpenAI23class App(BaseApp):4 async def setup(self, config):5 self.client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))HuggingFace Token
1secrets:2 - key: HF_TOKEN3 description: HuggingFace token for gated models4 optional: falseAdd huggingface_hub to requirements.txt; it is not preinstalled.
1from huggingface_hub import snapshot_download23self.model_path = snapshot_download(4 repo_id="meta-llama/Llama-2-7b",5 token=os.environ.get("HF_TOKEN")6)Managing Secrets via CLI
Users can manage their secrets using the CLI:
1# List all secrets2belt secrets list34# Set a secret (creates or updates; prompts for the value without echo)5belt secrets set OPENAI_API_KEY67# Pipe the value in scripts (keeps it out of shell history and ps)8printf %s "$OPENAI_API_KEY" | belt secrets set OPENAI_API_KEY -d "For GPT-4 calls"910# Save as a provider credential (apps declaring that provider receive the key)11belt secrets set ACME_API_KEY --provider acme --provider-name "Acme CRM"1213# Attach or detach without re-entering the value14belt secrets attach GRAFANA_API_KEY grafana15belt secrets detach GRAFANA_API_KEY1617# Get a secret (shows masked value)18belt secrets get OPENAI_API_KEY1920# Delete a secret21belt secrets delete OPENAI_API_KEYBest Practices
- Clear descriptions - help users understand what each secret is for
- Mark optional correctly - only if the app truly works without it
- Don't log secrets - never print or log secret values
- Validate early - check in
setup()and fail fast - Use specific names -
OPENAI_API_KEYis better thanAPI_KEY
REST API
Programmatic CRUD for workspace secrets: Secrets API.
Next
→ Credentials - OAuth service connections