MMakerToLaunch

Glossary

What Are API Keys?

An API key is a secret string your app uses to access a third-party service — OpenAI, Stripe, SendGrid, Supabase, and hundreds of others. Anyone with the key can often spend money, read data, or impersonate your app. If you built your app with an AI coding tool, your keys may already be in the wrong place. Treating them safely is non-negotiable before launch.

Updated July 2026 · 10 min read

Written for AI makers using tools like Cursor, Bolt, Lovable, Replit, Claude, and ChatGPT.

Quick answer

API keys are like passwords for automated service access. Store them in environment variables — a .env file locally and your hosting dashboard in production. Never commit them to GitHub or expose them in frontend JavaScript. If you accidentally shared a key, rotate it immediately.

Who this is for

  • Your AI tool created a .env file full of keys you do not recognize
  • You are unsure whether Stripe or OpenAI keys can go in GitHub
  • You want to understand the difference between public and secret keys
  • You just deployed your app and want to confirm keys are stored correctly

A simple definition

When your app calls an external API — to generate text, charge a card, send email, or fetch weather — the service needs to know the request is really from you. An API key is that proof: a long random string tied to your account.

You paste the key into your app's configuration. Server code includes it in request headers (Authorization: Bearer sk-..., or X-API-Key: ...). The provider checks the key, applies rate limits and billing to your account, and returns data.

Keys are not encryption. They are identifiers with privileges. If someone copies your Stripe secret key, they can create charges. If someone copies your OpenAI key, they can run models on your bill.

Why API keys matter before launch

AI coding tools generate integrations fast — and often drop real keys into .env files or even source code. First-time makers upload the whole folder to GitHub without reviewing. Within minutes, bots scan public repos for key patterns and abuse them.

Launch multiplies exposure. Production keys often have higher limits than test keys. A leaked production Stripe key can process real payments; a leaked OpenAI key can burn through credits overnight.

Before sharing any public URL, confirm keys are not in your repo history, not in client-side JavaScript, and rotated if they were ever exposed. These are launch-blockers, not nice-to-haves.

Where API keys should go

Local development: a .env file in your project root, listed in .gitignore. Your code reads process.env.OPENAI_API_KEY, os.environ['OPENAI_API_KEY'], or the equivalent for your stack. The .env file stays on your laptop — it never goes to GitHub.

Production: your hosting dashboard's environment variables panel. On Vercel, that is Project → Settings → Environment Variables. On Railway, it is your service's Variables tab. On Render, it is Environment → Environment Variables. You type the same variable names but paste your production key values.

Sharing with teammates: a password manager or secrets vault, never Slack, email, or a committed file. Your teammates each maintain their own local .env with their own test keys. Commit .env.example with placeholder values so teammates know what variables the app needs.

Where API keys should NOT go

Never in source code files (.js, .ts, .py, etc.) as string literals. Even if you delete the line later, the value lives in Git history and can be extracted.

Never in GitHub — not in .env files, not in comments, not in README examples with real values. Even private repositories expose keys to every collaborator, and repository visibility can change.

Never in frontend JavaScript that the browser downloads. Anything in your bundle — including environment variables prefixed NEXT_PUBLIC_ or VITE_ — is visible to every user who opens DevTools. Backend API calls should proxy requests rather than send keys to the browser.

Never in screenshots, screen recordings, Notion pages, or support tickets. Keys embedded in images are readable. Paste placeholder strings when demonstrating configuration.

API keys in frontend vs backend apps

Frontend apps (React, Vue, plain HTML) run in the browser. There is no safe way to include secret API keys — the source code ships to the user's machine. If your AI-built frontend calls OpenAI directly, that key is visible to anyone with browser DevTools.

The correct pattern: create a backend route (a Next.js API route, a Django view, a Node Express endpoint) that receives requests from your frontend, makes the API call server-side with the key stored as an environment variable, and returns only the safe response data to the browser.

Some SDKs offer client-safe versions: Stripe's publishable key for frontend checkout widgets, Supabase's anon key for client SDKs when row-level security is configured correctly. Read the provider's documentation before trusting any key in the browser.

API keys and .env files

A .env file is a plain text file in your project root that stores environment variables for local development. Each line has the format KEY=value, for example OPENAI_API_KEY=sk-proj-abc123. Your application reads them when it starts; they are never baked into your built code.

The .env file must be listed in .gitignore — that one-line addition to .gitignore prevents the file from ever being committed to Git. Verify it is there before your first push. If .env already shows up in GitHub Desktop's file list, add it to .gitignore before committing.

Use separate .env files for different environments if your setup supports it: .env.local for local overrides, .env.test for test runs, .env.production for build-time public variables. The naming conventions vary by framework — check your framework's documentation.

.env vs .env.example

.env.example is a safe template that you commit to GitHub. It lists every variable your app needs but uses placeholder values — OPENAI_API_KEY=your_key_here instead of a real key. It tells collaborators (and your future self) what to fill in without exposing real secrets.

When someone clones the project, they copy .env.example to .env and paste their own real values. The real .env is excluded by .gitignore. This two-file pattern is the standard way to document required secrets without leaking them.

