Claude Certification Program · v1.0 · Effective July 2026 · All four tracks open

Home › Study guides › CCDV-F › Domain 7 › Lesson 7.4

CCDV-F · Domain 7 · 8.1% of the exam · Lesson 7.4 · 21 min read

Secrets and key management: API keys, identity and access

Why a leaked API key is a live credit card, and how to store, scope, rotate and monitor Claude credentials and verify who is calling your app.

Written against skill 7.4 of the official CCDV-F exam guide (Version 1.0, effective July 2026). An independent resource, not affiliated with Anthropic; the practice questions are written from scratch.

7.4.1 Why one leaked key took down the whole app

Wrenly is a four-person startup with a mobile app for birdwatchers. Users log a sighting with a few notes and a photo. The app's back-end asks Claude to turn them into a tidy field entry, or to answer questions such as "chiffchaff or willow warbler?". The back-end is open source on GitHub. One Friday evening Selin, the back-end developer, pasted the Claude API key into settings.py to chase a bug, meaning to take it out again. The commit went out with the key in it.

Minutes later, every Claude feature in the app stopped working. GitHub's secret scanning had found the key in the public repository and reported it to Anthropic, which deactivated it and emailed Aurelio, the founder. That ended the leak, and it ended the app's Claude features too, because one key did everything: production, staging, both laptops and the nightly digest job. Nobody could say whether a stranger had used the key while it was public.

One key in every place

One API keypasted into settings.py
Production back-end
Staging server
Two laptops
Nightly digest job
A public commit
A single key served every environment, so one leak exposed all of them and switching it off stopped all of them.

An API key is the secret your code sends with every request to prove it may use your organization's Claude API account. Anthropic's guidance compares it to a credit card number: whoever holds it can spend on your behalf. The API checks that a key is valid, not who is holding it. Secrets management is the discipline of controlling where credentials live, what each one can do, and who is using it.

7.4.2 Keep secrets out of code, prompts and logs

Here is the question behind Wrenly's Friday: where may a secret live? The tempting answer is "somewhere private": a private repository, a config file on the server, a message to a colleague. Resist it. Every copy is one more copy to hunt down after a leak. And git keeps every commit, so deleting the line in a new commit leaves the key in history and in every clone.

The key lives in exactly one managed place and is handed to the program when it starts. In production that place is a secret manager, the encrypted store your cloud provider or a dedicated tool offers, which hands the key to the process, usually as an environment variable. It controls and records who reads each secret, and it turns rotation into a configuration change. On a laptop, the key goes in a .env file listed in .gitignore BEFORE the file exists, and a small library such as python-dotenv copies it into the environment at start-up. The Anthropic SDKs read ANTHROPIC_API_KEY from the environment, so the key never appears in your code.

Where the key sits Allowed? Why
Source code or a committed config file Never Every clone and every old commit keeps it
Inside the mobile or web app Never Anyone can pull strings out of an app package
A system prompt, message or tool result Never The model does not need it, and text in the context can be repeated in a reply
Logs, error reports, tickets, chat Never They are copied widely and kept for a long time
A .env file listed in .gitignore Development only Local and uncommitted, but still plain text on a laptop
A secret manager, injected as an environment variable Production Encrypted, access-controlled, audited and easy to rotate

Memorise the last two rows; every row above them is a way keys leak. The prompt row surprises developers new to LLMs. Your code authenticates to the API, so the model never needs your key. The same holds for a tool, a function your code offers the model, that calls another service. When Wrenly's assistant needs the weather for a sighting, the model asks for get_weather with a place and a date. Your tool handler then adds the weather service's token on the server. A secret that never enters the context can never come out of it.

Logs are the other quiet leak. A line that prints a whole request, a config object or an exception can carry a key into a logging service many people can read. Wrenly's back-end now refuses to start without its key and scrubs anything key-shaped from its logs. Look at load_dotenv(), which does nothing where no .env file exists, and at the raise line, which replaces a silent fallback to a hard-coded key. Then look at the filter on the handler, which every log record passes through.

