Skip to main content

Unofficial Python SDK for the ChatGPT Codex backend API

Project description

codex-backend-sdk

Unofficial Python SDK for the ChatGPT Codex backend API (chatgpt.com/backend-api/codex).

This package mirrors the official OpenAI Python SDK shape for the API surface that the Codex backend exposes. Use OpenAI, client.responses.create(...), and client.models.list() just as you would with openai-python, with Codex-specific authentication and backend limitations under the hood.

Requirements: a ChatGPT Plus, Pro, or Enterprise subscription. Authentication goes through ChatGPT OAuth and stores tokens in ~/.codex/auth.json.

Disclaimer: This is an independent, community-maintained library that reverse-engineers undocumented endpoints of chatgpt.com. It is not affiliated with, endorsed by, or supported by OpenAI.

Installation

git clone https://github.com/B4PT0R/codex-backend-sdk.git
cd codex-backend-sdk
pip install -e .

Basic Usage

from codex_backend_sdk import OpenAI

client = OpenAI().authenticate()

response = client.responses.create(
    model="gpt-5.4",
    input="Explain quicksort in one paragraph.",
)

print(response.output_text)

Streaming

stream = client.responses.create(
    model="gpt-5.4",
    input="Say 'hi' five times.",
    stream=True,
)

for event in stream:
    if event.type in {"response.output_text.delta", "response.content_part.delta"}:
        delta = event.delta
        print(delta if isinstance(delta, str) else delta.get("text", ""), end="")

Models

models = client.models.list()
for model in models:
    print(model.id, model.display_name, model.context_window)

info = client.models.retrieve("gpt-5.4")

Multi-Turn Input

The Codex backend does not expose previous_response_id, so pass prior input/output items explicitly.

history = [
    {"role": "user", "content": "My name is Alice. Say OK."},
]

reply1 = client.responses.create(input=history).output_text
history.append({"role": "assistant", "content": reply1})
history.append({"role": "user", "content": "What is my name?"})

reply2 = client.responses.create(input=history).output_text
print(reply2)

Function Calling

import json

tools = [{
    "type": "function",
    "name": "get_weather",
    "description": "Get the current weather for a city.",
    "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
        "additionalProperties": False,
    },
}]

first = client.responses.create(
    input="What's the weather in Paris?",
    tools=tools,
)

call = next(item for item in first.output if item["type"] == "function_call")
result = {"temperature": 18, "unit": "celsius", "condition": "cloudy"}

second = client.responses.create(
    input=[
        call,
        {
            "type": "function_call_output",
            "call_id": call["call_id"],
            "output": json.dumps(result),
        },
    ],
    tools=tools,
)

print(second.output_text)

Structured Output

schema = {
    "title": "person",
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
    },
    "required": ["name", "age"],
    "additionalProperties": False,
}

response = client.responses.create(
    input="Extract: Bob is 42 years old.",
    text={
        "format": {
            "type": "json_schema",
            "name": "person",
            "schema": schema,
            "strict": True,
        }
    },
)

Supported Backend Endpoints

The SDK exposes the supported backend endpoints through either OpenAI-shaped resources (responses, models, realtime) or Codex-only resources (codex).

