Codex Gateway API

December 17, 2025 · View on GitHub

HTTP service implemented by scripts/codex_gateway.js. Each request spawns a Codex process, returns when complete.

┌──────────────────────────────────────────────────────────────┐
│  POST /completion  →  spawns codex  →  returns result        │
│  GET  /sessions    →  list past runs                         │
│  GET  /status      →  concurrency, watcher, webhook info     │
└──────────────────────────────────────────────────────────────┘

Start the gateway:

pwsh ./scripts/gnosis-container.ps1 -Serve -GatewayPort 4000

Make a request:

curl -X POST http://localhost:4000/completion \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "List files in workspace"}]}'

Quick Reference

MethodEndpointDescription
GET/healthLiveness probe
GET/Gateway info, endpoints, config
GET/statusConcurrency, uptime, memory, watcher/webhook
POST/completionRun a prompt
GET/sessionsList sessions
GET/sessions/:idSession details
GET/sessions/:id/searchSearch session logs
POST/sessions/:id/promptContinue a session
POST/sessions/:id/nudgeReplay with updated metadata
GET/triggersList configured monitor triggers
POST/triggersCreate or replace trigger definitions
PATCH/DELETE/triggers/:idUpdate or remove a trigger

Configuration

VariableDefaultDescription
CODEX_GATEWAY_PORT4000Server port
CODEX_GATEWAY_BIND0.0.0.0Bind address
CODEX_GATEWAY_MAX_BODY_BYTES1048576Max request size (1 MiB)
CODEX_GATEWAY_MAX_CONCURRENT2Max parallel Codex runs
CODEX_GATEWAY_TIMEOUT_MS120000Default execution timeout
CODEX_GATEWAY_MAX_TIMEOUT_MS1800000Max allowed timeout (30 min)
CODEX_GATEWAY_DEFAULT_MODEL(empty)Default model

Authentication: None by default. Use CODEX_GATEWAY_SECURE_TOKEN for secure sessions or front with your own auth proxy.


Endpoints

GET /health

Liveness check.

{ "status": "ok" }

GET /

Gateway metadata: watcher config, webhook config, environment, available endpoints.

{
  "status": "codex-gateway",
  "watcher": { "enabled": false, "paths": [], "pattern": "**/*" },
  "webhook": { "configured": false },
  "env": { "CODEX_GATEWAY_SESSION_DIRS": ["/opt/codex-home/.codex/sessions"] },
  "endpoints": {
    "health": "/health",
    "status": "/status",
    "completion": { "path": "/completion", "method": "POST" },
    "sessions": {
      "list": { "path": "/sessions", "method": "GET" },
      "detail": { "path": "/sessions/:id", "method": "GET" },
      "search": { "path": "/sessions/:id/search", "method": "GET" },
      "prompt": { "path": "/sessions/:id/prompt", "method": "POST" },
      "nudge": { "path": "/sessions/:id/nudge", "method": "POST" }
    }
  }
}

GET /status

Extended status with concurrency, uptime, memory.

{
  "concurrency": { "active": 1, "max": 2, "available": 1 },
  "uptime": 3600,
  "memory": { "rss": 52428800, "heapTotal": 20971520, "heapUsed": 15728640 },
  "watcher": { "enabled": true, "paths": ["/workspace/temp"] },
  "webhook": { "configured": true, "url_tail": "...example.com/hook" }
}

POST /completion

Run a prompt through Codex.

Request:

{
  "messages": [
    { "role": "user", "content": "What files are in the workspace?" }
  ],
  "system_prompt": "You are a helpful assistant.",
  "model": "gpt-4o-mini",
  "workspace": "/workspace",
  "session_id": "optional-existing-session",
  "timeout_ms": 120000,
  "json_mode": false,
  "env": { "MY_VAR": "value" },
  "metadata": { "source": "api" }
}
FieldTypeRequiredDescription
messagesarrayYes*Chat-style messages with role and content
promptstringYes*Plain string prompt (ignored if messages provided)
system_promptstringNoSystem instructions
modelstringNoModel override
workspacestringNoWorking directory (default /workspace)
session_idstringNoResume existing session
timeout_msnumberNoExecution timeout
json_modebooleanNoAdd --experimental-json flag
envobjectNoPer-run environment variables
metadataobjectNoArbitrary data to persist with run

