Guides / Prompting and shipping

How to Keep API Keys Safe in Your App

Keep API keys out of your code, browser and chat: store them as secrets, use them only on the server, restrict them, and rotate any key that leaks.

Mythex Team · 2026-09-29 · 6 min read

To keep API keys safe, store them as secrets or environment variables on your host, use them only in server-side code, and never paste them into chat, code files, screenshots or a Git repository. Give each key the least permission it needs, set spending limits at the provider, and if a key ever leaks, rotate it — create a new one and delete the old — rather than just hiding where it appeared.

An API key is a password for a service. Your OpenAI key lets someone spend your money on AI; your Stripe secret key lets someone issue refunds; your email provider key lets someone send mail as you. AI app builders are good at wiring these in and not always careful about where they end up, so this guide covers how to keep them safe and how to check.

Public keys vs secret keys

Not every key is secret. Knowing the difference stops you from panicking about the wrong one and ignoring the right one.

TypeExamplesCan it be in the browser?
Publishable / public keysStripe pk_… key, a maps key restricted to your domain, some analytics IDsYes — designed for it
Secret keysStripe sk_…, OpenAI and Anthropic keys, email provider keys, database passwordsNever
Service/admin keysKeys that bypass access rules on a hosted databaseNever — treat as the most sensitive

If you're not sure which kind a key is, check the provider's documentation. When in doubt, treat it as secret.

Step 1: Store keys as secrets, not in code

Keys belong in your host's environment variables or secrets settings. Your code reads them by name at runtime (for example process.env.OPENAI_API_KEY), so the value never appears in your files. For the background, see what environment variables and secrets are.

Move every API key out of the code into environment variables. List each key you found, which file it was in, and the variable name you used. Don't show me the values.

Then check nothing is left:

Search the whole project, including config files and any .env files, for anything that looks like an API key or password. Report the file and line, not the value.

Step 2: Use secret keys only on the server

This is the rule that matters most. Anything the browser receives, a visitor can read — the page source and JavaScript files are all visible in developer tools.

So if the app needs to call OpenAI, the browser should call your server, and your server calls OpenAI with the key. The key never leaves the server.

The chat feature calls OpenAI directly from the browser. Move that call to a server API route that reads OPENAI_API_KEY from the environment. The browser should only call our route. Require login for the route.

Watch for one common trap in frontend frameworks: variables with a public prefix — VITE_ in Vite, NEXT_PUBLIC_ in Next.js — are built into the browser code on purpose. A secret key with one of those prefixes is exposed, even though it's "in an environment variable".

Step 3: Test that nothing leaks

Don't trust that it worked — check the live site:

  1. Open the published app in a browser.
  2. Open developer tools, then the Sources or Network tab.
  3. Search across files for the first characters of each secret key (for example sk_ or sk-).
  4. Check the network requests the app makes. A request going straight from the browser to a paid AI provider is a red flag.

If you find a secret key, move it to the server (step 2) and rotate it (step 6), because it was already public.

Step 4: Restrict what each key can do

Many providers let you limit a key:

  • Scoped or restricted keys that can only do what your app needs. Stripe, for example, supports restricted keys with specific permissions.
  • Domain or IP restrictions for keys that must be public, such as maps keys.
  • Separate keys per app and per environment, so one leak doesn't expose everything, and revoking one doesn't break the others.
  • Test keys while building, and live keys only in the published app.

Step 5: Put a ceiling on damage

Even a well-protected key can be misused through your own app — someone scripting your AI feature thousands of times, for example.

  • Set spending limits or alerts at every paid provider.
  • Require login for any feature that costs money per call.
  • Add a per-user rate limit. See what rate limiting is.

Add a limit of 30 AI requests per user per hour to /api/chat. Return a clear message when the limit is hit. Reject requests from users who aren't logged in.

Step 6: Rotate keys that leak

If a secret key appears somewhere it shouldn't — a chat message, a commit, a screenshot, a support ticket, browser code — assume it's compromised.

  1. Create a new key at the provider.
  2. Update the secret in your app's settings.
  3. Redeploy or publish again so the live app uses the new key.
  4. Delete the old key at the provider.
  5. Check the provider's usage logs for activity you don't recognise.

