"""Admin API read-only tour with the official Python SDK (openai 3.16.2): users, projects, audit logs, usage (completions by model, daily) and costs. Never mutates anything. STATUS: ACCOUNT_RESTRICTED — run 2026-09-18 with our project key (no Admin key available): every call raised openai.PermissionDeniedError (HTTP 403, "Missing scopes: api.management.read" / api.usage.read) and audit logs raised AuthenticationError (HTTP 401, "Missing scopes: api.audit_logs.read"). With OPENAI_ADMIN_KEY set the same code prints real data. Run: .venv/bin/python examples/openai/admin/admin_readonly.py """ from __future__ import annotations import os import sys import time from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[3])) from scripts import live # noqa: E402 loads .env, gives log_request import openai # noqa: E402 from openai import OpenAI # noqa: E402 client = OpenAI(admin_api_key=os.environ.get("OPENAI_ADMIN_KEY") or os.environ["OPENAI_API_KEY"], max_retries=0) start = int(time.time()) - 7 * 86400 def attempt(label: str, method: str, path: str, fn): try: out = fn() live.log_request("openai", method, path, 200, 0, f"admin example {label}") print(f"200 {label}: {out}") except openai.APIStatusError as e: # PermissionDeniedError(403) / AuthenticationError(401) / NotFoundError... live.log_request("openai", method, path, e.status_code, 0, f"admin example {label}: {type(e).__name__}") print(f"{e.status_code} {label}: {type(e).__name__} code={e.code!r} request_id={e.request_id} :: {live.mask(str(e.body))[:160]}") attempt("users", "GET", "/v1/organization/users", lambda: [u.email for u in client.admin.organization.users.list(limit=5).data]) attempt("projects", "GET", "/v1/organization/projects", lambda: [(p.id, p.name, p.status) for p in client.admin.organization.projects.list(limit=5).data]) attempt("audit_logs", "GET", "/v1/organization/audit_logs", lambda: [(a.type, a.effective_at) for a in client.admin.organization.audit_logs.list(limit=5).data]) attempt("usage.completions", "GET", "/v1/organization/usage/completions", lambda: [(b.start_time, [(r.model, r.input_tokens, r.output_tokens) for r in b.results]) for b in client.admin.organization.usage.completions(start_time=start, bucket_width="1d", group_by=["model"], limit=7).data]) attempt("costs", "GET", "/v1/organization/costs", lambda: [(b.start_time, [(r.line_item, r.amount.value) for r in b.results]) for b in client.admin.organization.usage.costs(start_time=start, bucket_width="1d", group_by=["line_item"], limit=7).data])