Skip to main content

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

ProviderIDBase URL
Anthropicanthropichttps://api.anthropic.com
OpenAIopenaihttps://api.openai.com
Googlegooglehttps://generativelanguage.googleapis.com
Perplexityperplexityhttps://api.perplexity.ai
OpenRouteropenrouterhttps://openrouter.ai/api/v1

Adding a Provider Key

Via Web UI

  1. Go to https://artemis.meetrhea.com/providers
  2. Select your group from the dropdown
  3. Click Add Key under the provider
  4. Enter the API key and a name
  5. 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:

  1. Override: If the API key has a provider key override configured
  2. Default: The key marked as default for that provider in the group
  3. 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

ColumnTypeDescription
idtextProvider slug (e.g., "openai")
nametextDisplay name
base_urltextAPI base URL
docs_urltextDocumentation URL
is_activeboolWhether provider is enabled

provider_accounts

ColumnTypeDescription
iduuidPrimary key
group_iduuidFK to groups
provider_idtextFK to providers
nametextAccount name
account_emailtextBilling email
account_phonetextSupport phone

provider_keys

ColumnTypeDescription
iduuidPrimary key
provider_account_iduuidFK to provider_accounts
user_iduuidWho created it
encrypted_keytextEncrypted API key
nametextDisplay name
key_suffixtextLast 4 chars
is_defaultboolDefault for provider
is_activeboolCan be used