AskSary lets you use your own OpenAI, Anthropic, Google Gemini or xAI key, or any OpenAI‑compatible endpoint. Requests served on your key cost you zero AskSary credits. This page describes exactly what happens to that key.
- Your key is validated against the provider, encrypted, and stored. The plain key is never written to disk, never logged, and never sent back to you.
- Only AskSary's server can read the encrypted record. Browsers, mobile apps and other users cannot, even if they know your user id.
- The key is decrypted only inside the request that needs it and is discarded when that request ends. It is never cached across requests.
- Deleting a key removes it immediately. There is no soft delete.
- We will never use your key for anything other than the request you sent.
What happens when you save a key
- Your browser sends the key over HTTPS to
PUT /api/web-byokwith your signed‑in identity. Anonymous guests cannot store keys. - The server checks the key is a plausible token (printable ASCII, no spaces, 8 to 512 characters). A custom endpoint URL must be
https://, must resolve to a public address, and may not point at AskSary's own hosts, private networks, loopback, link‑local or cloud metadata addresses. This is the server‑side request forgery (SSRF) guard. - The server makes one read‑only call to the provider (its "list models" endpoint) using your key. If the provider answers 401 or 403 the key is rejected and nothing is stored. The key is sent in a header, never in a URL, so it cannot appear in an access log.
- The key is encrypted with AES‑256‑GCM: a fresh random 96‑bit nonce for every write; a 128‑bit authentication tag so a modified record fails to decrypt; and additional authenticated data binding the ciphertext to your user id and the provider name, so a record copied to another user or provider slot fails to decrypt.
- The ciphertext, the last four characters of the key, an optional label, and timestamps are written to the Firestore document
userProviderKeys/{your uid}. No other part of the key is stored. - The plain key is discarded. The response contains only the provider name and the last four characters.
Where the encryption key lives
The master key (BYOK_MASTER_KEY, 256 bits) exists only as an environment variable on AskSary's server functions. It is not in the repository, not in the database, and not reachable from the client. A second variable is accepted for decryption only so the key can be rotated without locking anyone out. Each record carries the id of the master key that wrote it.
Who can read the record
Firestore security rules deny all client access to userProviderKeys:
match /userProviderKeys/{userId} {
allow read, write: if false;
}
Only server code running with the Firebase Admin SDK can read or write it, and that code decrypts a record only for the user whose signed identity is on the request.
What happens when you send a message
- Your request arrives with your signed identity. The server loads your encrypted records, decrypts them, and places them in a request‑scoped context that lives exactly as long as the request.
- Every provider client in the chat handler is a proxy that reads that context. If you have a key for the provider being called, a fresh client is built with your key for this request. Otherwise AskSary's own client is used.
- The billing layer reads the same context. If the call is going out on your key, the operation is recorded as user‑funded, zero credits are reserved, and settlement writes zero. The audit row still exists so you and we can see what ran. Because one context drives both decisions, "used your key" and "charged you nothing" cannot disagree.
- When the request ends the context is gone. Nothing about the key is written to logs. The only key‑related log lines record that a key was saved or deleted (provider name and last four characters) or could not be read (provider name and an error code).
If the provider rejects your key during a chat (401 or 403), you see a message telling you which provider refused it and how to fix it. It is not treated as an AskSary outage.
What still costs credits
Only calls that go to a provider you have a key for run at zero credits. Everything else is unchanged: image, video, music and 3D generation on AskSary's own provider accounts, and any text call to a provider you have not added a key for. Rate limits and abuse controls apply to every request regardless of who pays the provider.
Custom endpoints
A custom entry is an OpenAI‑compatible base URL, a key, and the model name your endpoint expects. It stands in for OpenAI when you have not stored an OpenAI key. Features that require OpenAI‑only APIs (file search, code interpreter, the Responses API) may not work on endpoints that do not implement them.
Deleting a key
Removing a key deletes the provider's field from your document in a single write. There is no retention window, no backup written by this feature, and no copy anywhere else. Firestore's own point‑in‑time recovery, if enabled on the project, retains history for at most seven days and is accessible only to project administrators.
What this does not protect against
We would rather say this plainly than let you assume otherwise.
- A compromised AskSary server. Server code that holds the master key can decrypt records. That is inherent to any server‑side BYOK design. We limit the blast radius by keeping the key decrypted only for the life of a request and never logging it, but we cannot make the server unable to read what it must use.
- Your provider account. We validate that a key works; we do not know or control what it is allowed to spend. Create a dedicated key with a spending limit at your provider, and rotate it whenever you like.
- Your own device and browser. The key is typed into a password field and cleared from the field before the network call. We do not store it in browser storage. Anything that can read your screen or keyboard is outside our control.
Verify the code yourself
The seven files that can see a plain key are sealed: their exact contents are committed to by a SHA‑256 manifest whose hash is published here. That code changes only for an upgrade or for maintenance, and every change is a new, announced seal that names the one it replaced and the reason. Silently altering the key‑handling code to read your key would change the hash.
fa576a1bd588605108f7fed43368f2b61f04511126899edea828e439e37114e1
Clone the public vault repository and check it against the anchor. The verifier is one file with no dependencies; read it before you run it.
node scripts/byok-verify.mjs --anchor fa576a1bd588605108f7fed43368f2b61f04511126899edea828e439e37114e1
Exit code 0 means every sealed file matches. Then ask the live deployment which seal it is running and compare:
curl https://www.asksary.com/api/web-byok-seal
Sealed files: lib/byok-vault.js, lib/byok-context.js, lib/byok-clients.js, lib/byok-seal.js, api/web-byok.js, api/web-byok-seal.js, scripts/byok-verify.mjs, plus the deny‑all Firestore rule above.
What a valid seal does not prove. The live endpoint is the server describing itself; a server altered to steal keys could be altered to lie there too, so the anchor you obtained independently is the real check. The chat handler that calls the sealed files is large and changes often, so it is not sealed. And whoever holds the master key and runs the server can decrypt records; the seal makes silent changes detectable, not impossible. The full protocol, the reseal policy, the history of every seal and the sealed source itself are public at github.com/sidevworks/asksary-byok-vault.
Reporting a problem
Email team@asksary.com. Please do not include your API key in the report.