Best Practices for Claude API Key Storage
If you're asking how to store your Claude API key safely, the short answer is: never in source code, never in client-side JavaScript, and never in a shared document. Keys belong in environment variables or a dedicated secrets manager, loaded at runtime, scoped to the minimum access needed, and rotated on a schedule.
The longer answer involves a few layers — where keys live at rest, how they're injected into your application, who can see them, and what happens if one leaks anyway. This article walks through each layer with concrete setups you can copy.
Why key storage matters more than people think
A leaked Claude API key isn't just a security embarrassment — it's a direct line to your billing account. Anyone with the key can make requests on your behalf, and depending on your rate limits and spend caps, that can mean a surprise invoice before you even notice. Keys that end up in public GitHub repos get scraped by bots within minutes in many documented cases, so "I'll just be careful" is not a storage strategy.
The goal is to make leaking a key hard by default, and recoverable fast if it happens anyway.
Never hardcode keys in source
This is the most common mistake and the easiest to fix. Hardcoded keys end up in git history even after you delete them from the current file — removing a line doesn't remove it from past commits.
// Don't do this
const client = new Anthropic({
apiKey: "sk-ant-api03-xxxxxxxxxxxx" // leaked the moment this is committed
});
Instead, read from environment variables:
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
Add .env to .gitignore before you add the key to .env, not after. If you've already committed a key, rotate it immediately — scrubbing git history is not a substitute for revoking the exposed credential.
Use environment variables correctly
Environment variables are the baseline, but they're not automatically secure. A few rules:
- Don't log them. Debug logs, error traces, and request dumps should never include the
Authorizationheader or raw key value. - Don't expose them to the frontend. Any variable prefixed for client-side bundlers (like
NEXT_PUBLIC_orREACT_APP_) gets shipped to the browser. A Claude key with that prefix is a public key. - Separate environments. Development, staging, and production should each have distinct keys so a compromised dev key doesn't touch production usage or billing.
# .env.local — never committed
ANTHROPIC_API_KEY=sk-ant-api03-...
Move to a secrets manager for production
Environment variables stored in .env files work for local development, but production systems should pull secrets from a dedicated manager rather than plaintext files on disk or in CI configuration:
- AWS Secrets Manager / Parameter Store for AWS-hosted apps
- HashiCorp Vault for self-hosted or multi-cloud setups
- Google Secret Manager or Azure Key Vault for their respective platforms
- Doppler or 1Password Secrets Automation for smaller teams who want a managed layer without running infrastructure
These tools give you access logging, automatic rotation hooks, and fine-grained IAM policies — so you can answer "who accessed this key and when" instead of guessing.
# Example: pulling a secret at deploy time instead of storing it in CI vars
aws secretsmanager get-secret-value --secret-id prod/claude-api-key \
--query SecretString --output text
Scope keys to the minimum needed
If your provider supports multiple keys per account, create separate keys per application or environment rather than reusing one key everywhere. This limits blast radius: if a key used by your internal admin tool leaks, it shouldn't also be the key powering your production customer-facing app.
This is one of the areas where SubToAPI (/docs/quickstart) differs from raw provider keys: instead of one shared credential, you issue scoped sub_live_ application keys from a dashboard, one per app or environment, each with its own usage visibility. If a key tied to a staging app gets exposed, you revoke that one key without touching production traffic. See /docs for the full key management flow.
Rotate keys on a schedule, not just after an incident
Rotation shouldn't be a reactive fire drill — build it into your routine:
- Generate a new key alongside the old one.
- Deploy the new key to your environment or secrets manager.
- Confirm traffic is flowing on the new key (check logs or dashboard usage).
- Revoke the old key.
- Repeat on a fixed interval — quarterly is a reasonable default for most teams, monthly for high-sensitivity environments.
Keeping both keys active briefly during the swap avoids downtime, which is why most providers let you have more than one valid key at a time.
Restrict access at the team level
Key storage isn't just a technical problem — it's an access control problem. If every engineer has direct access to the production secrets manager, your actual attack surface is "every engineer's laptop." Use role-based access so only deploy pipelines and a small number of senior engineers can read production keys directly; everyone else works through staging credentials or a proxy layer.
If you're managing a team around a single Claude account, giving every developer the raw provider key means revoking access when someone leaves requires rotating a key that's baked into multiple services. Tools with per-user seats — including SubToAPI's Team plan (/pricing) — let you remove an individual's access without regenerating the key everyone else depends on.
Monitor for anomalies
Even with good storage practices, keep an eye on usage patterns. A sudden spike in request volume, requests from unexpected IP ranges, or usage outside normal business hours are signs a key may have leaked despite your precautions. Review the usage and request metadata your API provider exposes regularly, not just when something looks obviously wrong.
A practical checklist
- [ ] No keys in source code or git history
- [ ]
.envfiles gitignored before keys are added - [ ] No
NEXT_PUBLIC_/REACT_APP_style prefixes on secret variables - [ ] Separate keys for dev, staging, and production
- [ ] Production secrets pulled from a secrets manager, not CI plaintext vars
- [ ] Rotation scheduled, not just incident-driven
- [ ] Access to raw keys limited to deploy pipelines and a few senior engineers
- [ ] Usage monitored for anomalies
Questions
Should I use the same Claude API key across dev, staging, and production? No. Separate keys per environment limit the damage if one leaks and make it easier to track usage and spend per environment without cross-contamination.
Where should I store a Claude API key for a serverless function? Use your cloud provider's secrets manager (AWS Secrets Manager, Google Secret Manager, etc.) and fetch the secret at cold start or via a configured environment variable injected by the platform — never bundle it into the deployment package.
What should I do if a Claude API key leaks publicly? Revoke the key immediately from your provider's dashboard, generate a replacement, deploy it, and review recent usage logs for unauthorized requests before assuming no damage occurred.