import logging, os, re
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()          # development: copies .env (listed in .gitignore) into the environment
                       # production has no .env: the secret manager injects ANTHROPIC_API_KEY
if not os.environ.get("ANTHROPIC_API_KEY"):
    raise RuntimeError("ANTHROPIC_API_KEY is not set")   # FAIL FAST, no hard-coded fallback
client = Anthropic()                                     # the SDK reads the key from the environment

KEY_SHAPE = re.compile(r"sk-ant-[A-Za-z0-9_-]+")

class RedactKeys(logging.Filter):
    def filter(self, record):
        record.msg = KEY_SHAPE.sub("sk-ant-[REDACTED]", record.getMessage())  # SCRUB before writing
        record.args = ()
        return True

handler = logging.StreamHandler()
handler.addFilter(RedactKeys())                          # on the handler: covers every logger
logging.basicConfig(handlers=[handler], level=logging.INFO)

7.4.3 One identity per environment and workload

The second failure at Wrenly was the leak's reach. One key was switched off and five jobs stopped, because the leaked copy and production were the same credential. Ask of any credential: if this one leaks, what does it expose, and what stops when you switch it off? The answer should be "very little". Getting there takes one credential per environment and workload, each allowed only what its job needs. That principle is least privilege. A hotel works this way: each guest's card opens one room for one stay, and losing it does not mean changing every lock.

The Claude Console, the web dashboard where your organization manages keys, members and billing, gives you the container for that separation. A workspace groups API keys, members and limits inside one organization, and Anthropic's docs suggest separate workspaces for development, staging and production. A key scoped to one workspace reaches only that workspace's resources, such as its files and message batches. Each workspace can have spend and rate limits below the organization's, plus spend alerts, so a runaway staging test hits staging's ceiling, not production's. The Default Workspace cannot take limits, one more reason to keep production out of it.

Inside each workspace, what a key acts as matters as much as where it sits. A person can hold a key, or a service account can: a non-human identity an organization admin creates for one workload, so the workload never borrows a person's key. You choose the key's type when you create it.

Key type Acts as Stops working when
Personal key You, with your roles You leave the organization, or lose access to its workspace
Service account key A named, non-human identity for a workload The service account is archived or removed from the workspace
Workspace key (legacy) Nobody; it belongs to the workspace It expires, is disabled or deleted, or its workspace is archived; its creator leaving changes nothing

Learn the first two rows: personal keys for people, service account keys for anything shared or automated, such as production and continuous integration (CI) jobs. A personal key shared by a team acts as one person and stops working when that person leaves. Every key also gets a lifetime at creation, which you cannot change later. Choose a preset from 3 hours to 30 days, a custom duration, or "never" for keys you keep in a secret manager and rotate yourself. Rotation means creating a new key, deploying it, confirming traffic, then deleting the old one, on a schedule such as Anthropic's example of every 90 days.

Workload Identity Federation goes further for workloads that already have a cloud identity. The workload trades a short-lived token from its own identity provider, such as AWS or GitHub Actions, for a short-lived Claude API token, so there is no static key to leak. Laptops count as an environment too. Claude Code, Anthropic's coding agent, can sign in with each developer's own account instead of a shared key, or fetch a short-lived credential from a vault through its apiKeyHelper setting. A deny rule such as Read(./.env) in its settings keeps the agent out of the file that holds the key.

Wrenly before and after

Before

Default Workspaceno limits possible
One keylaptops, staging, production, digest job
One leak stops everything

After

Developmentpersonal keys, low limits
Stagingservice account key, small spend cap
Productionservice account keys, alerts
Before, one key did every job; after, each environment has its own workspace, credential and limits, so a leak stays small.

7.4.4 Who is asking, and what may they do?

Wrenly has a second identity problem, beyond its key: who is the person typing? Every request carries Wrenly's service credential, so Anthropic sees Wrenly, never the individual birdwatcher. Knowing the user is your application's job. Claude cannot check an identity, and "I'm a Wrenly Plus member" in a message is just text.