Deleting the chat message or Git commit is not enough. Git history keeps old versions, and anything public may already have been copied.

Common mistakes

  • Pasting a key into the prompt. It's now in the chat history. Use a secrets form instead.
  • A public prefix on a secret variable. VITE_OPENAI_API_KEY ships the key to every visitor.
  • Committing a .env file. Make sure it's in .gitignore before the first push.
  • One key everywhere. Use separate keys for test and live, and for each app.
  • No spending limit. A leaked or abused key with no cap can run up a large bill before you notice.
  • Hiding instead of rotating. Once a key has been exposed, only a new key fixes it.
  • Keys in screenshots. Crop or blur settings pages before sharing them for help.

Checklist

  • Every key is stored as a secret or environment variable, not in code.
  • No .env file or key is committed to Git.
  • Secret keys are used only in server-side code.
  • No secret variable uses a public prefix like VITE_ or NEXT_PUBLIC_.
  • I searched the live site's JavaScript for each key's prefix and found nothing.
  • Keys are scoped or restricted where the provider allows it.
  • Test and live keys are separate.
  • Paid features require login and have per-user limits.
  • Every paid provider has a spending cap or alert.
  • I know how to rotate each key, and any key that was ever exposed has been rotated.

Keeping keys safe on Mythex

Mythex keeps keys out of your code and chat in two ways:

  • Secrets request card. When the agent needs a key, it shows a card in chat where you enter the value in form fields, not the message box, and it's stored as a project secret. See Secrets in chat.
  • Project settings → Secrets, or /secrets in chat, to add or change keys yourself. See Environment variables and secrets.

After changing a secret for a published app, publish again so the live app picks it up. Exported projects leave secrets out, so re-add them wherever you run the code next. If a key ever appears in chat, rotate it at the provider.

For the rest of the pre-launch security pass, work through the security checklist for AI-built apps. If you're adding AI features, how to use LLM APIs covers keys and costs in more depth.

Questions

Is it safe to put an API key in frontend code?

Only if the provider designed that key to be public, such as Stripe's publishable key or a maps key restricted to your domain. Any key that can spend money or read private data must stay on the server, because anything sent to the browser can be read by anyone.

What should I do if I pasted an API key into a chat or a public repo?

Rotate it: create a new key at the provider, update your app's secrets, publish again, then delete the old key. Deleting the message or commit is not enough, because copies may already exist.

Where should API keys be stored?

In your host's environment variables or secrets settings, read by server-side code at runtime. They should not be written into source files, committed to Git, or included in screenshots.

How can I tell if my API key is exposed in my website?

Open your live site, view the page source and the JavaScript files in the browser's developer tools, and search for the start of the key. If it appears, it's exposed and should be moved to the server and rotated.

Keep reading

  • How to Publish an App on Google Play: The Real Play Console Steps — How to publish an app on Google Play: developer account, Create app, store listing, App content forms, the 12-tester closed test and production release.
  • How to Publish an App on the App Store: TestFlight to Approval — How to publish an app on the App Store: Developer Program, App Store Connect, TestFlight, listing, App Privacy, submitting for review and rejections.
  • How to Use Google AI Studio: Playground, Build Mode and Vibe Coding With Gemini — How to use Google AI Studio: test Gemini in the Playground, get an API key, vibe code an app in Build mode, and know when to move to a full-stack builder.
  • Is Vibe Coding Safe? The Real Risks and What to Check Before You Publish — Is vibe coding safe? It can be. The real risks (data leaks, exposed keys, abuse), how to keep secrets safe, and a 30-minute check before you publish.
  • Vibe Coding for Beginners: How to Start, Step by Step — A vibe coding tutorial for complete beginners: pick a tool, write a first prompt, test, fix and publish a small app in one afternoon. No coding needed.
  • 30 Vibe Coding Prompts You Can Copy (Cheat Sheet) — 30 vibe coding prompts you can copy and paste, grouped by stage: first build, planning, design, data, fixing bugs, testing, security and publishing.

Start building free · Templates · Docs

አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)