Least privilege and Admin credentials
Status: DOCUMENTED (Admin endpoints in this atlas were exercised GET/LIST-only where the key allowed; xAI Management API is ACCOUNT_RESTRICTED — two GET probes with the inference key returned 401 {code:16}; see docs/openai/, docs/anthropic/, docs/xai/management-api.md, docs/gemini/authentication-headers-versions.md)
Sources: OpenAI OpenAPI spec (/organization/*) · https://developers.openai.com/api/docs/guides/production-best-practices · https://developers.openai.com/api/docs/guides/error-codes · https://platform.claude.com/docs/en/api/admin · https://platform.claude.com/docs/en/manage-claude/spend-limits-api · https://platform.claude.com/docs/en/api/rate-limits#setting-lower-limits-for-workspaces · xAI: https://docs.x.ai/developers/management-api-guide (Management keys SCOPE_TEAM/SCOPE_ORGANIZATION, POST /auth/teams/{teamId}/api-keys with acls[]/qps/qpm/tpm/expireTime, GET /auth/teams/{teamId}/endpoints|models (grantable ACLs), /v1/billing/teams/{id}/postpaid/spending-limits, /prepaid/balance, GET /audit/teams/{teamId}/events), https://docs.x.ai/developers/faq/team-management (Admin/Member roles, auto-join by domain), https://docs.x.ai/developers/rate-limits (per-key caps, Batch exempt) · Gemini: https://ai.google.dev/gemini-api/docs/api-key (IAM permissions to create keys, auth keys bound to service accounts, API/application restrictions), https://ai.google.dev/gemini-api/docs/rate-limits (limits per project, tiers by Cloud spend, project-level spend caps and billing-tier caps), https://ai.google.dev/gemini-api/docs/billing
Last verified: 2026-09-19
Privilege tiers
| Tier | OpenAI | Anthropic | xAI | Gemini | Use it for |
|---|---|---|---|---|---|
| Runtime (inference) | Project API key, service-account owned; project allowed service tiers, rate limits, spend limits | Workspace API key; workspace rate limits, spend limits | Team API key (xai-…) with ACLs (api-key:endpoint:chat / :image / *, api-key:model:<id> / * — keys created via the API have no access until granted), optional per-key qps/qpm/tpm caps and expireTime; introspect with GET /v1/api-key |
AI Studio auth key bound to a dedicated service account, restricted in the Cloud console to the Generative Language API and to your server IPs; quotas and spend caps apply to the Cloud project (one project per app/environment); serviceTier/labels per request |
Application servers only |
| Read-only management | Admin API key used only for GET (usage, costs, audit logs, lists) |
Admin API key with read:* scopes |
Management key (https://management-api.x.ai, distinct key type) used only for GET: /auth/management-keys/validation, /auth/teams/{id}/api-keys (list, redacted), `/auth/teams/{id}/endpoints |
models, /v1/billing/teams/{id}/{invoices,prepaid/balance,postpaid/spending-limits,payment-method}, POST …/usage(aggregated usage — a read),GET /audit/teams/{id}/events` |
Cloud IAM viewer roles + Cloud Billing viewer; AI Studio dashboards; GET /v1/webhooks, GET /v1beta/interactions/{id} |
| Write management | Admin API key: projects, keys, users, rate limits | Admin API key with write:* scopes, spend-limit approvals |
Management key with Read + Write: create keys (POST /auth/teams/{id}/api-keys), PUT /auth/api-keys/{id} (fieldMask qpm…), rotate / delete keys (!!CAUTION!! in the docs), set billing info / spending limits / default payment method, prepaid top-up. Team creation, member roles, ZDR toggle and mTLS are console-only |
Cloud IAM roles apikeys.keys.create, iam.serviceAccounts.create, iam.serviceAccountApiKeyBindings.create, serviceusage.services.enable; billing account admin; webhooks/agents/credentials/triggers management under the API key |
Provisioning pipelines, break-glass |
The atlas itself follows the strictest interpretation: Admin/Management keys are optional, and destructive actions are never run (CLAUDE.md): no key rotation/deletion, no billing changes, no webhook or agent creation.
Controls that shrink blast radius
- Projects / Workspaces as security boundaries. One per application (and per environment). Compromise of a key exposes only that project's data, spend and rate limit. OpenAI spend limits exist at org and project level (
project_spend_limit_exceeded429); Anthropic spend limits at org and workspace level (a 400invalid_request_errorwhen your own limit is hit; the Claude Code workspace can return 429 instead). - Allowed service tiers per project (OpenAI): a project can be prevented from using
priority(cost) orflex(latency) — a 400 "Invalidservice_tier" enforces it. - Spend limits before rate limits. A stolen key hits your spend cap before your bank account: set both providers' spend limits low for dev projects. Anthropic tier spend caps pause the org until the 1st of the month — treat that 429-without-
retry-afteras a page-worthy incident, not a retry. - Key governance: OpenAI API Key Governance (service-account-only, max lifetime); Anthropic key expiration. Rotate Admin keys more often than runtime keys — they can mint runtime keys.
- Audit logs: OpenAI
GET /v1/organization/audit_logs(api_key.created,project.updated,rate_limit.updated… —generated/fragments/audit-log-events/); Anthropic Console audit + Compliance API; xAIGET /audit/teams/{teamId}/events(administrative events only — key creation, team changes,ListApiKeys; filterseventFilter.userId|query|eventId,eventTimeFrom/To) and the console Usage Explorer grouped by request IP (catches a leaked key used from elsewhere); Gemini Cloud Audit Logs on the project (apikeys.googleapis.com,iam) + Cloud Billing exports. Export continuously with read-only credentials. - xAI-specific blast-radius controls: ACL a key to one endpoint family and one model; cap it with
qpm/tpm; setexpireTime; set a postpaid spending limit (default $0 = prepaid only — a stolen key can at most burn the prepaid balance); the Batch API bypasses rate limits (a leaked key can move volume there — watch usage by key); team-wide ZDR is a console toggle, read it viaGET /v1/me.zdr_status/x-zero-data-retention. - Gemini-specific blast-radius controls: limits and quotas are per project — separate projects, not just separate keys; project spend caps and billing-tier caps stop traffic instead of overspending; auth keys mean a compromised key acts as a service account whose IAM you chose — give it nothing beyond the Generative Language API; unrestricted keys are rejected by Google anyway.
- Separate identities for agents. If an autonomous agent needs API access, give it its own project/workspace/team key (xAI: its own ACL'd key; Gemini: its own project) with its own spend limit and
safety_identifier/metadata.user_id/labels.safety_identifiervalue, never a human's key. Gemini managed agents (Deep Research, Antigravity) additionally get agent credentials (client.credentials.*) and sandboxed environments — scope those secrets to the agent, not the operator.
Anti-patterns
- An Admin/Management key in the same secret store entry / container as the runtime key (xAI: the Management key can mint inference keys with
api-key:*:*). - "Temporary" org-owner personal keys in CI; xAI keys created with
acls: ["api-key:endpoint:*", "api-key:model:*"]"to make it work". - Raising a spend limit from the same automation that consumes the budget (Anthropic deliberately separates request and approve/deny; xAI
POST …/postpaid/spending-limitsand Gemini billing caps should be console/human actions). - Using one project/team for every environment because "rate limits are shared anyway" — on Gemini that also shares the 429 budget and the free-tier data-use terms.
Checklist
- One project/workspace/team/Cloud-project per app+environment; spend limit set on each (OpenAI project, Anthropic workspace, xAI postpaid limit, Gemini project cap).
- Runtime keys cannot manage the org (xAI: inference keys get 401 on
management-api.x.ai— verified). - xAI keys ACL-scoped to endpoint + model, capped (
qpm/tpm), withexpireTime; Gemini keys restricted (API + IP) and bound to a least-privilege service account. - Admin/Management automation uses read-only keys/roles; write keys are break-glass with approval.
- Audit log export running (OpenAI audit_logs, xAI audit events, Gemini Cloud Audit Logs); alerts on key creation, ACL/spend-limit changes, IP-allowlist changes, unknown request IPs.
- Service tiers restricted per project where cost matters (OpenAI
service_tier; xAIpriority; Geminipriority/flex). - Agents have their own keys, projects and attribution identifiers.