*Either messages or prompt required.

Response:

{
  "session_id": "session-abc123",
  "gateway_session_id": "session-abc123",
  "codex_session_id": "sess_xyz",
  "model": "gpt-4o-mini",
  "output": "The workspace contains...",
  "messages": [...],
  "usage": {
    "input_tokens": 1234,
    "output_tokens": 321,
    "cached_input_tokens": 0,
    "total_tokens": 1555
  },
  "logs_path": "/opt/codex-home/.codex/sessions/gateway/session-abc123",
  "metadata": { "source": "api" }
}

Error codes:

StatusMeaning
400Invalid payload or body too large
408Timeout exceeded
429At concurrency limit — retry later
500Codex execution failure

Concurrency: When max_concurrent is reached, returns 429:

{
  "error": "Too many concurrent requests",
  "retry_after": 5,
  "active": 2,
  "max": 2
}

GET /sessions

List known sessions.

Query params:

ParamDefaultDescription
limit50Max sessions (max 200)
sinceISO timestamp, filter sessions modified after

Response:

[
  {
    "session_id": "session-abc123",
    "dir": "/path/to/session",
    "modified": "2025-01-15T10:30:00Z",
    "metadata": { ... }
  }
]

GET /sessions/:id

Session details. Accepts gateway session ID or Codex session ID.

Query params:

ParamDefaultDescription
tail_lines200Lines of logs to return
include_stderrfalseInclude stderr output
include_eventsfalseInclude raw event stream

Response:

{
  "session_id": "session-abc123",
  "codex_session_id": "sess_xyz",
  "status": "completed",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:31:00Z",
  "model": "gpt-4o-mini",
  "runs": 1,
  "stdout": { "tail": "...", "tail_lines": 200 },
  "stderr": { "tail": "...", "tail_lines": 200 },
  "events": [...]
}

GET /sessions/:id/search

Search within session logs.

Query params:

ParamRequiredDescription
qYesSearch string
fuzzyNoEnable fuzzy matching
max_resultsNoLimit results (default 5)
tail_linesNoCap log snippet length

Response:

{
  "session_id": "session-abc123",
  "query": "error",
  "signals": [
    { "line": 42, "score": 0.95, "context": "...encountered an error..." }
  ]
}

POST /sessions/:id/prompt

Continue an existing session with a new prompt.

Request:

{
  "prompt": "Now summarize those files",
  "system_prompt": "optional override",
  "timeout_ms": 60000
}

Response: Same as /completion.


POST /sessions/:id/nudge

Replay a session with optional updated metadata or messages.

Request:

{
  "prompt": "Try again with more detail",
  "messages": [...],
  "metadata": { "retry": true }
}

Response: Same as /completion.


Trigger management (/triggers)

Use the new trigger API instead of editing .codex-monitor-triggers.json. The gateway still watches that file by default, but you can now call the API on port 4000 to list, add, update, or delete scheduled prompts. Each request accepts an optional trigger_file query parameter (defaults to the configured file) when you need to target a different trigger document.

MethodEndpointDescription
GET/triggersReturn the parsed trigger array
POST/triggersAdd a trigger payload (prompt_text + schedule required)
PATCH/triggers/:idUpdate trigger fields
DELETE/triggers/:idRemove a trigger

Payloads mirror the scheduler schema:

{
  "id": "optional-id",
  "title": "Friendly label",
  "description": "Why this runs",
  "prompt_text": "Run the latest monitor report",
  "schedule": {
    "mode": "daily",
    "time": "14:00",
    "timezone": "America/Chicago"
  },
  "enabled": true,
  "tags": ["reports"]
}

Each mutation persists to the trigger file and immediately refreshes the scheduler, so you can manage batches of triggers through HTTP without waiting on file-watch events.


File Watcher

When enabled, file changes automatically trigger /completion runs.

Enable with env vars before starting gateway:

$env:CODEX_GATEWAY_WATCH_PATHS = 'temp;inbox'
$env:CODEX_GATEWAY_WATCH_PROMPT_FILE = './MONITOR.md'
$env:CODEX_GATEWAY_WATCH_PATTERN = '**/*.txt'
pwsh ./scripts/gnosis-container.ps1 -Serve -GatewayPort 4000
VariableDefaultDescription
CODEX_GATEWAY_WATCH_PATHSPaths to watch (comma/semicolon separated)
CODEX_GATEWAY_WATCH_PATTERN**/*Glob pattern
CODEX_GATEWAY_WATCH_PROMPT_FILEPrompt template path
CODEX_GATEWAY_WATCH_DEBOUNCE_MS750Debounce delay
CODEX_GATEWAY_WATCH_POLL_MS1000Poll interval
CODEX_GATEWAY_WATCH_USE_WATCHDOGfalseUse watchdog implementation
CODEX_GATEWAY_WATCH_SKIP_INITIAL_SCANtrueSkip initial file scan

Prompt template variables:

VariableDescription
{{file}}Changed file path
{{filename}}File name only
{{container_path}}Path inside container
{{event_type}}Type of change

Watcher status exposed via / and /status.


Session Webhooks

Get notified when sessions complete.

VariableDescription
SESSION_WEBHOOK_URLWebhook endpoint
SESSION_WEBHOOK_TIMEOUT_MSRequest timeout (default 5000)
SESSION_WEBHOOK_AUTH_BEARERBearer token
SESSION_WEBHOOK_HEADERS_JSONAdditional headers as JSON

Payload:

{
  "session_id": "session-abc123",
  "workspace": "/workspace",
  "prompt": "...",
  "output": "...",
  "usage": { ... },
  "metadata": { ... }
}

Environment Variables

Gateway Core

VariableDefaultDescription
CODEX_GATEWAY_PORT4000Server port
CODEX_GATEWAY_BIND0.0.0.0Bind address
CODEX_GATEWAY_TIMEOUT_MS120000Default timeout
CODEX_GATEWAY_MAX_TIMEOUT_MS1800000Max timeout
CODEX_GATEWAY_DEFAULT_MODELDefault model
CODEX_GATEWAY_EXTRA_ARGSExtra Codex CLI args
CODEX_GATEWAY_JSON_FLAG--experimental-jsonJSON mode flag
CODEX_GATEWAY_MAX_BODY_BYTES1048576Max request size
CODEX_GATEWAY_MAX_CONCURRENT2Max parallel runs
CODEX_GATEWAY_LOG_LEVEL1Verbosity (0-3)

Sessions

VariableDefaultDescription
CODEX_GATEWAY_SESSION_DIRSSession directories (comma-separated)
CODEX_GATEWAY_SECURE_SESSION_DIR.codex-gateway-sessions/secureSecure session dir
CODEX_GATEWAY_SECURE_TOKENToken for secure access
CODEX_GATEWAY_DEFAULT_TAIL_LINES200Default log lines
CODEX_GATEWAY_MAX_TAIL_LINES2000Max log lines

Retries

VariableDefaultDescription
CODEX_GATEWAY_MAX_RETRIES0Max retry attempts
CODEX_GATEWAY_RETRY_DELAY_MS2000Base retry delay
CODEX_GATEWAY_RETRY_ON_EMPTYfalseRetry on empty response

Pass-through

VariableDescription
CODEX_SANDBOX_NETWORK_DISABLEDPassed to Codex CLI

Full options in scripts/codex_gateway.js.


CLI REPL

Interactive helper for calling the gateway:

python scripts/codex-repl.py http://localhost:4000

Commands:

CommandDescription
run <prompt>Call /completion
listList sessions
show <id> [events|triggers]Fetch session details
search <id> <phrase> [--f]Search session (--f for fuzzy)
prompt <id> <text>Continue a session
use <id>Pin session for subsequent runs
timeout <seconds>Set default timeout
mode <full|compact>Toggle output mode
watch <keys...>Show these keys in compact mode
watch clearReset watched keys
setenv <KEY> <VALUE>Add/clear env overrides for future runs (setenv clear resets)
helpShow help
clearClear screen
exit / quitExit

Example session:

codex> mode compact
codex> watch usage model
codex> setenv MY_VAR value
codex> run list markdown files
codex> use session-abc123
codex> prompt continue with summaries

Compact mode prints reasoning/agent messages and command outputs instead of full JSON.