Named keys with explicit scope
Use a separate named key for each integration. A scoped key belongs to one billing account and one explicit mode, with reviewedteam_ids, action_ids, expires_at
(epoch milliseconds), and manager_user_ids. Action IDs are exact public operation
IDs from the current server policy catalog; a label such as “all writes” is not a
scope. Named service keys belong to the organization: the issuer UID records
attribution, rather than borrowing that person’s current human permissions. Each
request still checks the key’s exact scope and current account/team state, API
entitlement and server policy.
Read GET /users/me/scoped-api-keys/policy?billing_account_id=ACCOUNT_ID using a
personal Firebase or MCP identity. The policy lists eligible teams, actions and
managers, creation authority, and expiry/overlap bounds. Account owners may omit expires_at or set it to null for no expiration. A chosen
expiry cannot exceed 365 days; bounded delegated administrators must supply a
future expiry within their assigned limit. Existing dates are preserved. The server
rechecks eligibility during private execution rather than trusting a saved policy.
Prepare api_keys.create_scoped through POST /users/me/account-approvals with a
saved UUIDv4 and payload {name,livemode,billing_account_id,team_ids,action_ids, expires_at,manager_user_ids}. Preparing does not issue a credential. The initiating
person reviews the exact scope in the private browser after a recent real sign-in.
Only the first successful private execution response contains the secret. Store it
locally in the integration’s secret manager; subsequent reads and retries contain
metadata only. An API key, including a legacy key, cannot manage key lifecycles.
List metadata with GET /users/me/scoped-api-keys?billing_account_id=ACCOUNT_ID.
Read one key at GET /users/me/scoped-api-keys/{keyId} and its safe lifecycle audit
at GET /users/me/scoped-api-keys/{keyId}/audit; include the billing-account query.
Use the returned capabilities and per-key management permissions. Audit entries
contain safe lifecycle evidence, never request bodies, headers or tokens.
last_used_at is observed usage only; null means unavailable, not never used.
Prepare api_keys.rotate_scoped with {key_id,overlap_seconds}. Rotation copies
that key’s immutable scope and managers without widening them. Review the explicit
overlap period: the predecessor remains usable only until its scheduled revocation
or earlier expiry. Other keys remain untouched. Revoke a single key using
DELETE /users/me/scoped-api-keys/{keyId} with {operation_id:UUID} and the exact
billing-account query. Preserve the UUID after an uncertain response and inspect
metadata before repeating the identical request; do not automatically rotate again.
Use named keys from CLI or MCP
expires_at is optional for owners. manager_user_ids:[]
adds no delegated managers. Choose action_ids from policy, and set expires_at to
null for no expiration or an actual future epoch-ms value within its expiry bound.
Rotation preserves the expiry choice, including no expiration. List/audit accept --limit
and --cursor; continue until next_cursor:null, even after an empty page.
Preparation succeeds with safe approval metadata and a review_url, not a key.
CLI exits nonzero for refused or unconfirmed requests and retains the operation
reference for readback; it never repeats a consequential request automatically.
The named MCP equivalents are account_api_keys_policy_get,
account_api_keys_list, account_api_keys_create_prepare,
account_api_keys_rotate_prepare, account_api_keys_get,
account_api_keys_audit_list, and account_api_keys_revoke. Use existing
get_account_approval to inspect preparation. An agent can request review within
current authority, but cannot execute the private secret-disclosure terminal.
Migrate an existing integration
Existing keys and tokens remain valid according to their existing checks. Thelegacy_unrestricted label means no reviewed explicit action/team scope was stored;
it does not exempt a legacy credential from current account and permission checks.
No migration deadline, forced rotation, or automatic retirement is implied.
- Inventory one integration’s actual teams, mode and API operations.
- Read policy and prepare a named key with those exact allowed operation IDs.
- Review privately and store the one-time secret in that integration.
- Verify its required requests and expected denial for excluded actions/teams.
- Switch that integration, then deliberately revoke its old key when ready.
Owner emergency for named scoped keys
The current personal billing-account owner can revoke all scoped keys across both modes usingPOST /users/me/scoped-api-keys/emergency-revoke with the exact billing
account query and {operation_id:UUID}. Delegated credential administrators, key
managers and API keys cannot use this operation. Legacy API keys, MCP and OAuth
credentials remain untouched. Pending scoped create/rotate approvals are invalidated.
Save the UUID before requesting revocation. Read
GET /users/me/scoped-api-keys/emergency-revocations/{operationId} with the same
billing account after an uncertain response. processing reports a partial
revoked_count and completed_at:null; only completed reports the final count.
Repeating POST with the same UUID deliberately resumes the existing operation;
do not retry automatically or substitute a new UUID.
account_api_keys_emergency_revoke with the saved operation UUID,
scope:"billing_account_scoped_keys" and confirmed:true, followed by
account_api_keys_emergency_get for readback. The confirmation fields express
intent; the backend independently checks current personal owner authority.
First-release action catalog
The first scoped-key catalog permits business reads, including client reads, and service creation, updates and deletion. Client mutations, fiscal issuance or cancellation, refunds, automation, team/user administration, and credential lifecycle are not grantable. Client writes can trigger downstream Stripe/fiscal effects whose scope proof is not yet covered. Read policy for the exact allowed operation IDs; new routes never inherit a grant. Unknown or unreviewed routes returnscoped_action_unavailable. Existing legacy credentials retain their existing
behavior; this release does not claim scoped-key coverage for every account workflow.
Handle a server denial
Select an allowed team and the key’s exact mode. If an operation is missing fromaction_ids, ask a current credential administrator to prepare a separately
reviewed key; the integration cannot grant itself permission. If current module
permissions or account entitlement are missing, correct that authority first.
Per-key managers can inspect/revoke/prepare rotation for managed keys, without
receiving permission to create or widen keys. Policy and safe key responses expose
current capabilities; credentials never override an explicit server denial.
Legacy pair: inspect before creating
GET /api-keys?team=TEAM_ID. It returns metadata
only: keyid, type, team, livemode, valid, timestamp,
invalidTimestamp and lastUsedAt. Stored JWTs never appear in list responses.
Pagination uses limit (1–100, default 20), cursor, has_more and
next_cursor. include_revoked=true includes revoked API keys. A filtered page
can be empty and still have another cursor; stop only when has_more is false.
Personal MCP tokens have their own account endpoints.
Legacy pair: prepare creation or rotation
Credential issuance requires an authenticated browser approval. Save a UUIDv4 before preparing each new request. The CLI commands return safe approval state andreview_url, never secrets:
POST /users/me/account-approvals with action
api_keys.generate or api_keys.rotate, the explicit team_id and payload:{}.
The old --out secret-file and issuance confirmation flags are no longer accepted.
The initiating person opens the authenticated review link, verifies the team,
requested live/test modes and exact revocations, and confirms there after a recent
real sign-in. Only that committing browser request receives the newly issued keys.
Legacy pair creation requires no active legacy API keys; rotation revokes only the
reviewed legacy API keys and preserves scoped keys and personal MCP tokens. Relevant account/key changes invalidate the
request rather than silently expanding its scope. The current API entitlement and
administrator authority are rechecked at execution.
After an uncertain preparation response, repeat only the original operation UUID
and exact input. After a lost browser execution response, read the approval receipt;
secrets cannot be retrieved. See credential approvals.
POST /api-keys and POST /api-keys/rotate are retired and return HTTP 403
account_approval_required, including for freshly authenticated Firebase users.
They do not create credentials. Existing list and revocation operations remain.
Revoke one key or perform emergency revocation
DELETE /api-keys/{keyId}?team=TEAM_ID returns metadata with valid: false.
Calling it again returns the revoked state. Foreign keys and MCP token IDs return
404; this operation only revokes API credentials.
For an explicitly requested team-wide emergency:
POST /api-keys/emergency-revoke?team=TEAM_ID revokes active legacy API and personal MCP credentials associated with the
team. It can revoke the calling legacy MCP credential. Named scoped keys and records
with malformed scoped markers are untouched. OAuth tokens are not revoked. Its
historical scope: "team_api_and_mcp_keys" label describes the legacy operation;
it does not mean all named scoped keys were revoked. oauth_revoked remains false.
The server batches large revocations and retains a revocation fence across
interruptions. Continue through another still-authorized Firebase/user session
if the calling MCP token has been revoked; do not assume the whole account has
been disconnected from OAuth integrations.