Backend endpoint SDK method Notes
POST /backend-api/codex/responses client.responses.create(...) Stream-only backend; non-streaming SDK calls are collected from SSE events.
POST /backend-api/codex/responses/compact client.responses.compact(...) Codex-specific helper for encrypted context compaction.
POST /backend-api/codex/memories/trace_summarize client.codex.memories.trace_summarize(...) Raw Codex memory trace summarization helper.
GET /backend-api/codex/models client.models.list() / client.models.retrieve(...) OpenAI-shaped model objects with Codex metadata preserved as extra fields.
POST /backend-api/codex/realtime/calls client.realtime.calls.create(...) OpenAI-shaped SDP call creation for realtime sessions.
wss://api.openai.com/v1/realtime?model=... client.realtime_websocket_url(...) / client.realtime_websocket_headers(...) Helper surface used by codex-agent's realtime plugin.
POST /v1/embeddings client.embeddings.create(...) Uses the Codex OAuth access token against api.openai.com; verified with text-embedding-3-small.
POST /v1/audio/transcriptions client.audio.transcriptions.create(...) Uses the Codex OAuth access token against api.openai.com; verified with gpt-4o-mini-transcribe.
GET /backend-api/wham/usage client.codex.usage() Codex/ChatGPT quota and rate-limit status.
GET /backend-api/wham/config/requirements client.codex.config.requirements() Raw managed requirements/config payload for the authenticated account.
GET /backend-api/wham/tasks/list client.codex.tasks.list(...) Raw Codex cloud task listing.
GET /backend-api/wham/tasks/{task_id} client.codex.tasks.retrieve(task_id) Raw Codex cloud task detail.
GET /backend-api/wham/tasks/{task_id}/turns client.codex.tasks.turns.list(task_id) Raw task turn mapping.
GET /backend-api/wham/tasks/{task_id}/turns/{turn_id}/sibling_turns client.codex.tasks.turns.sibling_turns(task_id, turn_id) Raw sibling turn list.
GET /backend-api/wham/environments client.codex.environments.list() Raw Codex cloud environment list.
POST /backend-api/files + signed upload client.files.upload(...) Uploads local files for Codex Apps/MCP file parameters and returns sediment://... metadata.
GET /backend-api/memories client.codex.memories.list() Raw ChatGPT memory payload for the authenticated account.
GET /backend-api/user_system_messages client.codex.user_system_messages.retrieve() Raw ChatGPT customization/system-message payload.

Responses

client.responses.create(...) follows the official OpenAI Responses API where the Codex backend overlaps with it.

Supported request fields:

  • model
  • input
  • instructions
  • include
  • parallel_tool_calls
  • prompt_cache_key
  • reasoning
  • service_tier
  • store=False
  • stream
  • text
  • tool_choice
  • tools

The backend itself requires streaming. When stream=True, the SDK yields ResponseStreamEvent objects directly. When stream is omitted or false, the SDK consumes the SSE stream and returns a collected Response.

response = client.responses.create(
    model="gpt-5.4",
    instructions="Be concise.",
    input=[
        {"role": "user", "content": "Summarize this API shape."},
    ],
    reasoning={"effort": "medium", "summary": "auto"},
    include=["reasoning.encrypted_content"],
    text={"verbosity": "medium"},
    prompt_cache_key="session-123",
)

Unsupported official Responses parameters are rejected explicitly with CodexBackendUnsupportedParameterError, including temperature, top_p, max_output_tokens, metadata, user, safety_identifier, truncation, previous_response_id, conversation, background, prompt, prompt_cache_retention, and stream_options.

Context Compaction

client.responses.compact(...) is specific to the Codex backend. It compresses a long Responses-style input list into an opaque encrypted compaction summary that can be replayed in later input arrays.

compacted = client.responses.compact(
    model="gpt-5.4",
    instructions="Keep task-critical context.",
    input=history,
)

history = compacted.output

The returned CompactedResponse.output contains regular response items plus one or more {"type": "compaction_summary", ...} items. Treat those summaries as opaque backend state.

Models

client.models.list() and client.models.retrieve(model) mirror the official OpenAI models resource, while preserving Codex-specific metadata as extra Pydantic fields.

models = client.models.list()
for model in models:
    print(
        model.id,
        model.context_window,
        model.supported_in_api,
        model.supports_reasoning_summaries,
    )

Common extra fields include:

  • display_name
  • description
  • context_window
  • supported_in_api
  • supports_reasoning_summaries
  • support_verbosity
  • default_verbosity
  • default_reasoning_level
  • supported_reasoning_levels
  • auto_compact_token_limit
  • prefer_websockets
  • input_modalities
  • available_in_plans
  • base_instructions
  • priority
  • raw

Realtime

The SDK keeps the realtime surface available for integrations that bridge Codex auth with voice sessions.

client.realtime.calls.create(...) mirrors the official OpenAI SDK call shape:

answer = client.realtime.calls.create(
    sdp=offer_sdp,
    session={"type": "realtime", "model": "gpt-realtime-1.5"},
)

print(answer.text)

For WebSocket-based plugins such as codex-agent, the client also exposes small helpers that reuse the OpenAI API key stored by the Codex OAuth flow:

url = client.realtime_websocket_url(model="gpt-realtime-1.5")
headers = client.realtime_websocket_headers(session_id="voice-session")

realtime_websocket_headers(...) requires ~/.codex/auth.json to contain openai_api_key. The default authenticate(request_api_key=True) flow stores that key when available.

Embeddings

client.embeddings.create(...) mirrors the official OpenAI embeddings resource and sends the Codex OAuth access token directly to api.openai.com/v1.

embedding = client.embeddings.create(
    model="text-embedding-3-small",
    input="Embed this sentence.",
    dimensions=256,
)

print(embedding.data[0].embedding)

Audio Transcriptions

client.audio.transcriptions.create(...) mirrors the official OpenAI transcriptions resource for non-streaming calls.

with open("meeting.wav", "rb") as audio:
    transcription = client.audio.transcriptions.create(
        model="gpt-4o-mini-transcribe",
        file=("meeting.wav", audio, "audio/wav"),
        response_format="json",
    )

print(transcription.text)

Quota And Usage

client.codex.usage() calls the ChatGPT WHAM usage endpoint. It returns the raw quota payload from the backend because the shape contains plan-specific fields.

quota = client.codex.usage()
primary = quota.get("rate_limit", {}).get("primary_window", {})
print(primary.get("used_percent"))

Typical fields include:

  • plan_type
  • rate_limit.allowed
  • rate_limit.limit_reached
  • rate_limit.primary_window
  • rate_limit.secondary_window
  • additional_rate_limits
  • credits
  • rate_limit_reached_type

Codex Cloud Tasks

The client.codex.tasks and client.codex.environments namespaces expose read-only WHAM cloud-task payloads as raw backend dictionaries.

tasks = client.codex.tasks.list(limit=10)
task = client.codex.tasks.retrieve(tasks["items"][0]["id"])
turns = client.codex.tasks.turns.list(task["task"]["id"])
environments = client.codex.environments.list()

Supported task-list filters are limit, cursor, task_filter, and environment_id.

ChatGPT Account Data

The client.codex namespace also exposes read-only ChatGPT account data that is not part of the official OpenAI SDK.

memories = client.codex.memories.list()
customization = client.codex.user_system_messages.retrieve()
requirements = client.codex.config.requirements()

These methods return raw backend dictionaries because these payloads can contain personal account-specific fields and may change without notice.

client.codex.memories.trace_summarize(...) exposes the Codex memory summarization endpoint used by the official client. It returns the raw backend dictionary:

summary = client.codex.memories.trace_summarize(
    model="gpt-5.4",
    traces=[
        {
            "id": "trace_1",
            "metadata": {"source_path": "memory.jsonl"},
            "items": [{"type": "message", "content": "Remember this"}],
        }
    ],
    reasoning={"effort": "low"},
)

File Uploads

client.files.upload(...) follows the official Codex file flow for Apps/MCP file parameters: create file metadata under ChatGPT, upload bytes to the signed URL, then finalize the upload.

uploaded = client.files.upload("report.csv")
print(uploaded.uri)  # sediment://file_...

Observed But Not Exposed

The reverse-engineering notes in docs/backend-api.md include additional observed endpoints. They are not exposed as SDK resources yet because they are plan-gated, unavailable on chatgpt.com, or not stable enough:

  • POST /v1/audio/speech (auth reaches the endpoint, but Pro OAuth lacks api.model.audio.request in current tests)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

codex_backend_sdk-0.3.1.tar.gz (34.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

codex_backend_sdk-0.3.1-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

Details for the file codex_backend_sdk-0.3.1.tar.gz.

File metadata

  • Download URL: codex_backend_sdk-0.3.1.tar.gz
  • Upload date:
  • Size: 34.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for codex_backend_sdk-0.3.1.tar.gz
Algorithm Hash digest
SHA256 bc24367f9ed73200382f3a9c1fb9458209b2eca3e48af9245276524bf649885a
MD5 1b7e7f3e80ff9a5c3d7dbe41d42538cc
BLAKE2b-256 c5d582001c1a282510f9e1e382d792e71c0f4f742060d40a7b0169a6d0168fde

See more details on using hashes here.

File details

Details for the file codex_backend_sdk-0.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for codex_backend_sdk-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cd577edb51bafa6e4199efab2d6d22d2a1813ad371ac3906d9f17714b8e079a3
MD5 38655d43880c5b50acde92d45d713216
BLAKE2b-256 0c1248be374736f0165aa79ccf00a35b4d660451c198c4f449798ddca4240647

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page