Providers
Multi-provider API key management with encryption.
Overview
Artemis securely stores API keys for multiple LLM providers. Keys are encrypted at rest and scoped to groups for multi-tenant access control.
URL: https://artemis.meetrhea.com/providers
Hierarchy
Group
└── Provider Account (e.g., "Production OpenAI")
└── Provider Key (encrypted API key)
Provider Account
A logical grouping for keys from the same provider. Useful when you have multiple accounts with a provider (e.g., personal vs. org billing).
Provider Key
The actual API key, encrypted and stored in the database. Each key has:
- Name: Display name for identification
- Key Suffix: Last 4 chars for recognition
- Is Default: Whether this is the default for the provider
- Is Active: Whether the key can be used
Supported Providers
| Provider | ID | Base URL |
|---|---|---|
| Anthropic | anthropic | https://api.anthropic.com |
| OpenAI | openai | https://api.openai.com |
google | https://generativelanguage.googleapis.com | |
| Perplexity | perplexity | https://api.perplexity.ai |
| OpenRouter | openrouter | https://openrouter.ai/api/v1 |
Adding a Provider Key
Via Web UI
- Go to https://artemis.meetrhea.com/providers
- Select your group from the dropdown
- Click Add Key under the provider
- Enter the API key and a name
- Key is encrypted and saved
Via Database (Seeding)
from app.services.provider_account_service import ProviderAccountService
from app.services.provider_key_service import ProviderKeyService
# Get or create account
account = await provider_account_service.get_or_create_default(
group_id=group_id,
provider_id="openai",
created_by_id=user_id
)
# Create key
await provider_key_service.create(
provider_account_id=account.id,
user_id=user_id,
key="sk-...",
name="Production Key"
)
Key Selection
When a request comes in, Artemis selects a provider key:
- Override: If the API key has a provider key override configured
- Default: The key marked as default for that provider in the group
- First Active: The first active key if no default is set
Per-API-Key Overrides
API keys can specify which provider key to use:
{
"provider_key_overrides": {
"openai": "pk_abc123",
"anthropic": "pk_def456"
}
}
Security
Encryption
Provider keys are encrypted using Fernet symmetric encryption before storage:
from app.auth import encrypt_api_key, decrypt_api_key
encrypted = encrypt_api_key("sk-...") # Store this
decrypted = decrypt_api_key(encrypted) # Use this
Access Control
- Keys are scoped to groups
- Only group members can view/manage keys
- Key values are never exposed in the UI (only suffix)
- Reveal requires explicit action
API
# List providers
GET /providers
# Add key (simple endpoint)
POST /providers/{provider_id}
Content-Type: application/x-www-form-urlencoded
api_key=sk-...&name=My+Key
# Create account
POST /providers/{provider_id}/accounts
name=Production&account_email=billing@example.com
# Add key to account
POST /providers/accounts/{account_id}/keys
api_key=sk-...&name=Key+Name
# Delete key
POST /providers/key/{key_id}/delete
# Set default
POST /providers/key/{key_id}/set-default
# Reveal key (returns JSON)
GET /providers/key/{key_id}/reveal
Model Sync
OpenRouter models can be synced from their API:
POST /providers/openrouter/models/sync
This fetches the latest model list and updates the local database with pricing and capabilities.
Database Schema
providers
| Column | Type | Description |
|---|---|---|
| id | text | Provider slug (e.g., "openai") |
| name | text | Display name |
| base_url | text | API base URL |
| docs_url | text | Documentation URL |
| is_active | bool | Whether provider is enabled |
provider_accounts
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| group_id | uuid | FK to groups |
| provider_id | text | FK to providers |
| name | text | Account name |
| account_email | text | Billing email |
| account_phone | text | Support phone |
provider_keys
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| provider_account_id | uuid | FK to provider_accounts |
| user_id | uuid | Who created it |
| encrypted_key | text | Encrypted API key |
| name | text | Display name |
| key_suffix | text | Last 4 chars |
| is_default | bool | Default for provider |
| is_active | bool | Can be used |