Can you put an AI API key in a frontend or mobile app? No. A key in a browser bundle or a mobile binary is public: anyone with the app can read it from the code, the binary or the network traffic, and use it on your provider account until you revoke it. Keep provider keys on a server. Have the app call your backend with the user's own session, mint short-lived credentials on the server where the client must talk to the provider directly (realtime voice), use attestation such as Firebase App Check where the platform offers it, and cap what each user can spend.
This guide explains why hiding techniques fail, then walks through the four patterns that work, with what OpenAI, Google and Firebase document for each.
Why a shipped key is a public key
A browser or a phone has to send the key with each request, so the key exists in plaintext on the device at that moment. Environment variables in a React, Vue or Next.js client build are inlined into the bundle at build time; the network tab shows the Authorization header; an Android package can be unpacked and searched for strings. Obfuscation moves the key around but cannot remove it.
The SDK authors agree. The OpenAI and Anthropic TypeScript SDKs disable browser use by default "to avoid exposing your secret API credentials", and only run there if you set dangerouslyAllowBrowser to true12. OpenAI's README says enabling it "exposes your secret API credentials in the client-side code"1. Google's Gemini key page says never to expose keys client-side in production or hardcode them in web or mobile apps, because they can be extracted, and to call the API through a backend3. OWASP's Mobile Top 10 lists hardcoded credentials in app code or configuration files as "a clear indicator of vulnerability" under M1, Improper Credential Usage, and recommends revocable access tokens instead4.
This is not a hypothetical. In April 2026 CloudSEK scanned the top 10,000 Android apps and found 32 live Google API keys across 22 apps with a combined install base above 500 million that worked against the Gemini API; for one language-learning app, the key listed files in Gemini's Files API that included users' speech recordings5. The keys had been embedded for Maps or Firebase, where Google's documentation once said that was fine, and gained Gemini access when the Generative Language API was enabled in the same project5. Google API keys and Gemini exposure covers that case in depth.
A key on a device exposes three things: spend (anyone can run inference on your account), data (stored files, responses or fine-tuning data the key can read), and your standing with the provider (abuse on your key is abuse by your account; see why providers suspend accounts).
Four patterns that keep the key off the device
| Pattern | Key on device? | Best for | What you still build |
|---|---|---|---|
| Your backend as the proxy | No | Chat, completions, images, anything request/response | User auth, per-user limits, fixed model and parameters |
| Short-lived client secrets | A credential that expires in minutes | Realtime voice and video over WebRTC or WebSockets | A server endpoint that authenticates the user, then mints |
| Platform proxy plus attestation | No provider key; an attestation token | Gemini in mobile and web apps via Firebase | App Check setup, per-user rate limits |
| Per-user caps | Not applicable | Every pattern above | A user id on every request and a cap per user |
1. Your backend is the proxy
The app authenticates the user with your normal session (cookie, OAuth token, Firebase Auth), calls your endpoint, and your server calls the provider with a key that never leaves the server. This is the default for anything that is not realtime.
A backend that forwards whatever the client sends is only a slower way of publishing the key. Decide on the server:
- Which model and parameters. Fix the model,
max_tokens, tools and system prompt server-side; never accept a model name or a raw message list from the client without checking it. - Who may call. Refuse unauthenticated requests; rate-limit by user, not only by IP.
- How much each user may spend. A per-user daily ceiling turns one abusive account into a bounded cost. Stopping your AI feature becoming a free LLM proxy covers the abuse patterns.
- What reaches logs. Prompts from users are user data; apply your prompt logging policy.
2. Short-lived client secrets for realtime
Realtime voice wants the client to connect to the provider directly, because relaying audio through your server adds latency. Both OpenAI and Google document the same shape: the server authenticates the user, mints a short-lived credential with its own key, and hands only that to the client.
OpenAI Realtime. The browser asks your server for a token; your server calls POST https://api.openai.com/v1/realtime/client_secrets with its standard API key and returns the result; the browser uses it to open a WebRTC session6. The returned value looks like ek_… and carries an expires_at; expires_after.seconds accepts 10 to 7,200 seconds and defaults to 6007. OpenAI recommends setting the OpenAI-Safety-Identifier header on the server request that creates the secret, so the identifier is bound to the token and the browser does not need to send it6. An alternative keeps the key and token entirely server-side: the browser sends its SDP offer to your server, which posts it to /v1/realtime/calls with the standard key6.
curl -X POST https://api.openai.com/v1/realtime/client_secrets \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "OpenAI-Safety-Identifier: $HASHED_USER_ID" \
-H "Content-Type: application/json" \
-d '{"expires_after": {"anchor": "created_at", "seconds": 60}}'Gemini Live. Ephemeral tokens are in preview, work only with the Live API on v1beta, and by default allow one minute to start a session and 30 minutes to use it; uses: 1 limits a token to one session, and liveConnectConstraints locks the model and configuration so the client cannot change the system instructions8. Google is direct about the limit: ephemeral tokens "can be extracted from client-side applications", and their value is that they expire quickly and can be restricted8.
A short-lived credential is only as good as the check before it is minted. If your mint endpoint hands a token to anyone who asks, an attacker calls the endpoint instead of stealing the key.
3. A platform proxy with app attestation
For Gemini in mobile and web apps, Firebase AI Logic puts Google's proxy between the app and the Gemini API so that, in Firebase's words, "your Gemini API key stays on the server and is not embedded in your apps' codebase"9. It applies per-user rate limits by default, and they are configurable9.
The proxy alone would still serve any client that copies the app's configuration. App Check closes that: with enforcement on, the proxy accepts only requests "verified to be from your actual app and/or an untampered device"10. Attestation comes from Play Integrity on Android, DeviceCheck or App Attest on Apple platforms, and reCAPTCHA Enterprise on the web; limited-use tokens with a fixed five-minute lifetime can be used once each for replay protection10. Two dates matter: since early July 2026 the console enforces App Check automatically for new setups, and from 2026-11-02 App Check enforcement is required to use Firebase AI Logic10.
Attestation raises the cost of abuse; it does not identify your users. Pair it with signed-in users and per-user limits.
4. Cap spend per end user
Every pattern above still lets a legitimate-looking user spend. The control that bounds that is a cap per end user, checked before the provider is called, so one account, one script or one compromised session cannot run up the whole month. Pass a stable, opaque user id with every request (never an email address), and refuse requests over the user's cap with a clear error your app can show.
A pre-release checklist
- Search the built bundle and the compiled app for provider key prefixes (
sk-,sk-proj-,sk-ant-,AIza) before every release. - No
dangerouslyAllowBrowser: truein production code. - Every Google API key embedded in an app (Maps, Firebase) is restricted, and the Generative Language API is not enabled in that project unless intended.
- The backend fixes model, parameters and tools; the client cannot choose them freely.
- Every AI endpoint requires a signed-in user and has a per-user rate limit and spend cap.
- Ephemeral credential endpoints authenticate before minting and use the shortest lifetime that works.
- A provider-side spend limit exists on the project or workspace the server key belongs to.
- You know how to revoke the server key in minutes; see secure LLM API keys.
How INFRO handles client-facing AI features
INFRO sits behind your backend, not in the client. An INFRO gateway key (sk_infro_) is a secret like any provider key and belongs on your server, never in a bundle or an app. With your backend calling INFRO:
- End-customer caps limit spend per end user, from the Team plan. Your server sends your opaque user id in
metadata.user_id(orX-INFRO-User-Id), a default rule caps every user, overrides change it for one, and a request over its cap is refused with402before your provider is called. - Model allowlists stop a request for a model the feature should not use, with
403 model_not_allowed. - Gateway key controls limit the key to the providers and environment the feature needs, and an IP allowlist set to your backend's egress addresses refuses a copied key used elsewhere with
403 ip_not_allowed. - Budgets on the key and project give the feature a hard ceiling, and guardrails on the Business plan can redact emails, card numbers and API keys users paste into prompts.
One limit to state plainly: INFRO governs requests that go through INFRO. If a provider key is ever shipped to a device or stolen from anywhere, it can be used directly against the provider and none of these controls see it. Keep a spend limit and usage monitoring at the provider as well, and revoke there first.
Summary
There is no safe way to ship a provider key in a frontend or mobile app. Keep keys on a server; authenticate users and fix model and limits there; for realtime, mint short-lived client secrets after checking the user; for Gemini on mobile, use Firebase AI Logic with App Check enforced; and cap spend per user so a single account cannot become your largest customer.
