← Blog

Claude API Environment Variables: Security Best Practices

2026-10-24 · 6 min read · SubToAPI Team

If you're searching for how to handle Claude API keys safely, the short answer is: never hardcode them, never commit them, store them in environment variables scoped to the narrowest possible context, and rotate them on a schedule plus whenever exposure is suspected. The rest of this guide covers exactly how to do that across local development, CI/CD pipelines, and production deployments without breaking your workflow.

Claude API keys (and similarly, keys for any wrapper service like SubToAPI) are bearer credentials — whoever holds the string has full access to whatever that key is scoped to. Treating them with the same care as a database password or a signing secret is not optional once you move past a weekend prototype.

Why Environment Variables (Not Config Files)

Environment variables are the standard mechanism for injecting secrets into a running process without writing them to disk in a readable file that might get committed, backed up, or synced to a laptop. Compared to the alternatives:

The tradeoff is that environment variables are visible to anything that can read the process environment — child processes, crash dumps, and some logging middleware. That's manageable with the practices below, but it's worth knowing the limitation.

Local Development

Use a .env file that is explicitly listed in .gitignore before the first commit, not after:

# .gitignore
.env
.env.*
!.env.example

Keep a .env.example with placeholder values checked into the repo so teammates know what variables are expected:

# .env.example
ANTHROPIC_API_KEY=sk-ant-xxxxxxxx
SUBTOAPI_KEY=sub_live_xxxxxxxx

Load variables with a library like dotenv rather than exporting them in your shell history, where they can leak via history files or terminal multiplexer logs:

require('dotenv').config();

const apiKey = process.env.SUBTOAPI_KEY;
if (!apiKey) {
  throw new Error('SUBTOAPI_KEY is not set');
}

Fail fast if a required variable is missing — don't let the app silently fall back to undefined and produce a confusing 401 three layers deep.

CI/CD Pipelines

CI systems (GitHub Actions, GitLab CI, CircleCI) all provide encrypted secret storage separate from your repo and separate from build logs. Use it instead of pasting keys into .yml files:

# GitHub Actions example
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run integration tests
        env:
          SUBTOAPI_KEY: ${{ secrets.SUBTOAPI_KEY }}
        run: npm test

A few rules specific to CI:

Production Deployments

In production, environment variables should come from your platform's secret manager rather than a .env file sitting on the server:

# Bad: baked into the image layer
docker build --build-arg ANTHROPIC_API_KEY=sk-ant-xxxx .

# Better: injected at runtime
docker run --env-file .env.production myapp

Key Scoping and Rotation

Not all keys need the same level of access. If you're building an application on top of Claude, consider issuing separate keys per environment and per team member rather than sharing one master key across your whole organization. This limits blast radius if one key leaks — you revoke that single key instead of rotating everything downstream.

SubToAPI applies this directly: each application gets its own sub_live_... key from the dashboard, usage is tracked per key, and you can revoke an individual key without regenerating credentials for your whole team. That makes it easier to scope access by project, by environment, or by developer, and to set up team seats where each member works under their own key rather than a shared secret passed around in a chat thread. See /docs/quickstart for how key issuance works end to end.

Rotation practices worth adopting regardless of provider:

  1. Rotate keys on a fixed schedule (quarterly is reasonable for most teams).
  2. Rotate immediately if a key appears in a log, a public repo, a bug report, or a support ticket.
  3. Keep the old key active for a short overlap window when rotating in production, so in-flight requests don't fail mid-deploy.
  4. Audit which keys exist and who/what uses each one — unused keys are the easiest ones to forget and the easiest ones to leak.

Logging and Error Handling

A surprising number of leaks come from well-intentioned debug logging. Two concrete habits prevent this:

try {
  const response = await fetch('https://api.subtoapi.app/v1/messages', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.SUBTOAPI_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });
} catch (err) {
  // Log the error message, not the request config
  console.error('Request failed:', err.message);
}

For full request/response shapes, see /docs/messages, and for streaming-specific error handling, /docs/streaming.

Checklist

questions

Do I need a different Claude API key for each environment? Yes. Using the same key in dev, staging, and production means a leak in a lower-security environment (like a local laptop) compromises production access too. Separate keys let you revoke one without affecting the others.

Is it safe to use environment variables if my server is compromised? Not fully — environment variables are readable by anything with process access on that machine. They protect against accidental leaks (commits, logs, config files) but not against a fully compromised host. Pair them with a secret manager and least-privilege key scoping.

How often should I rotate API keys? A quarterly schedule is a reasonable baseline for most teams, but rotate immediately and without waiting for the schedule if a key shows up anywhere it shouldn't — a log file, a public repo, a shared screenshot, or a support ticket.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →