Founding keys are opena year free at 6,000 req/hour, for the first 1,000 developersClaim yours

OpenAI

Point the official openai SDK (or curl) at https://openai.sandboxapis.dev via the client's baseURL option. Auth is a Bearer admin key (sk-admin-… — any value is accepted here). This is the org's OpenAI platform telemetry: users, projects, admin-key metadata, completions usage, and costs — the codex cohort's usage, reconciling with the git activity on the git hosts.

REST · 122 endpointsMCP-ready

Coverage badge

Deep113/122 · 93%

The share of read rows with a final answer — served and verified, a deviation, retired upstream, or a reviewed empty/refusal. Computed in the coverage manifest, copied here.

Live host
openai.sandboxapis.dev
Pinned hosts
6 — generation 5, 6, 8, 9, 10, 11
Serving since
2026-08-18
Lifecycle
Live

Served & verified

44 / 36%

Answering with real universe data, each response checked against OpenAI's published spec by the conformance suite on this build.

The full read API

122

Every read surface OpenAI publishes, deferred long tail included, minus the rows excluded by policy. Writes are out of scope: this universe is read-only.

Not served yet

78

Each returns an explicit, provider-shaped coverage error naming the gap — never invented data.

01 / The swap

Point your client at a different base URL.

No SDK of ours, no shim, no recorded fixtures. The same client library you already use, one environment variable different.

shell
curl -H 'Authorization: Bearer any-key' "https://openai.sandboxapis.dev/v1/organization/users"

Verified drop-in clients

  • openai7.5.0

The versions the conformance suite drives against this host on every build — pinned in coverage/client-pins.yaml, and watched weekly for upstream releases, because a client library moving without us is how a shipped integration breaks silently.

02 / Coverage by family

Every read surface, grouped the way OpenAI groups it.

All 122 rows the coverage manifest carries for OpenAI, deferred long tail included and nothing capped. Open a family, or filter by path to find the exact endpoint your client calls.

Status — what a conformance test found

served & verified
answers with real universe data, and this build checked that response against the vendor's spec.
deviation
served and faithful to the real provider, but failing the vendored spec — usually a bug in the spec.
retired
the vendor removed the endpoint; snapshots pinned before that date still serve it.
planned / deferred
not served yet — an explicit coverage error naming the gap, never invented data.
excluded
out of the claim by policy (writes, and surfaces we refuse); not in any denominator on this page.

Mode — what kind of answer a row gets

derive
the response is computed from artifact rows that already exist
generate
canon does not carry this yet; the generator will produce it, then derive
empty
the true answer for this universe is an empty collection — reason + reviewed date required
refuse
mirror the provider's OWN refusal (e.g. its 403 for a non-admin token) — reason + reviewed date required
read-only
a write named in the manifest because clients probe it; the read-only 403 IS its final response, and it never joins the badge denominator

A row with no mode shown has not been judged yet. Modes are the manifest's own words, from coverage/MODES.yaml; every empty and refuse carries a written reason and a review date before it counts as final.

Badge — where Deep starts

Full
every published read row has a final answer
Deep
60% up to 100%
Partial
25% up to 60%
Preview
under 25%

REST + GraphQL + git rows that are not `excluded`. Write operations are NOT rows (DECISIONS 2026-09-01 decision 9): they are counted in meta.write_operations and never enter this ratio.

122 read surfaces in 14 families

platform0 of 55 served & verified
GET
/assistants

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/assistants/{assistant_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/audio/voice_consents

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/audio/voice_consents/{consent_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/batches

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/batches/{batch_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/chat/completions

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/chat/completions/{completion_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/chat/completions/{completion_id}/messages

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/conversations/{conversation_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/conversations/{conversation_id}/items

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/conversations/{conversation_id}/items/{item_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals/{eval_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals/{eval_id}/runs

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals/{eval_id}/runs/{run_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals/{eval_id}/runs/{run_id}/output_items

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/evals/{eval_id}/runs/{run_id}/output_items/{output_item_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/files

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/files/{file_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/files/{file_id}/content

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/fine_tuning/jobs

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/fine_tuning/jobs/{fine_tuning_job_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/fine_tuning/jobs/{fine_tuning_job_id}/checkpoints

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/fine_tuning/jobs/{fine_tuning_job_id}/events

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/organization/projects/{project_id}/hosted_tool_permissions

refuse — the vendored document declares security: [{AdminApiKeyAuth: []}] on retrieve-project-hosted-tool-permissions - the SAME scheme as /organization/users, /organization/costs and the sibling /organization/projects/{project_id}/model_permissions this replica serves at 200 - so the sandbox admin key IS the right credential here and a 401 invalid_api_key would contradict the document; this org configures no hosted-tool permission set, so OpenAI's own 404 for an object that does not exist is the answer, the same shape as /organization/certificates/{certificate_id} (founder ruling 2026-09-03 on proposal 1 of coverage/reviews/2026-09-03-openai-refuse-shapes.md, superseding the INFERENCE-plane 401 read that grouped this row by its "Hosted tools" tag rather than by its plane)

deferred
Long tail
GET
/responses/{response_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/responses/{response_id}?beta=true

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/responses/{response_id}/input_items

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/responses/{response_id}/input_items?beta=true

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills/{skill_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills/{skill_id}/content

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills/{skill_id}/versions

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills/{skill_id}/versions/{version}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/skills/{skill_id}/versions/{version}/content

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/messages

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/messages/{message_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/runs

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/runs/{run_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/runs/{run_id}/steps

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/threads/{thread_id}/runs/{run_id}/steps/{step_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}/file_batches/{batch_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}/file_batches/{batch_id}/files

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}/files

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}/files/{file_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/vector_stores/{vector_store_id}/files/{file_id}/content

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/videos

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/videos/{video_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/videos/{video_id}/content

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
GET
/videos/characters/{character_id}

refuse — the sandbox key is an OpenAI ADMIN key and this row is on the INFERENCE plane (assistants, threads, responses, files, batches, evals, fine-tuning, vector stores, skills, videos, conversations, audio consents); OpenAI answers 401 invalid_api_key when an admin key reads it, and SandboxAPIs mirrors the admin surface, not the inference surface

deferred
Long tail
usage11 of 11 served & verified
GET
/organization/costs
served & verified
Core
GET
/organization/usage/audio_speeches

this org's OpenAI story is coding: it recorded no speech usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/audio_transcriptions

this org's OpenAI story is coding: it recorded no transcription usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/code_interpreter_sessions

this org's OpenAI story is coding: it recorded no code-interpreter usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/completions
served & verified
Core
GET
/organization/usage/embeddings

this org's OpenAI story is coding: it recorded no embedding usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/file_search_calls

this org's OpenAI story is coding: it recorded no file-search usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/images

this org's OpenAI story is coding: it recorded no image usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/moderations

this org's OpenAI story is coding: it recorded no moderation usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/vector_stores

this org's OpenAI story is coding: it recorded no vector-store usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/usage/web_search_calls

this org's OpenAI story is coding: it recorded no web-search usage in the window, so the family's page is real, spec-validating and empty (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
<none>0 of 10 served & verified
GET
/chatkit/threads

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/chatkit/threads/{thread_id}

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/chatkit/threads/{thread_id}/items

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/containers

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/containers/{container_id}

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/containers/{container_id}/files

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/containers/{container_id}/files/{file_id}

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/containers/{container_id}/files/{file_id}/content

refuse — the same inference plane as the tagged platform rows — chatkit threads and code-interpreter containers only read as separate here because the spec leaves their tag empty; an OpenAI admin key gets 401 invalid_api_key for them too

deferred
Long tail
GET
/organization/projects/{project_id}/spend_limit

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
GET
/organization/spend_limit

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
groups7 of 10 served & verified
GET
/organization/groups

SERVED 2026-09-10 (hello-15): canon's IdentityGroup — reader.listIdentityGroups(org) (reader.ts:2472) — in the vendored GroupListResource envelope. A GROUP IS NOT A TEAM and this reads neither a team nor a roster: the generator builds each group out of an access fact canon already records (everyone who writes code, everyone who has reviewed something, everyone who may cut a release, the machine accounts) and the canon suite asserts no group has exactly a team's membership, which groups.test.ts re-asserts over the served rows. `is_scim_managed` is the FEDERATION's fact, read off IdentityProviderConfig.scim_enabled, so every group this provider asserts reports the same value. `group_type` is `group` and never `tenant_group`: a tenant group belongs to an OpenAI enterprise tenant standing above the organization, and these are asserted by the organization's own provider. The id is openaiId("group_", "idgroup-00N") — the same fnv-1a derivation user-/proj_/key_ ride, so it is a pure function of the canonical id rather than a counter over an iteration order. Older pins answer the noIdentityGroups generation-gap 404 naming openai-2020-10-g10, never an empty list

served & verified
Long tail
GET
/organization/groups/{group_id}

SERVED 2026-09-10 (hello-15): the same IdentityGroup by id, byte-identical to the row the list publishes — conformance asserts every group both ways. GroupResponse carries NO `object` field and spells the flag `is_scim_managed`; the document's `Group` schema (the summary embedded in a role assignment) carries `object: "group"` and `scim_managed` instead, and these two operations return GroupResponse. A canonical `idgroup-00N` does NOT address a group here, which conformance asserts too

served & verified
Long tail
GET
/organization/groups/{group_id}/roles

SERVED 2026-09-12 (hello-17): the ORGANIZATION role an identity group holds, from the `scope_kind = 'group'` membership hello-17's features.grants writes — reader.groupRole(group) — in the vendored RoleListResource envelope. ONE ROW OR NONE, and that is canon's shape rather than a slice taken in the renderer: a group's role is the FLOOR of its members' own authority, because a grant to a group reaches everyone in it and granting more than its least-authorised member already holds would elevate that person through the directory, so canon writes exactly one row per group (decisions/2026-09-11-2304-hello-17-grants.md). The objects are the SAME AssignedRoleDetails under the SAME ids the user assignments publish — one catalog, two kinds of principal — which groups.test.ts asserts directly, because a schema cannot. Paged by the Roles API's own bounds: list-group-role-assignments declares no limit default and no order default, exactly as list-user-role-assignments does not, so both take 0..1000 / default 1000 / order asc from list-roles. hello-16 and every older artifact answer the noGrants generation-gap 404 naming generation hello-17 — never an empty list, which would be a claim about the ORGANIZATION rather than about the snapshot the caller pinned (the 2026-09-02 ruling). FOUNDER RULING 2026-09-10, round 13

served & verified
Long tail
GET
/organization/groups/{group_id}/roles/{role_id}

SERVED 2026-09-12 (hello-17): the same assignment by id, byte-identical to the row the list publishes — conformance asserts every group both ways. A REAL catalog role this group does not hold misses here too, the way it does for a user one route over: which role is held is the question the route answers, and a group holds exactly one. The by-id half was PROPOSED as a `refuse` on the reading that no role id could ever resolve for a group; hello-17's grant makes exactly one resolve per group, so the proposal is withdrawn rather than ruled and this is a `derive` like its list. FOUNDER RULING 2026-09-10, round 13

served & verified
Long tail
GET
/organization/groups/{group_id}/users

SERVED 2026-09-10 (hello-15): a group's canonical members (IdentityGroup.members) INTERSECTED with this organization's own roster, in the vendored UserListResource envelope. THE INTERSECTION IS THE JUDGMENT AND IT IS THE ONLY COHERENT ONE: an OpenAI organization user on this replica is a codex seat holder (renderer-openai/src/render.ts members()), canon's group rosters are rosters of PEOPLE, and serving a person with no account here would publish a user id that 404s against /organization/users/{user_id} standing right beside it — invariant #5 broken in one response pair. OpenAI's own question is which USERS are assigned to the group, and a person with no account is not one of its users; the same reading /v3/enterprise/members/service-users takes on Devin. NOTHING IS HIDDEN, because no shape here publishes a member count: GroupResponse is {id, name, created_at, is_scim_managed, group_type} and carries neither a size nor canon's description. Two of the four groups therefore list nobody, which is DATA rather than a mode — the Default project lists no API key for the same kind of reason — and conformance asserts the served set equals the intersection FROM BOTH SIDES, so a widening and a narrowing are both red. `order` defaults to DESC here and asc on every sibling, which is the document's own default. Older pins answer the noIdentityGroups generation gap

served & verified
Long tail
GET
/organization/groups/{group_id}/users/{user_id}

SERVED 2026-09-10 (hello-15): the same membership addressed by (group, user), in the vendored GroupMemberUser shape — the list item plus three fields. A real organization user who is NOT in this group misses here too, because group membership is the question this route answers. `picture` is null because nothing in this universe is a profile-picture URL: canon holds identicon bytes for an org and a repo and nothing keyed to a person, and an authored URL would resolve nowhere (invariant #4). `is_service_account` READS person.is_bot rather than being hard-coded, so it follows rather than being asserted; it is false for everyone this route can reach today because canon's only non-human identity is the CI bot and it holds no codex seat. `user_type` is `user` and never `tenant_user`, for the reason group_type is never tenant_group

served & verified
Long tail
GET
/organization/projects/{project_id}/groups

no identity group has access to a project, and no generation of this universe grants one. The vendored summary on list-project-groups is "Lists the groups that have ACCESS to a project" and its item, ProjectGroup, is a GRANT object (object + project_id + group_id + group_name + group_type + created_at) rather than a group — so this list can only carry rows canon does not have. hello-17's features.grants writes one `scope_kind = 'group'` membership per identity group, which attaches the group to a ROLE; IdentityGroup itself carries an org, a provider, a name slot, a member list and a creation instant and nothing that names a container, and a project on this host is minted per TEAM holding a codex seat (renderer-openai/src/render.ts projects()) with no group on either side of it. UNGATED BY GENERATION, deliberately: a generation gap would say the caller's snapshot is too old to answer where the true statement is that the answer is the same on every snapshot there is. The project still has to resolve — a ruling about a project nobody has is a typo answered confidently — and the bounds validated are this operation's own (limit 0..100 default 20, order default asc), which differ from every sibling's. FOUNDER RULING 2026-09-11, round 17

served & verified
Long tail
GET
/organization/projects/{project_id}/groups/{group_id}

refuse — the id half of the project-groups pair: its list is empty because no identity group has access to a project, so no (project, group) grant can resolve and OpenAI's own 404 is the only possible answer — the certificates/invites shape ruled 2026-09-01. It addresses a ProjectGroup (the grant) and not a Group, so there is nothing for {group_id} to resolve against and a REAL group id misses here exactly as an invented one does, which is the ruling rather than a gap. Parent-guarded (the project resolves first) and ungated by generation, for the reason the list carries. FOUNDER RULING 2026-09-11, round 17

deferred
Long tail
GET
/projects/{project_id}/groups/{group_id}/roles

refuse — NOT the project-scoped twin of /organization/groups/{group_id}/roles, and the difference is what decides the mode: this one is scoped BY a group's access to a project, and /organization/projects/{project_id}/groups is `empty` because no identity group has that access in any generation (founder ruling 2026-09-11, round 17). So the (project, group) pair never resolves and OpenAI's own 404 is the only possible answer — the same reading /projects/{project_id}/users/{user_id}/roles already takes one route over, where a person who is not in the project misses rather than getting an empty list. hello-17's features.grants attaches a group to an ORGANIZATION role, which /organization/groups/{group_id}/roles serves; it attaches nothing to a container. The refusal names the GROUP and not the role, because the group's access is the first thing that fails and the request never reaches a role. Parent-guarded (the project resolves first) and ungated by generation, for the reason the project-groups pair carries. FOLLOWS FROM FOUNDER RULING 2026-09-11, round 17

deferred
Long tail
GET
/projects/{project_id}/groups/{group_id}/roles/{role_id}

refuse — the id half of the project group-roles pair: its list refuses because no identity group has access to a project, so the (project, group) pair never resolves and no role id under it can either — OpenAI's own 404, naming the group rather than the role for the reason the list gives. Same guard, same ungating, same ruling. FOLLOWS FROM FOUNDER RULING 2026-09-11, round 17

deferred
Long tail
projects9 of 10 served & verified
GET
/organization/projects
served & verified
Core
GET
/organization/projects/{project_id}
served & verified
Core
GET
/organization/projects/{project_id}/api_keys
served & verified
Core
GET
/organization/projects/{project_id}/api_keys/{api_key_id}
served & verified
Core
GET
/organization/projects/{project_id}/model_permissions

an empty DENY list — no model is denied, which is exactly a universe with no restriction evidence; an empty ALLOW list would claim no model may be called, which the usage report disproves (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/projects/{project_id}/rate_limits

these are policy NUMBERS and this org configures no override; any figure printed here would be a placeholder copied off the spec's example, which invariant #4 forbids. The empty list says 'no override configured' (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/projects/{project_id}/service_accounts

the canon's only non-human identity is the CI bot: it holds no codex seat, belongs to no team and produced no OpenAI usage, so nothing here is a project-scoped machine identity (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/projects/{project_id}/users
served & verified
Core
GET
/organization/projects/{project_id}/users/{user_id}
served & verified
Core
GET
/organization/projects/{project_id}/service_accounts/{service_account_id}

refuse — the id half of the service-account pair: /organization/projects/{project_id}/service_accounts is `empty` because the CI bot is not a project-scoped machine identity, so no service-account id can resolve and OpenAI's own 404 is the only possible answer (DECISIONS 2026-09-01 [coverage/A0]). The refusal suite owns this row: its OPENAI_ENDPOINTS expectMiss entry was removed 2026-09-03 (founder ruling on proposal 2 of coverage/reviews/2026-09-03-openai-refuse-shapes.md) because it made a refuse row read `green`, and a refusal is terminal by mode, never green by status

planned
Core
roles8 of 8 served & verified
GET
/organization/roles

SERVED 2026-09-10 (hello-16): reader.listMembershipRoles() (packages/artifact/src/reader.ts:3042) in the vendored PublicRoleListResource envelope. Five catalog ROWS rather than an enum rendered at request time: `Role.permissions` is REQUIRED, and a permission list composed inside a renderer is a fact invented at serving time. `permissions` stays canon's closed `scope:level` vocabulary, which the schema types `array<string>` with no enum; `resource_type` is `api.organization`, the document's own example for this scope; and `predefined_role` is DERIVED — a role minted at the organization's own creation instant was created by nobody in it, which conformance asserts as a biconditional rather than as the current answer

served & verified
Long tail
GET
/organization/roles/{role_id}

SERVED 2026-09-10 (hello-16): the same catalog row by id — reader.listMembershipRoles() (reader.ts:3042) addressed by openaiId("role_", …), byte-identical to the row the catalog serves, which conformance asserts for all five. An id the catalog does not carry is OpenAI's own `Role <id> not found`, never the empty-body coverage miss

served & verified
Long tail
GET
/organization/users/{user_id}/roles

SERVED 2026-09-10 (hello-16): the role on this person's ACTIVE organization membership — reader.listMemberships("org", org) (reader.ts:3020) — rendered as the catalog row it names, in the vendored RoleListResource envelope. A pending membership is an invitation and is not an assignment, which is the only place that distinction could have been lost. The four nulls are facts: canon records no edit to a catalog row (`updated_at`), no author for one (`created_by`), and every assignment is held directly rather than inherited (`assignment_sources`)

served & verified
Long tail
GET
/organization/users/{user_id}/roles/{role_id}

SERVED 2026-09-10 (hello-16): the same assignment addressed by (user, role) — reader.listMemberships("org", org) (reader.ts:3020). A REAL catalog role this person does not hold misses here too, because which role you hold is the question this route answers; conformance drives both halves

served & verified
Long tail
GET
/projects/{project_id}/roles

SERVED 2026-09-10 (hello-16): the same reader.listMembershipRoles() catalog (reader.ts:3042) at project scope — `resource_type: api.project`, the document's own example for this scope, under ids of its own because OpenAI addresses an organization role and a project role as different objects. Same name, same description, same permissions, same created_at as the organization row, which conformance asserts; an organization role id does NOT address a project role, which it asserts too

served & verified
Long tail
GET
/projects/{project_id}/roles/{role_id}

SERVED 2026-09-10 (hello-16): the project catalog row by id — reader.listMembershipRoles() (reader.ts:3042). The project must still resolve, so an unknown {project_id} is OpenAI's own `Project <id> not found` rather than a cheerful empty catalog

served & verified
Long tail
GET
/projects/{project_id}/users/{user_id}/roles

SERVED 2026-09-10 (hello-16): the role on this person's membership in the container the PROJECT IS — reader.listMemberships("team", team) for a team project and reader.listMemberships("org", org) for the Default project (reader.ts:3020), since a project here is a team holding a codex seat and Default is the organization's own project. One rule, total over every project this renderer mints, which is why an assignment can never name somebody outside the container; a user who is not in the project misses rather than getting an empty list

served & verified
Long tail
GET
/projects/{project_id}/users/{user_id}/roles/{role_id}

SERVED 2026-09-10 (hello-16): the same project assignment addressed by (project, user, role) — reader.listMemberships over team and org scope (reader.ts:3020). Byte-identical to the row the list serves, and a role the person does not hold in THIS project is OpenAI's own 404

served & verified
Long tail
spend-alerts0 of 4 served & verified
GET
/organization/projects/{project_id}/spend_alerts

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
GET
/organization/projects/{project_id}/spend_alerts/{alert_id}

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
GET
/organization/spend_alerts

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
GET
/organization/spend_alerts/{alert_id}

generate — new canon entity SpendAlert, hung off the Subscription the A15 wave lands

deferred
Long tail
certificates2 of 3 served & verified
GET
/organization/certificates

OpenAI answers {"data": []} to an admin key for the org certificate list when no mTLS certificate has been uploaded, and this org uploaded none — refusing would be false to the provider

served & verified
Long tail
GET
/organization/projects/{project_id}/certificates

OpenAI answers {"data": []} to an admin key for a project certificate list when no mTLS certificate has been uploaded, and this org uploaded none — refusing would be false to the provider

served & verified
Long tail
GET
/organization/certificates/{certificate_id}

refuse — the id half of the certificate pair: this org uploaded no mTLS certificate, so no certificate id can resolve and OpenAI's own 404 is the only possible answer (the by-id shape ruled in DECISIONS 2026-09-01 [coverage/A0] for the invite and service-account rows)

deferred
Long tail
admin-keys2 of 2 served & verified
GET
/organization/admin_api_keys
served & verified
Core
GET
/organization/admin_api_keys/{key_id}
served & verified
Core
data-retention0 of 2 served & verified
GET
/organization/data_retention

generate — new canon entity RetentionPolicy

deferred
Long tail
GET
/organization/projects/{project_id}/data_retention

generate — new canon entity RetentionPolicy

deferred
Long tail
invites1 of 2 served & verified
GET
/organization/invites

every member of this org accepted; no invite is pending (DECISIONS 2026-08-20 [P31/openai])

served & verified
Core
GET
/organization/invites/{invite_id}

refuse — the id half of the invites pair: /organization/invites is `empty` because every member already accepted, so no invite id can resolve and OpenAI's own 404 is the only possible answer (DECISIONS 2026-09-01 [coverage/A0]); `derive` was the wrong word for that answer. The refusal suite owns this row: its OPENAI_ENDPOINTS expectMiss entry was removed 2026-09-03 (founder ruling on proposal 2 of coverage/reviews/2026-09-03-openai-refuse-shapes.md) because it made a refuse row read `green`, and a refusal is terminal by mode, never green by status

planned
Core
models2 of 2 served & verified
GET
/models
served & verified
Core
GET
/models/{model}
served & verified
Core
users2 of 2 served & verified
GET
/organization/users
served & verified
Core
GET
/organization/users/{user_id}
served & verified
Core
audit-logs0 of 1 served & verified
GET
/organization/audit_logs

generate — A WIDENING, NOT A BUILD: canon.AdminAuditEvent exists (packages/canon/src/support-desk.ts:690) and its own doc comment calls it "GENERIC by construction". The action vocabulary (AuditAction, :602), the change vocabulary (AuditChangeSlot, :633), the target vocabulary (AuditTargetKind, :611) and the RFC 5737 source-address rule (AuditSourceBlock, :652) all shipped, and Zendesk serves the table today (reader.listAuditEvents(), ruled 2026-09-07). TWO things are missing and neither is the entity: git-host members on AuditTargetKind, and a generation that WRITES personActor — the field is declared for exactly this wave and "this generation writes none" (:695-697)

deferred
Next

03 / What's simulated

One data set, rendered in OpenAI's dialect.

Every OpenAI call resolves against the same simulated data set every other provider serves. Counted from the openai-2020-10-g11 artifact (universe generation 11):

What another provider has to agree with, and the test that makes it

Each line below is one assertion in the conformance suite named beside it — run on every build, over one artifact, through the real renderers. Nothing is claimed here that no expect checks.

05 / Pinned snapshots

Frozen universes, on their own hostnames.

Each pin regenerates byte-identically on every request, so a test written against one never drifts. Generations are DIFFERENT universes, not versions of one — never swap a suffix expecting the same data.

PinHostUniverse generationOpenAI API versionRepository files
openai-2020-10openai-2020-10.snap.sandboxapis.devgeneration 52020-10-01served
openai-2020-10-g10openai-2020-10-g10.snap.sandboxapis.devgeneration 102020-10-01served
openai-2020-10-g11openai-2020-10-g11.snap.sandboxapis.devgeneration 112020-10-01served
openai-2020-10-g6openai-2020-10-g6.snap.sandboxapis.devgeneration 62020-10-01served
openai-2020-10-g8openai-2020-10-g8.snap.sandboxapis.devgeneration 82020-10-01served
openai-2020-10-g9openai-2020-10-g9.snap.sandboxapis.devgeneration 92020-10-01served

Need an endpoint that is not served yet?

Every row OpenAI's manifest carries is on this page, so “not here” is an answer rather than a gap in the rendering. Tell us which path and which client, and it moves up the queue — the order is set by what people ask for.

Request coverage