If your project does not have a .env.example yet, create one. List every variable from your .env with placeholder strings as values. Commit it. This is a small step that prevents significant confusion and security problems.

Publishable vs secret keys

Payment providers often give two keys. Stripe's publishable key (pk_live_...) is designed for frontend checkout widgets — limited power, relatively safe in browsers. The secret key (sk_live_...) must stay server-side only. Never send it to the browser.

OpenAI, Anthropic, and most AI providers issue keys that are always secret. There is no safe browser exposure — route AI calls through your backend.

Supabase and Firebase use anon keys for client SDKs with row-level security rules, plus service role keys that bypass security and must never ship to browsers. Read each provider's documentation — naming varies across services.

If a key leaks or was accidentally committed

Assume compromise if a secret touched GitHub, was pasted in a screenshot, or appeared in client-side code. Rotation is urgent, not optional. Open the provider dashboard, revoke the old key, generate a new one, update your local .env and hosting env vars, and redeploy.

Removing the file from your latest commit is not enough — Git history still contains the exposed value. Bots continuously scan commit history. Rotate the key regardless of whether you clean up history; then use git filter tools or GitHub's guidance on removing sensitive data from history.

Check your billing dashboard for unexpected usage. Report significant abuse to the provider — many have processes for reversing fraudulent charges when you report promptly after discovering an exposure.

Common mistakes

  • Committing .env to GitHub

    How to fix it: Add .env to .gitignore before the first commit. Use .env.example with fake placeholders. Run a safe-upload check before pushing.

  • Putting secret keys in NEXT_PUBLIC_ or VITE_ variables

    How to fix it: Those prefixes expose values to browsers. Keep secrets in server-side code or API routes only.

  • Hardcoding keys in source files because the AI did it

    How to fix it: Move values to environment variables. Search the codebase for sk-, pk-, api_key, and bearer patterns before deploying.

  • Using production keys in development

    How to fix it: Use test or sandbox keys locally when providers offer them. Limits blast radius if a dev copy leaks.

  • Never rotating after a suspected leak

    How to fix it: Revoke immediately. Provider dashboards make rotation fast — doing nothing costs money and data.

  • Calling AI or payment APIs directly from frontend JavaScript

    How to fix it: Create a backend route that makes the API call server-side. Return only safe response data to the browser.

Copy-ready prompt

Prompt: audit API key handling before launch

Paste this into Cursor, Claude, ChatGPT, Bolt, Lovable, or your AI coding tool.

Ready to paste

Review this project for API key and secret handling before deployment.

Tasks:
1. Find any hardcoded API keys, tokens, passwords, or secret-like string values in source files.
2. Check that all secrets are read from environment variables, not hardcoded.
3. Confirm that no secret keys use NEXT_PUBLIC_, VITE_, or similar browser-exposure prefixes.
4. Verify that .env is listed in .gitignore and not committed.
5. Create or update .env.example with placeholder values for every real secret in .env.
6. Identify any API calls made directly from frontend code that should be proxied through a backend route.
7. Summarize what you changed and tell me which provider dashboards I need to visit to set production environment variables.

Paste this into Cursor, Claude, ChatGPT, Bolt, Lovable, or your AI coding tool.

Ready check

Beginner checklist

  • Every API key is in a .env file, not hardcoded in source code
  • .env is listed in .gitignore and not visible in GitHub Desktop's file list
  • .env.example exists with placeholder values for every variable
  • No secret keys use NEXT_PUBLIC_ or VITE_ prefixes
  • AI and payment API calls go through a backend route, not directly from the browser
  • Production keys are entered in the hosting dashboard environment variables panel
  • Test or sandbox keys are used locally, not production keys
  • Keys have been rotated if they ever appeared in GitHub history or client-side code
  • Billing dashboards checked for unexpected usage after any suspected exposure

Frequently asked questions

Are API keys the same as passwords?
Similar sensitivity. Passwords authenticate humans; API keys authenticate software. Both grant access and must stay private. Treat them with the same care.
Can I put API keys in GitHub if the repo is private?
Better than public, but still risky — collaborators, forks, and future visibility changes expose them. Use environment variables and .gitignore instead.
What is .env.example for?
A template listing variable names with fake values. It documents what keys your app needs without exposing real secrets. Safe to commit.
How do hosts get my API keys?
You paste them into the host's environment variables UI. The host injects them at runtime — no .env file on the server required.
Do I need different keys for staging and production?
Recommended when providers support separate projects or test modes. Keeps staging experiments off your production bill and limits damage if staging keys leak.
My app worked before but the API calls fail after deployment. What happened?
The host does not have your environment variables yet. You need to add each key to the hosting dashboard's environment variables panel, then redeploy. The .env file stays on your laptop — it does not travel with the code.
How do I know if my AI tool put keys in the wrong place?
Search the project for patterns like sk-, pk-, Bearer, api_key, and your actual key values. If any appear in .js, .ts, or .py files as string literals rather than process.env.X references, they are hardcoded and need to be moved.