SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
13 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
47.1 KB

# OpenAI Administration API — atlas

Status: DOCUMENTED for all 124 operations (OpenAPI spec v2.3.0); every GET we could probe is ACCOUNT_RESTRICTED (our project key gets HTTP 403 — 401 for audit logs — Missing scopes: api.management.read etc.). No Admin key is available, so nothing below is LIVE_VERIFIED except the exact error shapes. No mutating admin call was ever issued.

Sources: Administration overview · Admin APIs guide · Production best practices → organization · Spend limits · Mutual TLS · IP allowlist · Your data (retention / residency) · OpenAPI sources/openai/openapi/openapi-master.yaml (all /organization/* + /projects/* paths) · SDK surfaces sources/openai/openapi/{python,node}-sdk-api.md.

Last verified: 2026-09-18 (live probes: 14 admin GETs, all 401/403; details in tmp-live/openai-admin/ and reports/live-requests.jsonl).

Machine-readable twins: generated/fragments/endpoints/openai-admin.json (124 endpoints), generated/fragments/parameters/openai-admin.json (431 parameters), generated/fragments/audit-log-events/openai-audit-log-events.json (149 event types).

# 1. Model of the Admin API

Concept What it is Where
Organization Billing + policy boundary; has users (owner/reader), groups, custom roles, spend limit, data retention, certificates, external storage, audit log /v1/organization/*
Project Isolation unit inside an org: own API keys, service accounts, users (owner/member), groups, per-model rate limits, model/hosted-tool permissions, spend limit & alerts, data retention, certificates, webhooks /v1/organization/projects/{project_id}/*, project roles at /v1/projects/{project_id}/*
Admin API key sk-admin-… created by org owners at Settings → Organization → Admin keys; the only credential accepted by /v1/organization/* and /v1/projects/*; refused by non-admin endpoints. Workload-identity tokens cannot call Admin endpoints. GET/POST/DELETE /v1/organization/admin_api_keys
Scopes Fine-grained permissions carried by restricted keys / roles. Read scopes we observed in error messages: api.management.read (users, invites, projects, admin keys, spend limit/alerts, data retention), api.usage.read (usage + costs), api.audit_logs.read, api.roles.read, api.groups.read, api.mtls.read (certificates, message adds "(Owner)"), api.external_storage.read. Documented write scopes: api.groups.write, api.mtls.write. Model-side scopes seen in the spec/guides: api.model.request, api.model.read, api.responses.write, api.files.read/write, api.batch.read/write, api.vector_store.read, api.videos.read/write, api.voices.read/write, api.agents.read/write, api.vaults.read/write, api.webhooks.read, api.traces.read, api.safety.read, api.safety.alerts.read, api.apps.read/write. error bodies, Role.permissions[]
Roles Predefined + custom roles (object: role, permissions[], `resource_type: api.organization api.project, predefined_role). Bound to users or groups at org level (/organization/users/{id}/roles, /organization/groups/{id}/roles) or project level (/projects/{id}/users/{uid}/roles, /projects/{id}/groups/{gid}/roles). Legacy simple roles: org owner/reader; project owner/member`.
Pagination Cursor style: limit (1–100, default 20) + after → {object:"list", data, first_id, last_id, has_more}. Usage/costs use page → {object:"page", data:[buckets], has_more, next_page}. Roles/groups lists use after/limit and return has_more + next cursor (SDK SyncNextCursorPage). —
Mutations Always POST (no PUT/PATCH), deletes are DELETE → {object:"…deleted", id, deleted:true}. No Idempotency-Key header. —

# 2. Endpoint catalogue

Legend: * = required parameter; SDK column = Python method (Node is the camelCase twin, e.g. client.admin.organization.auditLogs.list).

# Organization admin api keys

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/admin_api_keys List all organization and project API keys. after, order (asc desc), limit client.admin.organization.admin_api_keys.list
POST /v1/organization/admin_api_keys Create admin API key name*, expires_in_seconds client.admin.organization.admin_api_keys.create DOCUMENTED
GET /v1/organization/admin_api_keys/{key_id} Retrieve admin API key — client.admin.organization.admin_api_keys.retrieve DOCUMENTED
DELETE /v1/organization/admin_api_keys/{key_id} Delete admin API key — client.admin.organization.admin_api_keys.delete DOCUMENTED

# Organization audit logs

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/audit_logs List audit logs effective_at, tenant_only, limit, after, before client.admin.organization.audit_logs.list ACCOUNT_RESTRICTED (403/401 with project key)

# Certificates (Mutual TLS)

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/certificates List organization certificates limit, after, order (asc desc) client.admin.organization.certificates.list
POST /v1/organization/certificates Upload certificate name, certificate* client.admin.organization.certificates.create DOCUMENTED
POST /v1/organization/certificates/activate Activate certificates for organization certificate_ids* client.admin.organization.certificates.activate DOCUMENTED
POST /v1/organization/certificates/deactivate Deactivate certificates for organization certificate_ids* client.admin.organization.certificates.deactivate DOCUMENTED
GET /v1/organization/certificates/{certificate_id} Get certificate include (content) client.admin.organization.certificates.retrieve DOCUMENTED
POST /v1/organization/certificates/{certificate_id} Modify certificate name client.admin.organization.certificates.update DOCUMENTED
DELETE /v1/organization/certificates/{certificate_id} Delete certificate — client.admin.organization.certificates.delete DOCUMENTED
GET /v1/organization/projects/{project_id}/certificates List project certificates limit, after, order (asc desc) client.admin.organization.projects.certificates.list
POST /v1/organization/projects/{project_id}/certificates/activate Activate certificates for project certificate_ids* client.admin.organization.projects.certificates.activate DOCUMENTED
POST /v1/organization/projects/{project_id}/certificates/deactivate Deactivate certificates for project certificate_ids* client.admin.organization.projects.certificates.deactivate DOCUMENTED

# Usage & costs

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/costs Costs start_time*, end_time, bucket_width (1d), project_ids, api_key_ids, line_items, group_by (project_id line_item api_key_id), limit, page
GET /v1/organization/usage/audio_speeches Audio speeches start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, group_by (project_id
GET /v1/organization/usage/audio_transcriptions Audio transcriptions start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, group_by (project_id
GET /v1/organization/usage/code_interpreter_sessions Code interpreter sessions start_time*, end_time, bucket_width (1m 1h 1d), project_ids, group_by (project_id), limit, page
GET /v1/organization/usage/completions Completions start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, batch, group_by (project_id
GET /v1/organization/usage/embeddings Embeddings start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, group_by (project_id
GET /v1/organization/usage/file_search_calls File search calls start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, vector_store_ids, group_by (project_id
GET /v1/organization/usage/images Images start_time*, end_time, bucket_width (1m 1h 1d), sources (image.generation
GET /v1/organization/usage/moderations Moderations start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, group_by (project_id
GET /v1/organization/usage/vector_stores Vector stores start_time*, end_time, bucket_width (1m 1h 1d), project_ids, group_by (project_id), limit, page
GET /v1/organization/usage/web_search_calls Web search calls start_time*, end_time, bucket_width (1m 1h 1d), project_ids, user_ids, api_key_ids, models, context_levels (low

# Organization data retention

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/data_retention Retrieve organization data retention — client.admin.organization.data_retention.retrieve ACCOUNT_RESTRICTED (403/401 with project key)
POST /v1/organization/data_retention Update organization data retention retention_type* (zero_data_retention modified_abuse_monitoring enhanced_zero_data_retention

# Organization groups

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/groups List groups limit, after, order (asc desc) client.admin.organization.groups.list
POST /v1/organization/groups Create group name* client.admin.organization.groups.create DOCUMENTED
GET /v1/organization/groups/{group_id} Retrieve group — client.admin.organization.groups.retrieve DOCUMENTED
POST /v1/organization/groups/{group_id} Update group name* client.admin.organization.groups.update DOCUMENTED
DELETE /v1/organization/groups/{group_id} Delete group — client.admin.organization.groups.delete DOCUMENTED

# Organization role bindings

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/groups/{group_id}/roles List group organization role assignments limit, after, order (asc desc) client.admin.organization.groups.roles.list
POST /v1/organization/groups/{group_id}/roles Assign organization role to group role_id* client.admin.organization.groups.roles.create DOCUMENTED
GET /v1/organization/groups/{group_id}/roles/{role_id} Retrieve group organization role — client.admin.organization.groups.roles.retrieve DOCUMENTED
DELETE /v1/organization/groups/{group_id}/roles/{role_id} Unassign organization role from group — client.admin.organization.groups.roles.delete DOCUMENTED
GET /v1/organization/users/{user_id}/roles List user organization role assignments limit, after, order (asc desc) client.admin.organization.users.roles.list
POST /v1/organization/users/{user_id}/roles Assign organization role to user role_id* client.admin.organization.users.roles.create DOCUMENTED
GET /v1/organization/users/{user_id}/roles/{role_id} Retrieve user organization role — client.admin.organization.users.roles.retrieve DOCUMENTED
DELETE /v1/organization/users/{user_id}/roles/{role_id} Unassign organization role from user — client.admin.organization.users.roles.delete DOCUMENTED

# Group membership

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/groups/{group_id}/users List group users limit, after, order (asc desc) client.admin.organization.groups.users.list
POST /v1/organization/groups/{group_id}/users Add group user user_id* client.admin.organization.groups.users.create DOCUMENTED
GET /v1/organization/groups/{group_id}/users/{user_id} Retrieve group user — client.admin.organization.groups.users.retrieve DOCUMENTED
DELETE /v1/organization/groups/{group_id}/users/{user_id} Remove group user — client.admin.organization.groups.users.delete DOCUMENTED

# Organization invites

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/invites List invites limit, after client.admin.organization.invites.list ACCOUNT_RESTRICTED (403/401 with project key)
POST /v1/organization/invites Create invite email, role (reader owner), projects client.admin.organization.invites.create
GET /v1/organization/invites/{invite_id} Retrieve invite — client.admin.organization.invites.retrieve DOCUMENTED
DELETE /v1/organization/invites/{invite_id} Delete invite — client.admin.organization.invites.delete DOCUMENTED

# Organization projects

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects List projects limit, after, include_archived client.admin.organization.projects.list ACCOUNT_RESTRICTED (403/401 with project key)
POST /v1/organization/projects Create project name*, geography, residency, external_key_id client.admin.organization.projects.create DOCUMENTED
GET /v1/organization/projects/{project_id} Retrieve project — client.admin.organization.projects.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id} Modify project name, external_key_id, geography client.admin.organization.projects.update DOCUMENTED

# Project api keys

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/api_keys List project API keys limit, after, owner_project_access (active inactive any)
GET /v1/organization/projects/{project_id}/api_keys/{api_key_id} Retrieve project API key — client.admin.organization.projects.api_keys.retrieve DOCUMENTED
DELETE /v1/organization/projects/{project_id}/api_keys/{api_key_id} Delete project API key — client.admin.organization.projects.api_keys.delete DOCUMENTED

# Project archive

Method Path Name Key params (query/body) Python SDK Status
POST /v1/organization/projects/{project_id}/archive Archive project — client.admin.organization.projects.archive DOCUMENTED

# Project data retention

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/data_retention Retrieve project data retention — client.admin.organization.projects.data_retention.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/data_retention Update project data retention retention_type* (organization_default none zero_data_retention

# Project groups

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/groups List project groups limit, after, order (asc desc) client.admin.organization.projects.groups.list
POST /v1/organization/projects/{project_id}/groups Add project group group_id, role client.admin.organization.projects.groups.create DOCUMENTED
GET /v1/organization/projects/{project_id}/groups/{group_id} Retrieve project group group_type (group tenant_group) client.admin.organization.projects.groups.retrieve
DELETE /v1/organization/projects/{project_id}/groups/{group_id} Remove project group — client.admin.organization.projects.groups.delete DOCUMENTED

# Project hosted tool permissions

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/hosted_tool_permissions Retrieve project hosted tool permissions — client.admin.organization.projects.hosted_tool_permissions.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/hosted_tool_permissions Modify project hosted tool permissions file_search, web_search, image_generation, mcp, code_interpreter client.admin.organization.projects.hosted_tool_permissions.update DOCUMENTED

# Project model permissions

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/model_permissions Retrieve project model permissions — client.admin.organization.projects.model_permissions.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/model_permissions Modify project model permissions mode* (allow_list deny_list), model_ids* client.admin.organization.projects.model_permissions.update
DELETE /v1/organization/projects/{project_id}/model_permissions Delete project model permissions — client.admin.organization.projects.model_permissions.delete DOCUMENTED

# Project rate limits

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/rate_limits List project rate limits limit, after, before client.admin.organization.projects.rate_limits.list_rate_limits DOCUMENTED
POST /v1/organization/projects/{project_id}/rate_limits/{rate_limit_id} Modify project rate limit max_requests_per_1_minute, max_tokens_per_1_minute, max_images_per_1_minute, max_audio_megabytes_per_1_minute, max_requests_per_1_day, batch_1_day_max_input_tokens client.admin.organization.projects.rate_limits.update_rate_limit DOCUMENTED

# Project service accounts

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/service_accounts List project service accounts limit, after client.admin.organization.projects.service_accounts.list DOCUMENTED
POST /v1/organization/projects/{project_id}/service_accounts Create project service account name*, create_service_account_only, expires_in_seconds client.admin.organization.projects.service_accounts.create DOCUMENTED
GET /v1/organization/projects/{project_id}/service_accounts/{service_account_id} Retrieve project service account — client.admin.organization.projects.service_accounts.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/service_accounts/{service_account_id} Update project service account name, role (member owner) client.admin.organization.projects.service_accounts.update
DELETE /v1/organization/projects/{project_id}/service_accounts/{service_account_id} Delete project service account — client.admin.organization.projects.service_accounts.delete DOCUMENTED
POST /v1/organization/projects/{project_id}/service_accounts/{service_account_id}/api_keys Create an API key for a service account name, scopes, expires_in_seconds client.admin.organization.projects.service_accounts.api_keys.create DOCUMENTED

# Project spend alerts

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/spend_alerts List project spend alerts limit, order (asc desc), after, before client.admin.organization.projects.spend_alerts.list
POST /v1/organization/projects/{project_id}/spend_alerts Create project spend alert threshold_amount, currency (USD), interval* (month), notification_channel* client.admin.organization.projects.spend_alerts.create DOCUMENTED
GET /v1/organization/projects/{project_id}/spend_alerts/{alert_id} Retrieve project spend alert — client.admin.organization.projects.spend_alerts.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/spend_alerts/{alert_id} Update project spend alert threshold_amount, currency (USD), interval* (month), notification_channel* client.admin.organization.projects.spend_alerts.update DOCUMENTED
DELETE /v1/organization/projects/{project_id}/spend_alerts/{alert_id} Delete project spend alert — client.admin.organization.projects.spend_alerts.delete DOCUMENTED

# Project users

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/users List project users limit, after client.admin.organization.projects.users.list DOCUMENTED
POST /v1/organization/projects/{project_id}/users Create project user user_id, email, role* client.admin.organization.projects.users.create DOCUMENTED
GET /v1/organization/projects/{project_id}/users/{user_id} Retrieve project user — client.admin.organization.projects.users.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/users/{user_id} Modify project user role client.admin.organization.projects.users.update DOCUMENTED
DELETE /v1/organization/projects/{project_id}/users/{user_id} Delete project user — client.admin.organization.projects.users.delete DOCUMENTED

# Organization roles

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/roles List organization roles limit, after, order (asc desc) client.admin.organization.roles.list
POST /v1/organization/roles Create organization role role_name, permissions, description client.admin.organization.roles.create DOCUMENTED
GET /v1/organization/roles/{role_id} Retrieve organization role — client.admin.organization.roles.retrieve DOCUMENTED
POST /v1/organization/roles/{role_id} Update organization role permissions, description, role_name client.admin.organization.roles.update DOCUMENTED
DELETE /v1/organization/roles/{role_id} Delete organization role — client.admin.organization.roles.delete DOCUMENTED

# Organization spend alerts

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/spend_alerts List organization spend alerts limit, order (asc desc), after, before client.admin.organization.spend_alerts.list
POST /v1/organization/spend_alerts Create organization spend alert threshold_amount, currency (USD), interval* (month), notification_channel* client.admin.organization.spend_alerts.create DOCUMENTED
GET /v1/organization/spend_alerts/{alert_id} Retrieve organization spend alert — client.admin.organization.spend_alerts.retrieve DOCUMENTED
POST /v1/organization/spend_alerts/{alert_id} Update organization spend alert threshold_amount, currency (USD), interval* (month), notification_channel* client.admin.organization.spend_alerts.update DOCUMENTED
DELETE /v1/organization/spend_alerts/{alert_id} Delete organization spend alert — client.admin.organization.spend_alerts.delete DOCUMENTED

# Organization users

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/users List users limit, after, emails client.admin.organization.users.list ACCOUNT_RESTRICTED (403/401 with project key)
GET /v1/organization/users/{user_id} Retrieve user — client.admin.organization.users.retrieve DOCUMENTED
POST /v1/organization/users/{user_id} Modify user role, role_id, technical_level, developer_persona client.admin.organization.users.update DOCUMENTED
DELETE /v1/organization/users/{user_id} Delete user — client.admin.organization.users.delete DOCUMENTED

# Project roles & role bindings

Method Path Name Key params (query/body) Python SDK Status
GET /v1/projects/{project_id}/groups/{group_id}/roles List project group role assignments limit, after, order (asc desc) client.admin.organization.projects.groups.roles.list
POST /v1/projects/{project_id}/groups/{group_id}/roles Assign project role to group role_id* client.admin.organization.projects.groups.roles.create DOCUMENTED
GET /v1/projects/{project_id}/groups/{group_id}/roles/{role_id} Retrieve project group role — client.admin.organization.projects.groups.roles.retrieve DOCUMENTED
DELETE /v1/projects/{project_id}/groups/{group_id}/roles/{role_id} Unassign project role from group — client.admin.organization.projects.groups.roles.delete DOCUMENTED
GET /v1/projects/{project_id}/roles List project roles limit, after, order (asc desc) client.admin.organization.projects.roles.list
POST /v1/projects/{project_id}/roles Create project role role_name, permissions, description client.admin.organization.projects.roles.create DOCUMENTED
GET /v1/projects/{project_id}/roles/{role_id} Retrieve project role — client.admin.organization.projects.roles.retrieve DOCUMENTED
POST /v1/projects/{project_id}/roles/{role_id} Update project role permissions, description, role_name client.admin.organization.projects.roles.update DOCUMENTED
DELETE /v1/projects/{project_id}/roles/{role_id} Delete project role — client.admin.organization.projects.roles.delete DOCUMENTED
GET /v1/projects/{project_id}/users/{user_id}/roles List project user role assignments limit, after, order (asc desc) client.admin.organization.projects.users.roles.list
POST /v1/projects/{project_id}/users/{user_id}/roles Assign project role to user role_id* client.admin.organization.projects.users.roles.create DOCUMENTED
GET /v1/projects/{project_id}/users/{user_id}/roles/{role_id} Retrieve project user role — client.admin.organization.projects.users.roles.retrieve DOCUMENTED
DELETE /v1/projects/{project_id}/users/{user_id}/roles/{role_id} Unassign project role from user — client.admin.organization.projects.users.roles.delete DOCUMENTED

# Organization external storage

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/external_storage List external storage configurations project_id, after, order (asc desc), limit —
POST /v1/organization/external_storage Create an external storage configuration project_id, provider — DOCUMENTED
GET /v1/organization/external_storage/{external_storage_id} Get an external storage configuration — — DOCUMENTED
DELETE /v1/organization/external_storage/{external_storage_id} Delete an external storage configuration — — DOCUMENTED
POST /v1/organization/external_storage/{external_storage_id}/validate Validate an external storage configuration — — DOCUMENTED

# Organization spend limit

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/spend_limit Get organization spend limit — client.admin.organization.spend_limit.retrieve ACCOUNT_RESTRICTED (403/401 with project key)
POST /v1/organization/spend_limit Update organization spend limit threshold_amount, currency (USD), interval* (month) client.admin.organization.spend_limit.update DOCUMENTED
DELETE /v1/organization/spend_limit Delete organization spend limit — client.admin.organization.spend_limit.delete DOCUMENTED

# Project spend limit

Method Path Name Key params (query/body) Python SDK Status
GET /v1/organization/projects/{project_id}/spend_limit Get project spend limit — client.admin.organization.projects.spend_limit.retrieve DOCUMENTED
POST /v1/organization/projects/{project_id}/spend_limit Update project spend limit threshold_amount, currency (USD), interval* (month) client.admin.organization.projects.spend_limit.update DOCUMENTED
DELETE /v1/organization/projects/{project_id}/spend_limit Delete project spend limit — client.admin.organization.projects.spend_limit.delete DOCUMENTED

# 3. Roles & scopes catalogue

Level Predefined roles (legacy strings) Where they appear
Organization owner (billing, members, all reader rights), reader (make API requests, view org info, manage resources) Invite.role, OrganizationUser.role, POST /organization/users/{id} body role
Project owner, member ProjectUser.role, Invite.projects[].role, POST /organization/projects/{id}/users
Custom roles Role{id, name, description, permissions[], resource_type, predefined_role} created with POST /organization/roles (org-wide) or POST /projects/{id}/roles; assigned with the …/roles binding endpoints (role_id) Roles API
API key permission levels (dashboard) All, Restricted (per-resource read/write), Read-only; restricted keys carry scopes like api.model.request; audit log api_key.created.data.scopes[] records them dashboard + audit logs
Key types project key sk-proj-… (owned by a user or a service account, `owner.type: user service_account, owner_project_access: active

Governance knobs documented in production-best-practices: max API-key lifetime (org and project, project ≤ org), API Key Governance (allow only service-account keys / only user keys / block new keys; org restrictions win), key usage tracking (keys created before 2023-12-20 are untracked by default).

# 4. Usage & costs query cookbook (ACCOUNT_RESTRICTED for us — verified 403 api.usage.read)

All usage endpoints share the same query grammar (from the OpenAPI spec):

Param Type Notes
start_time* int (unix s) inclusive
end_time int exclusive
bucket_width 1m / 1h / 1d (default 1d) costs: only 1d
limit int buckets per page: 1d ≤ 31 (default 7), 1h ≤ 168 (default 24), 1m ≤ 1440 (default 60)
page string cursor from next_page
project_ids, user_ids, api_key_ids, models string[] filters (repeat the query key)
batch bool completions/embeddings/…: true = Batch API traffic only
group_by string[] completions: project_id, user_id, api_key_id, model, batch, service_tier; costs: project_id, line_item; images add size, source; audio speeches/transcriptions add model; code_interpreter_sessions/vector_stores: project_id
Endpoint Result object Key metrics
GET /v1/organization/usage/completions organization.usage.completions.result `input_tokens, input_cached_tokens, input_cache_write_tokens, input_uncached_tokens, output_tokens, input/output_text
…/usage/embeddings organization.usage.embeddings.result input_tokens, num_model_requests
…/usage/moderations organization.usage.moderations.result input_tokens, num_model_requests
…/usage/images organization.usage.images.result images, num_model_requests, dims size (256x256…1536x1024), source (image.generation, image.edit, image.variation)
…/usage/audio_speeches organization.usage.audio_speeches.result characters, num_model_requests
…/usage/audio_transcriptions organization.usage.audio_transcriptions.result seconds, num_model_requests
…/usage/vector_stores organization.usage.vector_stores.result usage_bytes
…/usage/code_interpreter_sessions organization.usage.code_interpreter_sessions.result num_sessions
…/usage/file_search_calls, …/usage/web_search_calls organization.usage.*_calls.result num_calls (web search adds search_context_size)
GET /v1/organization/costs organization.costs.result amount{value, currency:"usd"}, line_item, project_id, organization_id

Recipes (curl; -G turns --data-urlencode into query params):

bash
# daily completions tokens per model for the last 7 days
curl -G https://api.openai.com/v1/organization/usage/completions -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  --data-urlencode "start_time=$(( $(date +%s) - 7*86400 ))" --data-urlencode bucket_width=1d \
  --data-urlencode group_by=model --data-urlencode group_by=service_tier --data-urlencode limit=7
# hourly usage of one project, Batch only, paginated
curl -G https://api.openai.com/v1/organization/usage/completions -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  --data-urlencode start_time=1789000000 --data-urlencode bucket_width=1h --data-urlencode project_ids=proj_XXX \
  --data-urlencode batch=true --data-urlencode limit=168 --data-urlencode page=page_AAAA…
# spend in USD per day per line item and project
curl -G https://api.openai.com/v1/organization/costs -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  --data-urlencode start_time=$(( $(date +%s) - 30*86400 )) --data-urlencode bucket_width=1d \
  --data-urlencode group_by=line_item --data-urlencode group_by=project_id --data-urlencode limit=31

Python: client.admin.organization.usage.completions(start_time=…, bucket_width="1d", group_by=["model"], limit=7); costs: client.admin.organization.usage.costs(...). Runnable examples: examples/openai/admin/usage_costs.sh, admin_readonly.py, admin_readonly.ts (all return 403 on our account).

# 5. Spend limits, alerts, data retention, permissions

Resource Endpoints Body / semantics
Org spend limit GET/POST/DELETE /v1/organization/spend_limit threshold_amount (cents), currency: USD, interval: month; hitting it → 429 organization_spend_limit_exceeded on API traffic
Project spend limit GET/POST/DELETE /v1/organization/projects/{p}/spend_limit same body; → 429 project_spend_limit_exceeded
Spend alerts /v1/organization/spend_alerts[/{id}], /v1/organization/projects/{p}/spend_alerts[/{id}] threshold_amount, currency, interval, notification_channel{type:"email", recipients[], subject_prefix}
Data retention GET/POST /v1/organization/data_retention, GET/POST /v1/organization/projects/{p}/data_retention project retention_type: organization_default inherits; org sets the policy (ZDR / modified retention need approval)
Model permissions GET/POST/DELETE /v1/organization/projects/{p}/model_permissions `mode: allow_list
Hosted tool permissions GET/POST /v1/organization/projects/{p}/hosted_tool_permissions allow/deny hosted tools (web search, code interpreter, file search, MCP, …) per project
Rate limits GET /v1/organization/projects/{p}/rate_limits, POST …/rate_limits/{rate_limit_id} project.rate_limit{model, max_requests_per_1_minute, max_tokens_per_1_minute, max_images_per_1_minute, max_audio_megabytes_per_1_minute, max_requests_per_1_day, batch_1_day_max_input_tokens}; a project limit can only lower the org limit
Certificates (mTLS) org: GET/POST /v1/organization/certificates, …/{id} GET/POST/DELETE, …/activate, …/deactivate; project: GET …/projects/{p}/certificates, …/activate, …/deactivate upload PEM trust anchor (content, name), activate = enforce; API mTLS host mtls.api.openai.com; scopes api.mtls.read/write
External storage GET/POST /v1/organization/external_storage, GET/DELETE …/{id}, POST …/{id}/validate bring-your-own bucket for stored artifacts; audit events external_storage.registered/removed
Archive project POST /v1/organization/projects/{p}/archive irreversible; status: archived

# 6. Audit logs

GET /v1/organization/audit_logs (scope api.audit_logs.read; HTTP 401 not 403 without it). Filters: effective_at[gt|gte|lt|lte], project_ids[], event_types[], actor_ids[], actor_emails[], resource_ids[], limit, after, before. Each entry: {object:"organization.audit_log", id, type, effective_at, project{id,name}, actor{type: session|api_key, session{user, ip_address, user_agent, ja3, ja4, ip_address_details}, api_key{type: user|service_account, id, user|service_account}}, <type>: {payload}}.

Category Event types (149 total)
api_key api_key.created, api_key.updated, api_key.deleted
certificate certificate.created, certificate.updated, certificate.deleted
certificates certificates.activated, certificates.deactivated
checkpoint checkpoint.permission.created, checkpoint.permission.deleted
external_key external_key.registered, external_key.removed
external_storage external_storage.registered, external_storage.removed
group group.created, group.updated, group.deleted
invite invite.sent, invite.accepted, invite.deleted
ip_allowlist ip_allowlist.created, ip_allowlist.updated, ip_allowlist.deleted, ip_allowlist.config.activated, ip_allowlist.config.deactivated
login login.succeeded, login.failed
logout logout.succeeded, logout.failed
organization organization.updated
project project.created, project.updated, project.archived, project.deleted
rate_limit rate_limit.updated, rate_limit.deleted
resource resource.deleted
tunnel tunnel.created, tunnel.updated, tunnel.deleted
workload_identity_provider workload_identity_provider.created, workload_identity_provider.updated, workload_identity_provider.deleted
workload_identity_provider_mapping workload_identity_provider_mapping.created, workload_identity_provider_mapping.updated, workload_identity_provider_mapping.deleted
role role.created, role.updated, role.deleted, role.assignment.created, role.assignment.deleted, role.bound_to_resource, role.unbound_from_resource
scim scim.enabled, scim.disabled
service_account service_account.created, service_account.updated, service_account.deleted
user user.added, user.updated, user.deleted
tenant (enterprise workspace / ChatGPT-side) tenant.metadata.updated, tenant.microsoft_entra_mapping.upserted, tenant.microsoft_entra_mapping.deleted, tenant.workload_identity.provider.created, tenant.workload_identity.provider.updated, tenant.workload_identity.provider.archived, tenant.workload_identity.mapping.created, tenant.workload_identity.mapping.updated, tenant.workload_identity.mapping.archived, tenant.workload_identity.binding.created, tenant.workload_identity.principal.provisioned, tenant.workload_identity.access_token.issued, tenant.admin_api_key.created, tenant.admin_api_key.updated, tenant.admin_api_key.deleted, tenant.project_api_key.created, tenant.trusted_access.business_verification.started, tenant.trusted_access.application.submitted, tenant.chatgpt_access_token.revoked, tenant.migration.completed, tenant.sso.migrated, tenant.domains.migrated, tenant.sso_connection.created, tenant.sso_connection.updated, tenant.sso_connection.deleted, tenant.sso_connection.setup.started, tenant.policy.created, tenant.policy.updated, tenant.policy.deleted, tenant.policy.attached, tenant.policy.detached, tenant.principal_authentication_policy.resolved, tenant.scim.setup.started, tenant.scim.deletion.requested, tenant.scim.directory.created, tenant.product_access_policy.updated, tenant.resource_share_grant.created, tenant.resource_share_grant.updated, tenant.resource_share_grant.accepted, tenant.resource_share_grant.declined, tenant.resource_share_grant.revoked, tenant.resource_share_grant.deleted, tenant.service_account.updated, tenant.service_account.deleted, tenant.service_account.token.revoked, tenant.billing.overage_limit.updated, tenant.billing.alerts.updated, tenant.billing.info.updated, tenant.usage_limit.workspace.updated, tenant.usage_limit.group.updated, tenant.usage_limit.user.updated, tenant.usage_limit.increase_request.updated, tenant.usage_limit.increase_request.resolved, tenant.group.created, tenant.group.updated, tenant.group.deleted, tenant.group.member.added, tenant.group.member.removed, tenant.migration_rollout.status.updated, tenant.migration_rollout.tier.updated, tenant.role.metadata.updated, tenant.custom_role.created, tenant.custom_role.updated, tenant.custom_role.deleted, tenant.role_assignment.created, tenant.role_assignment.deleted, tenant.resource_role_assignment.created, tenant.resource_role_assignment.deleted, tenant.resource_access.updated, tenant.resource_access.deleted, tenant.ads_account.onboarding.redemption, tenant.session_policy.created, tenant.session_policy.updated, tenant.session_policy.deleted, tenant.session_revocation.started, tenant.third_party_app_policy.updated, tenant.user.added, tenant.user.updated, tenant.user.removed, tenant.user.looked_up, tenant.user.invited, tenant.membership.revoked, tenant.api_organization_invite.upserted, tenant.api_organization_invite.deleted, tenant.chatgpt_workspace_invite.upserted, tenant.membership.accepted, tenant.membership.declined, tenant.workspace_invite_email_settings.updated

Payload fields per event are in generated/fragments/audit-log-events/openai-audit-log-events.json (57 events carry a typed payload in the spec; the tenant.* enterprise-workspace events are enum-only).

# 7. Verified behaviour with a non-admin key (2026-09-18)

Call HTTP Body
GET /v1/organization/{users,invites,projects,admin_api_keys,spend_limit,spend_alerts,data_retention} 403 {"error": "You have insufficient permissions for this operation. Missing scopes: api.management.read. Check that you have the correct role in your organization, and if you're using a restricted API key, that it has the necessary scopes."} — note error is a bare string
GET /v1/organization/usage/completions, GET /v1/organization/costs 403 same shape, api.usage.read
GET /v1/organization/roles / groups 403 api.roles.read / api.groups.read
GET /v1/organization/certificates 403 api.mtls.read … correct role in your organization (Owner)
GET /v1/organization/external_storage 403 structured: {"error":{"message":"… api.external_storage.read …","type":"invalid_request_error","param":null,"code":"insufficient_permissions"}}
GET /v1/organization/audit_logs 401 structured, api.audit_logs.read, code: null

Response headers on these errors still include x-request-id, openai-version: 2020-10-01, openai-processing-ms, and (except certificates/audit logs) openai-organization / openai-project.

# 8. SDK access

python
from openai import OpenAI
client = OpenAI(admin_api_key=os.environ["OPENAI_ADMIN_KEY"])      # Python >= 2.34.0
users = client.admin.organization.users.list(limit=20)              # SyncConversationCursorPage -> iterate
for u in users: print(u.id, u.email, u.role)
client.admin.organization.projects.model_permissions.update("proj_abc", mode="allow_list", model_ids=["gpt-4.1"])
ts
const client = new OpenAI({ adminAPIKey: process.env.OPENAI_ADMIN_KEY }); // Node >= 6.36.0
for await (const log of client.admin.organization.auditLogs.list({ limit: 50 })) console.log(log.type);

Go option.WithAdminAPIKey (≥ 3.34.0), Java OpenAIOkHttpClient.builder().adminApiKey(...) (≥ 4.34.0), Ruby OpenAI::Client.new(admin_api_key:) (≥ 0.61.0).