Your browser cannot keep an API key secret
You are building your first AI feature: a text box, a submit button, and an answer from a model. Putting an API key directly into the browser request feels like the shortest path. It also gives that key to anyone who opens your app.
Browsers download the JavaScript they need to run. Visitors can inspect those files and watch outgoing requests using developer tools. A key hidden in a request header is still visible to the person controlling that browser.
If your front end can read a secret, your visitors can usually read it too. Minifying JavaScript, encoding the key, or hiding it behind an unusual variable name does not change that boundary.
Put your backend between the browser and the model
The safer design has three steps. Your browser sends a request to your backend. Your backend adds the API key and calls the model service. It then returns the answer to the browser without returning the key.
A backend can be a traditional server, a serverless function, or a framework route that runs only on the server. You do not need a large application. You need a trusted place to hold credentials and decide which requests are allowed.
- Browser: collects the prompt and calls your application endpoint, such as /api/chat.
- Backend: checks the request, reads the secret, and makes the authenticated model request.
- Model service: processes that request and sends a response back through your backend.
Keep the browser request free of your upstream API key. Your app may use a session cookie or another user authentication mechanism, but that is separate from the credential that pays for model access.
Store the key in server-only configuration
For local development, put the key in a server-side environment variable. If you use an environment file, exclude it from version control before adding real credentials. In production, use your hosting provider's secret settings or a dedicated secret manager.
An environment variable is not automatically private. Front-end build tools can copy selected variables into browser bundles. Variables with public prefixes, such as NEXT_PUBLIC_ or VITE_, are intended to be exposed. Never put your model API key there.
Also keep secrets out of shared configuration modules, screenshots, support messages, and request logs. An example configuration file should contain placeholders, not working credentials.
Make the backend a guarded doorway
Moving the key solves credential exposure, but an unrestricted backend can still let strangers spend your balance. Require appropriate user authentication and enforce authorization before forwarding requests. For an anonymous demo, set strict usage limits and accept that public access carries abuse risk.
- Limit requests per user and apply spending controls where available.
- Cap prompt size, requested output, and concurrent requests.
- Allow only the models and operations your feature needs.
- Keep the upstream host fixed rather than accepting arbitrary destination URLs.
- Return clean errors without credentials or sensitive upstream details.
CORS is not a replacement for these controls. It governs certain browser interactions; it does not prevent someone from calling your endpoint with a script.
Connect SwiftRelay from the server only
SwiftRelay is a practical option when you want pay-as-you-go model access through an OpenAI-compatible SDK. Configure that SDK on your backend with https://api.fastapirelay.com/v1 as its base URL, and load the SwiftRelay key from server-only configuration.
Sign up for SwiftRelay to try the setup with the small gift credit provided to new accounts. Billing is per token, so pair your first working request with sensible usage limits.
Run a secret check before the green light
Before deploying, inspect the browser bundle and network requests for your key. Check repository history and logs too. Confirm that unauthenticated or oversized requests are rejected as intended.
If a key has already reached browser code or a public repository, treat it as compromised. Revoke it, review usage, and issue a replacement stored only on the server. Deleting the visible copy is not enough: someone may already have saved it.