# API key handling

URL: /systems/trust-and-governance/api-keys · Id: `page:systems/trust-and-governance/api-keys`

> How keys work for your code, your agents and your customers, each scoped to its job, rolled without downtime and revoked on the next call.

Three kinds of caller hold keys: your own code, the agents in your [Roles](/business/nouns/role), and the customers of your API. Every key reaches one scope and stops on the next call once revoked.

## Your code and agents
| Who | Holds | Lifetime |
| --- | --- | --- |
| Server code and unattended agents | A secret key, `sk_test_` or `sk_live_` | Until revoked |
| Your own [Site](/business/nouns/site) and [App](/business/nouns/app) in the browser | A publishable key, `pk_test_` or `pk_live_` | Until revoked |
| An agent working one seat | A Role session key, `rk_`, holding exactly that Role's [Permissions](/business/nouns/permission) | 1 hour, renewed while the session runs |
| An MCP client a person approved | An access token, `oat_` | 1 hour, renewed by its refresh token |
| CI and deploy pipelines | An exchanged token, `xt_`, from the runner's own identity | 15 minutes |

A key's scope is set when it is made and never widens. A publishable key runs only the [Verbs](/business/nouns/verb) you mark public, so a leaked one exposes nothing a page does not already show. [Keys](/code/api/guides/keys) covers each kind in code.

## Your customers' keys
A [Customer](/business/nouns/customer) of your API makes its own [API Keys](/business/nouns/api-key) in the [Portal](/business/nouns/portal), so key requests never reach your inbox. Each key reaches that Customer's [Tenant](/business/nouns/tenant) and nothing else, and never more than its plan allows. Its full secret shows once, at issue; after that only the prefix does.

Each key carries your brand prefix, such as `leaseline_sk_live_`, ahead of a fixed pattern, so code scanners catch a leak with one rule. Tell customers to make one key per job, so a leak costs one job. [Your customers' API keys](/products/api/customer-keys) covers scopes and the request log.

## Secrets agents never read
The keys your [Startup](/business/nouns/startup) uses to reach outside accounts are [Secrets](/business/nouns/secret). A Secret's value is write-only: no read returns it, the owner's included.

The platform fills each value into the outgoing request at call time, so no model ever sees it. Every use is an [Event](/business/nouns/event) naming the Secret, the [Action](/business/nouns/action) and where it went. [Secrets](/code/platform/secrets) has the full contract.

## Roll, revoke, replace
| To | Do | What happens |
| --- | --- | --- |
| Replace a key without downtime | Roll it | A new key with the same scope; the old one keeps working until it expires |
| Stop a key now | Revoke it | The next call returns `401` [unauthorized](/code/api/errors/unauthorized) |
| Replace a Secret's value | Rotate it | A new version; every old one is kept, marked retired |

The platform watches public code and pages for live keys, and revokes a leaked one within minutes. Your owner Role gets a [Task](/business/nouns/task) to deploy the replacement, and a Customer's admins get an email to roll theirs.

Ask your agent to [replace a leaked key](/products/api/replace-a-leaked-key) for a customer.

## On the record
Every key's creation, use, roll and revocation is an Event in the [audit log](/systems/trust-and-governance/audit-log). [Secret rotation](/systems/trust-and-governance/controls/secret-rotation) tests that every Secret rotates within its maximum age.

## Next
- [Security practices](/systems/trust-and-governance/security): every practice in one table.
- [Authentication](/code/api/guides/authentication): how a keyed call is checked and attributed.