Authentication, or identity validation, proves who the user is, on every request, before any prompt is built. Wrenly's app signs users in and receives a session token. The back-end verifies the token's signature and expiry and takes the user ID from the token, never from a field the app sends alongside it. That ID decides which sightings go into the request. Wrenly also sends a hashed user ID in metadata.user_id, which Anthropic may use to help detect abuse. The docs ask for an opaque value such as a hash or UUID, never a name, email address or phone number.

Level verification asks the next question: does this identity hold the level the action requires? Wrenly Plus users can ask questions answered from their whole sighting history; free users cannot. The back-end reads the plan from its own database and, for a free user, neither loads the history nor offers the tool that fetches it. A boarding gate scans your pass rather than taking your word that you fly business class. A system-prompt line such as "only help Plus members" is the passenger's word, and one persuasive message can talk past it.

Identity and level are settled before Claude is called

SIGN INthe app receives a session token
VERIFYsignature and expiry, user ID from the token
CHECK LEVELplan and role from your database
BUILDonly this user's data and allowed tools
CALL CLAUDEwith Wrenly's key
Your back-end verifies who the user is and what they may do, then builds a request containing only what that user is entitled to.

The same checks apply to your team in the Console. Each member has an organization role and a role in each workspace they belong to. Adding someone to a workspace is access approval: only an admin can do it, so every grant is a deliberate decision someone can be asked about. Organization admins automatically administer every workspace, so keep them few. At Wrenly, Aurelio is the only admin. Selin is a developer in Development and Staging with no role in Production, which runs on service account keys that Aurelio writes straight into the secret manager.

Workspace role What it allows Who holds it in Wrenly's Production workspace
Workspace User Playground only Nobody
Workspace Developer Create and manage API keys, use the API Nobody; production runs on service accounts
Workspace Admin Full control of the workspace's settings and members Aurelio, through his organization admin role
Workspace Billing View billing; inherited from the organization billing role The part-time bookkeeper

There is also a Limited Developer role, a Developer without access to session traces and file downloads; learn the principle rather than the list. Each person gets the lowest role that does their job, in only the workspaces they need, reviewed on a schedule.

7.4.5 Watch every key, and know what to do when one leaks

Wrenly learned of its leak from an email. Most leaks are quieter: a key in a private repository, a CI log or a ticket is never scanned, and the first sign is a bill. Authorized access monitoring closes that gap. It means checking continuously that each credential is used only by its own workload, at the volume you expect, and that the people who can touch keys are still the right people.

Three sources do most of the work. The Console shows usage and logs per key, and workspace spend alerts warn you before a limit is reached. The Usage and Cost API returns token usage grouped by API key, workspace or model, and a request usually shows up in it within about five minutes. And an organization that has turned on the Compliance API can query its Activity Feed, a per-event audit trail of who did what, such as creating a key or adding a workspace member.

Wrenly's monitor runs hourly with an Admin API key, a separate sk-ant-admin credential for the endpoints that manage the organization and report its usage. Only admins can create one, and it reaches the whole organization, so it lives in this job's secret and nowhere else. Look at group_by[], which splits the report by key, and at the last if, which fires for an unknown key as well as for a known key over its ceiling.

import os, httpx
from datetime import datetime, timezone

CEILING = {"apikey_01Prod...": 3_000_000, "apikey_01Staging...": 150_000}  # output tokens per day, by key ID
today = datetime.now(timezone.utc).strftime("%Y-%m-%dT00:00:00Z")
report = httpx.get(
    "https://api.anthropic.com/v1/organizations/usage_report/messages",
    headers={"x-api-key": os.environ["ANTHROPIC_ADMIN_KEY"],   # ADMIN key: this job only, never the app
             "anthropic-version": "2023-06-01"},
    params={"starting_at": today, "bucket_width": "1d", "group_by[]": "api_key_id"},
).json()

