## What you are holding

An API key: 43 opaque characters, with no prefix and no marker. It carries no
hint of what it opens or who issued it. It is a bearer credential — whoever
holds it can read what you can read, until it is revoked.

It is never meant to run client-side. A key in a mobile app, a browser bundle,
or a public repository is a key anyone can read. Keys live on your server,
never leave it, and are called from server-to-server requests only.

Because keys do not expire, a leaked key stays useful to whoever found it until
somebody notices. That is the trade for not having to renew them, and it is why
the rest of this page matters.

## Never commit a key

A key looks like any other random string, which cuts both ways: it gives away
nothing on sight, and **it cannot be found by grepping for a pattern**. There
is no prefix to match, so detection has to work on entropy and on context
rather than on shape.

Scan with a secret scanner that detects high-entropy strings — these find
opaque credentials that pattern rules miss:

```bash
gitleaks detect --source . --redact
```

And catch the common shape of a mistake, which is the variable name rather
than the value:

```bash
git diff --cached | grep -nE '(STYLUMIA_KEY|api[_-]?key)\s*[=:]\s*["\x27]?[A-Za-z0-9_-]{40,}'
```

Run both in CI against a pull request's full diff, not just the latest commit —
a key committed once and reverted is still in the repository's history, and
still works until it is revoked.

Because detection is weaker than it would be with a branded prefix, the
placement rules below carry more of the weight. Treat them as the control, not
the backstop.

## Where to put it

1. A secrets manager — first choice.
2. An environment variable, read at start-up — acceptable.
3. Never in code, config checked into git, or an error page. A stack trace that
   includes your request headers is a leak, not a debugging convenience — scrub
   it before you log it.

If your logs capture request headers, redact `Authorization` at the logger, not
at each call site. One missed call site is one leaked credential.

## Blast radius is bounded by construction

A key is bound to a team and cannot widen its own access (see
[Authentication](/docs/authentication)). Stated plainly: the worst case for a
leaked key is that it can read your team's
[catalog slice](/docs/coverage-freshness) until you revoke it. It cannot mutate
anything, delete anything, or spend anything — every [endpoint](/reference) on
this surface is a read.

## Rotation without downtime

Because a team can hold several keys at once, rotation needs no maintenance
window:

1. Create a new key in the [console](/app/keys).
2. Deploy it to whatever calls the API.
3. Confirm the new key is serving traffic — the console's **Last used** column
   tells you.
4. Revoke the old one.

Revocation is immediate and permanent, so do not revoke the old key until the
new one is confirmed live. Rotate on a schedule you choose; nothing forces it.

## If a key leaks

1. **Revoke it now**, from the console. It stops working on the very next
   request — there is no cache to wait out and no propagation delay.
2. Create a replacement and deploy it.
3. Email security@stylumia.com so [we can check](/docs/security) what the leaked
   key was used for. Include roughly when and where it was exposed.

A key posted publicly for five minutes and one posted for five months are
different incidents — exposure is not the same as confirmed compromise. Treat
both the same way operationally: revoke first, ask questions after. Revoking
costs you one deploy; not revoking costs you an unknown.

**We will never ask you for your API key.** Not in an email, not in a support
ticket, not over a call. If anything claiming to be Stylumia asks for it, it
isn't us.
