Connect your own AI keys
Bring your own provider keys so AI-powered apps run on your account
Some apps call AI models. Rather than bundling model costs into the price, those apps can run on your provider key: you pay your provider directly for what you use, and the app's price stays what the creator set.
This is usually called BYOK — bring your own key.
What is live and what is planned
Live. The Key Vault is running. Each purchase of a paid hosted app gets its own Vault token, and it ends if the purchase is refunded. Through it the app can hold your key for one of four providers — Anthropic, OpenAI, Google or Mistral — and call that provider with it. The key is encrypted, never returned to the app or to your browser, and used only inside the Vault. The token itself stays on Panoply's servers too: the app reaches the Vault through its own address, so the page never holds it. A free app has no Vault.
Live. A key belongs to one app. The Vault stores it per app and per buyer, so a key you give one app is not available to another, and you give it again to each app that needs it.
Planned. One place in your account settings to add a key once and reuse it across apps. There is none today.
Planned. A field on the listing that names the provider an app needs. Today, read the listing's description, and expect the key to be asked for by the app itself.
Panoply does not use your key for its own inference.
For creators: what the Vault forwards
Your app reaches the Vault through window.panoplyVault, which Panoply adds to every hosted app. It calls your app's own address, and your app's server side (which Panoply runs, not you) fetches the buyer's Vault token and calls the Vault. Your code never handles the token, and needs nothing in its content security policy beyond 'self'.
// Store the buyer's key once, from your settings screen.
await panoplyVault.keys.set('anthropic', keyTheBuyerPasted)
// Which providers this buyer has a key for, with the key's last four characters
// for your settings screen: { providers: ['anthropic'], keys: [{ provider: 'anthropic', last4: 'x9Qa' }] }
const { providers, keys } = await panoplyVault.keys.list()
// Call the provider in its own request format. You get the provider's
// Response back, so a streamed answer streams.
const res = await panoplyVault.run('anthropic', 'v1/messages', {
headers: { 'content-type': 'application/json', 'anthropic-version': '2023-06-01' },
body: JSON.stringify({ model, max_tokens: 1024, messages }),
})
// Remove it again.
await panoplyVault.keys.delete('anthropic')
A failed call rejects with an error carrying a code. vault_revoked means the buyer's access ended (for example, the purchase was refunded) while the app was open; tell them so rather than retrying. vault_unavailable means the vault could not check access right now (an outage, not a revocation): the call was not made, and trying again later is right. The buyer's sign-in is handled for you: an expired session is renewed in the background and the call retried once, and only if that fails does the call reject with session_expired.
The Vault forwards a short list of endpoints per provider, each with the one method it takes, and refuses every other path or method:
| Provider | Path your app calls |
|---|---|
| Anthropic | POST /run/anthropic/v1/messages |
| OpenAI | POST /run/openai/v1/chat/completions |
| Mistral | POST /run/mistral/v1/chat/completions |
POST /run/google/v1beta/models/<model>:generateContent or :streamGenerateContent |
OpenRouter and Runware keys are stored with keys.set like the others, but panoplyVault.run refuses both, and so does a tool's vault.run: the call is rejected with vault_provider_ai_only before anything reaches the vault. They are reached only through the AI routes your app's Worker serves under /__panoply/ai/. Only OpenRouter chat calls made through those routes write a cost row. Calls to Anthropic, OpenAI, Google and Mistral through panoplyVault.run or a tool's vault.run write none, and Runware has no AI route yet.
An OpenRouter key is checked with OpenRouter before it is stored. A key OpenRouter does not accept is not stored, and keys.set rejects with key_rejected; if the check could not run, nothing is stored and it rejects with key_check_unavailable.
The Vault also limits what it forwards:
- It supplies the key itself, so a request carrying its own
keyparameter is refused. - Request bodies are capped at 4 MB.
- The provider has 60 seconds to start answering. A stream that has started can run as long as it needs.
- Calls are accepted only from your app's own pages. A request from another app's page is refused, even though it is on the same
panop.lydomain.
What it costs to run a model
Model prices come from the providers, not from Panoply — we take no cut of your model spend. Rates change often, so here is the current picture rather than a number written into this page:
| Model | Provider | Input | Output |
|---|---|---|---|
| Claude Opus 4.8 | Anthropic | $5 | $25 |
| Claude Sonnet 5 | Anthropic | $2 | $10 |
| Claude Haiku 4.5 | Anthropic | $1 | $5 |
| GPT-5.5 | OpenAI | $5 | $30 |
| GPT-5.4 | OpenAI | $2.50 | $15 |
| GPT-5.1 | OpenAI | $1.25 | $10 |
| Gemini 3.1 Pro | $2 | $12 | |
| Gemini 3 Pro | $2 | $12 | |
| Gemini 3.5 Flash | $1.50 | $9 | |
| Mistral Large | Mistral | $0.50 | $1.50 |
| Mistral Medium | Mistral | $1.50 | $7.50 |
Prices are USD per million tokens. Scores are BenchLM’s raw overall score (may be provisional), not the calibrated site ranking. Prices in USD per million tokens. Scores from BenchLM.ai. Rates updated Oct 31, 2026.
Prices are per million tokens, in USD. Use them to estimate what an app will cost you to run: a chat-style app that sends a few thousand tokens per exchange costs fractions of a cent per message on a cheap model, and meaningfully more on a frontier one.
Choosing a model
If an app lets you pick a model, the trade-off is the usual one — cheaper and faster, or slower and more capable. Start on a cheap model and move up only if the output isn't good enough. The app's listing should say which models it supports.
If you'd rather not
An app that needs a key should say so in its description before you buy. Plenty of apps don't need one at all. See Find an app worth buying.