Workspace & Team

Provider API keys

Add your own OpenAI, Anthropic, Google, Mistral, Groq, Together, or DeepSeek keys — encrypted in Supabase Vault.

Project88 runs on your provider API keys. You add them once per org; every workspace in the org can use them.

Why your own keys

  • Cost — you pay your provider directly, at their rates.
  • Quotas — your org's quota is your quota; you're never sharing.
  • Security — keys are encrypted in Supabase Vault. The plaintext is never persisted in provider_keys.api_key (that column was dropped in migration 014) and never reaches the browser at runtime.

Supported providers

ProviderKey prefixModels
OpenAIsk-...gpt-4o, o1, o1-mini, gpt-4o-mini
Anthropicsk-ant-...Claude 3.5 Sonnet, Claude 3.5 Haiku, Opus
Google(no prefix)Gemini 2.5 Pro, Gemini 2.5 Flash
Mistral(no prefix)Large, Medium, Small
Groqgsk_...Llama 3.x, Mixtral on Groq
Together(no prefix)Mixtral, Llama, Qwen, DeepSeek
DeepSeeksk-...DeepSeek-V3, DeepSeek-R1

The UI validates the key prefix client-side before saving so you don't silently store a malformed key.

Add a key

  1. ⌘KSettings → Providers.
  2. Click + Add key on the provider you want.
  3. Paste the key. We validate the prefix.
  4. Give it a key name (free-form — useful when you rotate or have multiple).
  5. Save.

The key is sent to the insert_provider_key security-definer function, which:

  1. Creates a row in vault.secrets with the plaintext.
  2. Inserts a row in provider_keys with the secret ID reference only.
  3. Returns the row to the UI.

The plaintext never returns from the function.

What you can see

The Providers tab shows each key's name, provider, active flag, and created_at. The full key value is never displayed — only fields safe to show.

Dev keys

.env variables (VITE_OPENAI_API_KEY, VITE_ANTHROPIC_API_KEY, VITE_GOOGLE_API_KEY) can be used in development as a fallback. The Settings page shows the env-fallback section separately so it's obvious which keys come from where.

How chat completions use keys

When a chat request comes in:

  1. The browser calls the chat-proxy Edge Function with the model name and the conversation.
  2. The proxy looks up the active key for that model's provider via the get_decrypted_provider_key security-definer function.
  3. The function pulls the plaintext from Vault, returns it to the proxy only (not to the browser).
  4. The proxy makes the upstream provider call and streams results back to the browser.

The plaintext exists in memory inside the proxy for the lifetime of the request, then is dropped. No logs include the key.

Toggle and delete

Each key has an active toggle (deactivate without deleting) and a delete button. Deleting calls delete_provider_key, which removes the Vault secret and the provider_keys row in a single transaction.

Where to next

On this page