API Keys
API keys are long-lived, scoped credentials for callers that run without a browser: a backend service, a CI job, or an autonomous AI agent. A key carries exactly the scopes you grant it, is bound to one organization, and can be rotated or revoked at any time.
After reading this page you will be able to: create a key scoped to only what a caller needs, read and reason about the scope allowlist, set the mandatory expiry, rotate a key with no downtime, revoke a key immediately, and explain to a security reviewer why a key can never exceed its grant or reach another organization.
API keys are available on every plan, including Free. Use them anywhere you would otherwise paste a user access token into a machine.
Key Format
bb_live_{prefix}_{secret}
A key has three parts: the bb_live_ label, a short public prefix
that identifies the key in listings and audit logs, and a long secret. Only
the secret grants access. Present the whole value in the standard header:
Authorization: Bearer bb_live_abc123_yourLongSecret The Secret Is Shown Once
The full key value is returned only in the response to the create call. It is never shown again and cannot be recovered: the platform stores only what it needs to verify the key, not the secret itself. Copy the value into your secret manager the moment you create it. If you lose it, revoke the key and create a new one; there is no way to reveal it after the fact.
Create a Key
In Settings, open API Keys, choose Create Key,
enter a name, and choose Access. The default,
Full access (what your role allows), grants *.
Choose MCP access (what your role allows) for
mcp:*, or Custom scopes to enter only the scopes
the caller needs. Your role continues to limit what the key can do.
Separate custom scope names with commas, for example
project, mcp:document.read. Names are case-sensitive; surrounding
spaces and repeated names are removed. Enter at least one scope, with no
empty entries between commas, up to 50 distinct scopes and 255 characters
per name. If creation fails, correct the named problem and retry with your
choices still in the form. Cancelling and reopening starts with the default
access choice.
POST /v1/api-keys Creating a key requires a recently completed authentication (a step-up re-auth). If your session’s authentication is stale, the request is rejected and you must re-authenticate before retrying. This applies to creating, rotating, and revoking keys, because each is a credential-lifecycle action.
Request Body
{
"name": "CI deploy bot",
"scopes": ["bbdocs", "mcp:secrets.read"],
"pinned_env_id": "<intended-environment-uuid>",
"expires_in_days": 90
} Replace <intended-environment-uuid> with the UUID of the
environment the caller should use. The issuer must have access to that
environment. An explicit pin selects the intended environment for MCP data
calls; existing unpinned keys retain their current environment behavior.
| Field | Required | Description |
|---|---|---|
name | Yes | A human label so you can identify and revoke the key later |
scopes | Recommended | The explicit allowlisted scopes the key may use (see below). Always supply them when creating a new integration key. |
pinned_env_id | Optional; defaults to the active environment | The environment UUID authorized for the key. The issuer must be allowed to access it. Existing unpinned keys keep their current behavior; new keys inherit the active environment when one is available. |
expires_in_days | Recommended | Lifetime in days, 1 to 365. If you omit it, the key is created with the maximum 365-day lifetime. There is no non-expiring key. |
Response
The response carries the full key value once, plus the key’s identifying metadata. The scopes and expiry you set are stored on the key and are returned whenever you list your keys.
{
"success": true,
"data": {
"id": "...",
"name": "CI deploy bot",
"prefix": "abc123",
"key": "bb_live_abc123_yourLongSecret",
"created_at": "2026-07-16T00:00:00Z"
}
} Mandatory Expiry
Every key expires; there is no permanent key. When you supply
expires_in_days it must be between 1 and
365; if you omit it, the key is created with the maximum
365-day lifetime. This is a deliberate rotation-hygiene control: a leaked key
that is never rotated is one of the most common ways credentials are abused,
so the platform caps the lifetime and expects you to rotate on a schedule.
Pick the shortest lifetime that fits the caller’s job (30 or 90 days is
typical for a service; 1 day is right for a short-lived agent run).
Scopes
Select an explicit allowlist for each new key. Full access
(*) and MCP access (mcp:*) are broad grants; choose
custom scopes when a caller needs less. Scopes never add permissions beyond
those of the person and key type making the request.
| Grain | Examples | What it grants |
|---|---|---|
| Fine-grained | mcp:secrets.read, mcp:secrets.write | One specific capability. Prefer these for least privilege. |
| Coarse | bbdocs, bbsheet, secrets | A whole product area. |
| MCP category only | mcp:project, mcp:task | Tools in one MCP category. These grants do not authorize REST requests or satisfy a tool’s separate fine-grained scope requirement. |
| MCP grant | mcp:* | Every MCP tool permitted for the key type and caller. Use only for a trusted, general-purpose agent. |
| Full access | * | All scopes permitted for the key type and caller, including MCP and eligible REST requests. |
When a key calls an MCP tool, the key is
scoped to the tool if its scopes contain the tool’s fine-grained scope
or the matching coarse grant or mcp:*. So a
key with mcp:secrets.read can use read-scoped Backbuild Secrets
tools through MCP but not write-scoped ones, while mcp:*
matches every tool’s scope gate.
Key-type restrictions and the caller’s permissions still apply. Grant the
narrowest set that lets the caller do its job.
An MCP-only category grant such as mcp:project is narrower than
the bare project grant: it does not grant REST access. For a tool
with a separate fine-grained scope requirement, request that scope explicitly;
for example, mcp:secrets does not replace
mcp:secrets.read.
Extension and agent-auth keys can use scoped content and browser/device tools, but cannot use organization-control tools. Service and SCIM keys use their dedicated APIs. OAuth tokens keep their signed-in user scope behavior; individual tools can also require a direct API key. A wildcard scope does not remove these restrictions.
An unknown or unsupported scope is rejected at create time with a
400 whose message lists the scopes you are allowed to request,
so a typo fails loudly rather than silently under-granting.
mcp:*. Key-type restrictions and caller permissions also apply.List Keys
GET /v1/api-keys
Returns every key in the organization with its metadata (id, name, prefix,
scopes, expiry, last-used and created timestamps). The secret is never
included. A convenience read is also available at
GET /v1/settings/api-keys.
{
"success": true,
"data": {
"keys": [
{
"id": "...",
"name": "CI deploy bot",
"prefix": "abc123",
"scopes": ["bbdocs", "mcp:secrets.read"],
"last_used_at": null,
"expires_at": "2026-10-14T00:00:00Z",
"created_at": "2026-07-16T00:00:00Z"
}
]
}
} Rotate a Key With No Downtime
POST /v1/api-keys/{id}/rotate Rotation issues a fresh secret that carries over the retired key’s name, scopes, rate limit, and expiry, so you do not re-grant anything. Requires a step-up re-auth, like creation. The response returns the new full value once, exactly as create does. Crucially, the old secret does not stop working the instant you rotate: it stays valid for a short overlap window (a few minutes by default) so in-flight requests are not dropped mid-rollout. Roll it out like this:
- Call rotate and capture the new key value from the response.
- Deploy the new value to every service, within the overlap window.
- Confirm all traffic is on the new value (watch the new key’s last-used and your logs).
- The old secret retires automatically when the overlap window ends; after that it returns
401.
Because the new key inherits the retired key’s scopes and configuration, you rotate on a schedule without editing scope grants or reconfiguring the caller.
Revoke a Key
DELETE /v1/api-keys/{id}
Revoking a key invalidates it immediately; any caller still presenting it
starts receiving 401. Requires a step-up re-auth. Revoke a key
the moment it is no longer needed or is suspected of exposure, then create a
fresh scoped key for the caller that still needs access.
Security Guarantees
- An explicitly scoped key stays within its scopes. It can perform only actions allowed by its scopes and your role.
- A key is bound to one organization. It cannot read or write another organization’s data; a cross-organization id simply reads as not found.
- A key ends with its creator’s access. A key acts
as the person who created it, so it stops working when that person is
suspended, archived, or removed from the organization, and when they reset their
password, sign out of every session, or change a second factor. Each of
those takes the person’s keys with it.
A request with such a key is answered
401; create a new key. - The secret is never echoed. After creation or rotation it is unrecoverable. Store it in a secret manager, never in source control.
- Lifecycle actions require step-up. Creating, rotating, or revoking a key needs a recently completed authentication, so a stale session cannot mint or destroy credentials.
- Every key expires. The mandatory 1 to 365 day lifetime enforces rotation hygiene.
Frequently Asked Questions
Can I see the key again after I create it?
No. The full value is shown once, at creation (and again after each
rotation). If you lose it, revoke the key and create a new one.
How do I rotate without downtime?
Call rotate, deploy the new value everywhere within the overlap window,
confirm traffic has cut over, then let the old secret retire when the
window ends. The new key carries over the retired key’s scopes and
configuration.
Can I avoid wildcard grants?
Yes, and you should. Grant fine-grained scopes such as
mcp:secrets.read rather than mcp:*. A key holds
only its allowlisted scopes.
Why must a key have an expiry?
Every key expires (1 to 365 days) as a rotation control. There is no
permanent key, so a forgotten leaked key cannot live forever.
How is a key different from a user access token?
An access token is short-lived and tied to a signed-in user session; a key
is long-lived, scoped, and revocable, and it needs no interactive login,
which is what makes it right for servers and agents. Both are bounded by
the access of the identity behind them. See
MCP Server for how a key drives agent tools.
My create call was rejected even though I am signed in. Why?
Key creation requires a recent authentication. Re-authenticate (a step-up
re-auth) and retry.
My key stopped working before it expired. Why?
Either it was revoked, or something changed for the person who created it:
they were suspended, archived, or removed from the organization, or they reset
their password, signed out of every session, or changed a second factor.
Any of those ends their keys. Create a new key from an account that is
active in the organization.
How do I give an AI agent a key without pasting it?
Create a one-time agent setup link (POST /v1/agent-setup/links,
from a signed-in session) and hand the agent the instructions it returns.
The agent redeems the link once, within ten minutes, for its own key named
after it, with the mcp:* scope and a 90-day lifetime. See the
API reference.