used = {}
for bucket in report["data"]:
    for row in bucket["results"]:
        if row["api_key_id"]:                                 # Console playground usage has no key
            used[row["api_key_id"]] = used.get(row["api_key_id"], 0) + row["output_tokens"]
for key_id, tokens in used.items():
    if tokens > CEILING.get(key_id, 0):                       # UNKNOWN key, or a known key over its ceiling
        send_alert(f"{key_id}: {tokens} output tokens today")   # your pager or chat webhook

When an alert fires, order matters. Revoke first, because a valid key keeps working for whoever holds it. Disabling can be undone if you need the key back; deleting cannot. Then replace it through the secret manager, review what the old key was used for during the exposure, and repair the path it leaked through.

Responding to a leaked key

REVOKEdisable or delete it now
REPLACEnew key, straight into the secret manager
REVIEWthe old key's usage while exposed
REPAIRscanning, redaction, scoped keys
Revoke first, because nothing else makes the leaked copy useless; then replace, review and repair.

7.4.6 The exam traps

The mistakes here come in two kinds: a secret copied somewhere it can escape, or trust placed in something nobody verified. Questions describe the consequence and ask for the fix.

  • ✗ Deleting the key from the code in a new commit, or making the repository private. ✓ Revoke it and issue a new one; history and clones keep the old key, which works until it is revoked.
  • ✗ Shipping the key inside the mobile or browser app, even obfuscated. ✓ Keep it on your server; the app authenticates its user to your back-end, which calls Claude.
  • ✗ Putting a key or token in the prompt so Claude can call a service. ✓ The tool handler attaches the credential on the server; the model sends only business arguments.
  • ✗ One key for every environment and every person. ✓ Separate workspaces and keys per environment and workload, with personal keys for people and service accounts for services.
  • ✗ Letting the prompt or the model decide who the user is or which plan they hold. ✓ Authenticate and verify the level in your back-end before the request is built.
  • ✗ Treating scheduled rotation or a spend limit as your monitoring. ✓ Watch usage per key with alerts. Rotation shortens an unknown leak and a limit caps the bill; neither tells you a leak happened.

7.4.7 Put it together: lock down a Claude back-end

You now have every piece. Each secret has one managed home, each workload its own scoped identity, users are verified in your own code, and monitoring catches misuse early. To make it stick, rebuild Wrenly's set-up in miniature, then break it on purpose.

The next domain reuses these rules. In tool implementation (8.1), your handler, not the model, attaches credentials for external systems and checks what each user may do. MCP server development (8.2) moves that handler into a shared server, which must authenticate each calling application and keep upstream secrets on its own side.

Key takeaways

  • ✓ An API key works for whoever holds it, like a credit card number, so the fewer places it lives, the safer it is.
  • ✓ Secrets live in a secret manager in production or an ignored .env file in development and reach the code as environment variables, never in code, client apps, prompts or logs.
  • ✓ Each environment and workload gets its own scoped credential: separate workspaces with their own limits, personal keys for people, service accounts or federation for services, and an expiration or rotation schedule.
  • ✓ Your application authenticates each user and verifies their level on the server before building a request; the model cannot check identity, and a prompt rule is not access control.
  • ✓ An admin approves every grant of access, each person holds the lowest role in the fewest workspaces, and the list is reviewed regularly.
  • ✓ Monitor usage per key and workspace with alerts; when a key leaks, revoke it first, then replace it, review its usage and repair the path it leaked through.

Check your understanding

4 questions written for this lesson, then one from the CCDV-F question bank on the same topic. Every answer option is explained, including the ones you did not pick. Nothing is stored.

12 CCDV-F questions on Domain 7, free

Every question in the bank is tagged to a domain, so you can drill 12 questions on Security and Safety alone, or sit the full 53-question timed simulator.

Open the CCDV-F question bank → Back to Domain 7 →

The question bank is free. It asks for an account only because the quiz engine has to store answers to score them and show which domains are weak. The questions on this page need nothing.

Sources