james-6-23/codex2api

Codex2API 是一个基于 Go + Gin + React/Vite 的 Codex 反向代理与管理后台项目

2,075

stars

1,673

commits

Go

primary language

Sep 10, 2026

updated

codex2api-latest-vu8j.onrender.com
2api
codex

README

Codex2API

English | 中文

Go Gin React Vite Database Cache API Docker

Turn a Codex account pool into an observable, schedulable, operations-ready OpenAI / Anthropic compatible gateway. Codex2API is not a thin forwarding proxy. It is a long-running Codex access hub: it exposes /v1/chat/completions, /v1/responses, /v1/messages, Images, Videos (Grok Imagine), and Models endpoints while managing Refresh Token / Access Token accounts, health scoring, dynamic concurrency, rate-limit recovery, usage tracking, and admin operations behind the scenes.

Run it as a full PostgreSQL + Redis production stack or as a single-container SQLite + in-memory cache deployment. Point Codex CLI, Claude Code, the OpenAI SDK, or any compatible client at one Base URL, then manage accounts, proxies, API keys, prompt filtering, image workflows, and runtime settings from the built-in dashboard.

One compatible gatewayOpenAI-style Chat Completions / Responses / Images, Anthropic Messages, prefixless compatibility routes, and native Codex Responses forwarding are all exposed through one service.
Account-pool schedulerSelection is driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery, and recent usage so unhealthy accounts are avoided automatically. Supports round_robin and remaining_quota modes, with per-account credit billing flags.
Visual admin consoleThe embedded React / Vite dashboard covers account import and testing, API keys, proxy pools, image studio (text-to-image + image-to-image), prompt filtering, usage analytics, operations, scheduler board, and system settings.
Two deployment shapesUse PostgreSQL + Redis for production or SQLite + Memory for lightweight single-node deployments; Docker images, source builds, local development, and the interactive deploy script are ready to use. SQLite mode binds to 127.0.0.1 by default for security.
Billing and observabilityPer-account 5h/7d windowed USD cost tracking, credit quota support, API key usage tracking, OAuth PKCE token acquisition, prompt filtering, and a usage dashboard with request logs and trend charts.

Live Demo

The demo is only for trying the admin dashboard and basic UI flows. Do not upload real Refresh Tokens, Access Tokens, API keys, or any other sensitive data.


Screenshots

Screenshots use demo data. The actual dashboard depends on your account pool, request logs, and runtime environment.

CodexProxy Dashboard

More admin dashboard screenshots
AccountsDashboard Trends
AccountsDashboard Trends
Image StudioPrompt Filter
Image StudioPrompt Filter
OperationsUsage
OperationsUsage
Usage GuideAPI Reference
Usage GuideAPI Reference

Sponsors

Want to appear here? Open an issue on GitHub.

FastAITokenFastAIToken is a developer-first AI API gateway providing unified access to leading models including OpenAI, Claude, and Gemini. Fully OpenAI-API compatible and works seamlessly with Claude Code, Codex, Gemini CLI, Cherry Studio, Cline, and Continue. With a 1:1 top-up ratio (¥1 = $1 API credit) and routes ranging from 0.02× OpenAI (limited time) to 1.2× Claude Max, plus a public status page and 24/7 human support. Enterprise-ready with invoice support and 99% SLA dedicated account pools.
AiXorAiXor provides cost-effective AI model API access with support for mainstream models including OpenAI, Claude, and Gemini. Top-up ratio of ¥0.2 = $1 credit, bringing per-call costs down to under 10% of official pricing. Plans start at ¥25/28 days; the Premium plan (¥129/28 days) includes about $4,752 in model credit (plans cover OpenAI models only), with high-concurrency support and 95%+ SLA stability.
星辰·AI星辰·AI provides stable and high-speed relay services for Claude Code / Codex / Gemini, suitable for both individual developers and teams.

Contents


Quick Start

For detailed deployment instructions, see DEPLOYMENT.md.

Deployment Modes

ModeFileUse Case
Docker image deploymentdocker-compose.ymlRecommended for servers and test environments using the prebuilt image
Local source container builddocker-compose.local.ymlFull container verification after local source changes
SQLite lightweight deploymentdocker-compose.sqlite.ymlSingle-node deployment without PostgreSQL or Redis
SQLite local source builddocker-compose.sqlite.local.ymlLocal source verification for the lightweight SQLite mode
Local developmentgo run . + npm run devBackend and frontend development

Commands

Standard image mode:

git clone https://github.com/james-6-23/codex2api.git
cd codex2api
cp .env.example .env
docker compose pull
docker compose up -d
docker compose logs -f codex2api

Standard local build mode:

cp .env.example .env
docker compose -f docker-compose.local.yml up -d --build
docker compose -f docker-compose.local.yml logs -f codex2api

SQLite image mode:

cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.yml pull
docker compose -f docker-compose.sqlite.yml up -d
docker compose -f docker-compose.sqlite.yml logs -f codex2api

SQLite local build mode:

cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.local.yml up -d --build
docker compose -f docker-compose.sqlite.local.yml logs -f codex2api

After startup:

  • Admin dashboard: http://localhost:8080/admin/
  • Health check: http://localhost:8080/health

Notes:

  • Standard and SQLite modes both read .env.
  • Before switching deployment modes, replace .env with the matching example file.
  • The SQLite lightweight mode runs a single codex2api container and stores data at /data/codex2api.db.
  • SQLite compose files bind to 127.0.0.1 by default for security. To expose the SQLite service on all interfaces, set BIND_HOST=0.0.0.0 in .env or override the port binding in the compose file. The standard compose files bind to 0.0.0.0 by default.
  • The image studio library is stored under /data/images; uploaded admin backgrounds are stored under /data/backgrounds; Docker configurations persist /data.
  • docker compose down does not delete named volumes by default. Data is removed only by commands such as docker compose down -v, docker volume rm, or docker volume prune.

Antigravity channel (experimental API Key path)

Antigravity accounts are managed as a dedicated Google channel with browser/imported OAuth credentials and an optional Google API Key credential shape. Admin tooling includes secret-bearing JSON/ZIP credential export plus sanitized state, explicit control-plane sync, and bounded capability probing. OAuth requests use the Cloud Code v1internal adapter. API Key requests target the Generative Language v1beta/interactions endpoint, but ordinary API-key dispatch is fail-closed by default and requires ANTIGRAVITY_ENABLE_EXPERIMENTAL_INTERACTIONS=true. The opt-in real-upstream integration test has not succeeded in this environment, so this path remains experimental rather than production-certified. See docs/ANTIGRAVITY.md for endpoints, test instructions, models, channel restrictions, plaintext credential-storage risk, and the certification checklist.

Documentation

DocumentDescriptionPath
Chinese READMEMain Chinese project overviewREADME.zh-CN.md
API DocumentationAPI endpoints, request and response examples, error codesdocs/API.md
Antigravity IntegrationGoogle OAuth and experimental API Key channel, models, risks, and protocol statusdocs/ANTIGRAVITY.md
Deployment GuideDeployment modes, upgrade guide, backup and restoredocs/DEPLOYMENT.md
Configuration GuideEnvironment variables, system settings, configuration prioritydocs/CONFIGURATION.md
ArchitectureSystem architecture, scheduling algorithm, storage designdocs/ARCHITECTURE.md
TroubleshootingCommon issues, diagnostic scripts, fixesdocs/TROUBLESHOOTING.md
ContributingDevelopment rules, PR workflow, code standardsdocs/CONTRIBUTING.md

Upgrade and Local Development

Upgrade the standard image deployment:

git pull && docker compose pull && docker compose up -d && docker compose logs -f codex2api

Back up the database before upgrading:

docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sql

Restore from a backup if needed:

docker exec -i codex2api-postgres psql -U codex2api codex2api < backup_xxx.sql

Unless you explicitly need to recreate resources, avoid docker compose down during upgrades. pull + up -d keeps existing containers and named volumes.

Local Development

Backend:

cp .env.example .env
cd frontend && npm ci && npm run build && cd ..
go run .

The frontend must be built before the first backend run because Go embeds frontend/dist through go:embed.

Frontend dev server:

cd frontend && npm ci && npm run dev

Vite proxies /api and /health to the backend. During development, open http://localhost:5173/admin/.


Configuration

Environment Variables

For the full configuration reference, see CONFIGURATION.md.

VariableDescription
CODEX_PORTHTTP port, default 8080
CODEX_MAX_REQUEST_BODY_SIZE_MBHTTP request body limit in MB, default 48
ADMIN_SECRETAdmin dashboard secret. When set, /admin prompts for authentication
DATABASE_DRIVERDatabase driver: postgres or sqlite
DATABASE_PATHSQLite database file path, used when DATABASE_DRIVER=sqlite
DATABASE_HOSTPostgreSQL host
DATABASE_PORTPostgreSQL port, default 5432
DATABASE_USERPostgreSQL user
DATABASE_PASSWORDPostgreSQL password
DATABASE_NAMEPostgreSQL database name
DATABASE_SSLMODEPostgreSQL SSL mode, default disable
CACHE_DRIVERCache driver: redis or memory
REDIS_ADDRRedis address, for example redis:6379, redis://default:pass@host:6379/0, or rediss://default:pass@host:6379/0
REDIS_USERNAMEOptional Redis ACL username
REDIS_PASSWORDRedis password
REDIS_DBRedis database number
REDIS_TLSEnable TLS for host:port Redis addresses
REDIS_INSECURE_SKIP_VERIFYSkip Redis TLS certificate verification, default false
TZTimezone, for example Asia/Shanghai

Cloud Redis providers such as Aiven and Upstash often require TLS. Prefer a rediss://... URL when your provider gives one.

The standard .env.example declares DATABASE_DRIVER=postgres and CACHE_DRIVER=redis. For the lightweight SQLite mode, use .env.sqlite.example.

Runtime Settings

Runtime business settings are stored in the database SystemSettings table and can be updated from the admin settings page.

Examples include MaxConcurrency, GlobalRPM, TestModel, TestContent, TestConcurrency, ProxyURL, PgMaxConns, RedisPoolSize, AdminSecret, SchedulerMode, and auto-cleanup switches.

Default settings are written automatically on first startup.

Response Context Cache

Locally reconstructed HTTP Responses continuations that use previous_response_id are protected by a bounded, per-process L1 cache. Its defaults are 64 MiB of logical retained JSON payload, 8 MiB per admitted entry, 2,000 entries, a 10-minute absolute TTL, and at most 200 raw items per entry.

The Settings page exposes three persisted integer-MiB budgets:

BudgetDefaultAllowed Range
Local L1 total64 MiB8-4096 MiB
Local L1 entry admission8 MiB1-256 MiB and no greater than the total
Backend reconstruction64 MiB8-512 MiB

With Redis, a shared context that is within the reconstruction limit but above the L1 admission budget can still serve the request; it is not promoted into the local cache. Memory mode has no shared response-context fallback, so a dependent continuation whose context was oversized or evicted can return HTTP 409 response_context_unavailable. A dependent continuation can return HTTP 503 when its shared backend is temporarily unavailable and no eligible relay fallback can preserve previous_response_id.

Each successful budget change receives a read-only generation and is polled by every instance every five seconds. Operations shows effective/applied generations, synchronization state, logical cache bytes and counters, process memory, Go heap fields, and GC count. Logical cache bytes do not include Go/container overhead and are not an RSS or process-memory hard limit. During a rolling upgrade, a newer frontend tolerates an older backend that omits the new settings or Operations fields.

API Keys and Admin Secret

  • Public API keys come from the database API Keys table. If no key is configured, /v1/* skips API key authentication.
  • Admin Secret priority:
    • If ADMIN_SECRET is set in .env, the environment variable wins.
    • Otherwise, the database AdminSecret value is used.
    • After login, the frontend sends X-Admin-Key when calling /api/admin/*.

Public API

EndpointDescription
POST /v1/chat/completionsChat Completions style endpoint
POST /v1/responsesResponses style endpoint
POST /v1/images/generationsOpenAI Images generation endpoint (gpt-image-2 via Codex, grok-imagine via Grok)
POST /v1/images/editsOpenAI Images edit endpoint
POST /v1/videos/generationsGrok Imagine video generation (async, returns request_id)
POST /v1/videos/edits / POST /v1/videos/extensionsGrok Imagine video edit / extension
GET /v1/videos/:idPoll video task status (video.url rewritten to the gateway content proxy)
GET /v1/videos/:id/contentDownload the generated video through the gateway (Range supported)
GET /v1/modelsList available models (includes gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, gpt-image-2, grok-imagine-*, etc.)
GET /healthHealth check

Pricing: gpt-5.5 is billed at $5.00/M input and $30.00/M output (standard tier). Priority tier: $12.50/M input, $75.00/M output. Other models follow pricing rules in the billing engine.

See API.md for full request formats, response formats, and error codes.

Token Upload and Account Management

The following admin endpoints require the X-Admin-Key header.

Add Refresh Token Accounts

# Single account
curl -X POST http://localhost:8080/api/admin/accounts \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-account", "refresh_token": "rt_xxxxxxxxxxxx"}'

# Batch import, newline separated, up to 100 tokens per request
curl -X POST http://localhost:8080/api/admin/accounts \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "batch", "refresh_token": "rt_xxx1\nrt_xxx2\nrt_xxx3"}'

Add Access Token Accounts

# Single AT-only account
curl -X POST http://localhost:8080/api/admin/accounts/at \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-at", "access_token": "eyJhbGciOiJSUzI1NiIs..."}'

# Batch import, newline separated
curl -X POST http://localhost:8080/api/admin/accounts/at \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"access_token": "eyJtoken1...\neyJtoken2...\neyJtoken3..."}'

File Import

# Import Refresh Tokens from TXT, one token per line
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@tokens.txt" \
  -F "format=txt"

# Import Refresh Tokens from JSON
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@credentials.json" \
  -F "format=json"

# Import Access Tokens from TXT, one token per line
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@access_tokens.txt" \
  -F "format=at_txt"

Import endpoints deduplicate tokens automatically. Existing tokens are not inserted again.

OAuth PKCE Authorization

Codex2API supports acquiring Refresh Tokens through the OAuth PKCE flow, useful when manual token extraction is impractical:

# Step 1: Generate an authorization URL
curl -X POST http://localhost:8080/api/admin/oauth/generate-auth-url \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{}'

# Step 2: Open the returned auth_url in a browser, complete authorization
# Step 3: Exchange the authorization code for a token (auto-creates account)
curl -X POST http://localhost:8080/api/admin/oauth/exchange-code \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"session_id": "...", "code": "...", "state": "..."}'

See API.md for the full OAuth flow and all admin endpoints.


Admin Dashboard

Open /admin/ in a browser.

PagePathDescription
Dashboard/admin/Overview metrics, request trends, latency trends, token breakdown, model ranking
Accounts/admin/accountsImport, test, batch actions, scheduler state
API Keys/admin/api-keysAPI key creation, inspection, deletion, and credential management
Proxies/admin/proxiesProxy pool management, account proxy assignment, connectivity checks
Image Studio/admin/images/studioText-to-image, image-to-image, prompt templates, task history, server-side image library
Image Studio portal (non-admin)/image-studioStandalone studio for teammates using their own API key; toggle on the API Keys page
Prompt Filter/admin/prompt-filter/overviewRules, hit logs, testing, and handling mode configuration
Usage/admin/usageRequest logs, metric cards, charts, log cleanup
Operations/admin/opsRuntime overview, response-context logical cache metrics, process memory, Go heap, and GC
Scheduler Board/admin/ops/schedulerScheduler health, penalties, and score breakdown
Settings/admin/settingsRuntime parameters, response-context cache budgets, and admin secret settings
Usage Guide/admin/docsCodex CLI and Claude Code integration examples
API Reference/admin/api-referenceOpenAI-style endpoints and admin API reference

Core Capabilities

Positioning

Codex2API is not just a forwarding proxy. It is a long-running Codex gateway with a full admin dashboard:

  • Exposes a unified OpenAI-style API surface.
  • Maintains a Refresh Token account pool and Access Token lifecycle.
  • Coordinates persistence and runtime state through PostgreSQL + Redis or SQLite + in-memory cache.
  • Provides operational observability through the /admin dashboard.

Request Flow

Public request flow:

Client -> Gin RPM limiter -> proxy.Handler API key check -> auth.Store scheduler -> upstream request -> response + usage logging

Admin flow:

Browser -> embedded /admin frontend -> /api/admin/* -> database / account pool / cache layer

Scheduler

The scheduler lives in auth.Store. It evaluates availability, scheduler priority, health tier, dynamic concurrency, historical errors, and recent usage before selecting an account.

Runtime state:

  • Status: ready, cooldown, error
  • HealthTier: healthy, warm, risky, banned
  • SchedulerScore: real-time scheduling score based on a baseline of 100
  • DynamicConcurrencyLimit: concurrency limit adjusted by health tier
  • SchedulerPriority: strict account priority; higher-priority accounts are considered before health tier, score, or current load

Selection strategy:

  1. Filter unavailable accounts, including error, banned, cooldown accounts, and accounts without an Access Token.
  2. Recompute health tier, scheduler score, and dynamic concurrency.
  3. Exclude accounts that have reached their concurrency limit.
  4. Prefer higher SchedulerPriority, then healthy > warm > risky > banned; within the same priority and tier, prefer higher score and lower concurrency.
  5. In indexed mode, use a per-tier cursor or deterministic affinity offset inside the highest valid priority/health segment.

When multiple end users share one downstream API key, send X-Codex2API-Affinity-Key with a stable user or conversation identifier. Codex2API hashes it for local account affinity only and never forwards it upstream.

Concurrency rules:

TierConcurrency Limit
healthySystem MaxConcurrency
warmBase concurrency / 2, at least 1
riskyFixed at 1
bannedFixed at 0, not schedulable

The persistent upstream WebSocket pool is also capped by each account's current DynamicConcurrencyLimit, so connection reuse cannot grow beyond the account's effective concurrency.

Observability:

  • GET /api/admin/accounts shows health tier, scheduler score, and penalty details.
  • GET /api/admin/ops/overview shows scheduler engine, indexed/legacy selections, scan volume, event waiters, sparse routing-cache state, shadow parity, and outbox lag in addition to runtime and connection-pool state.
  • /admin/ops/scheduler provides the scheduler board.

Scheduler engine (scheduler_engine, via Admin Settings, or CODEX_SCHEDULER_ENGINE):

EngineBehavior
legacyCompatibility path that scans the immutable account snapshot
shadowLegacy remains authoritative while 1 in 64 requests compares indexed candidate availability
indexedPriority/health buckets, sparse API-key sub-pools, and event-driven availability waits are authoritative

For a production rollout, use legacy → shadow → indexed. CODEX_SCHEDULER_ENGINE overrides the database setting and can pin an instance for a canary or emergency rollback. The old FAST_SCHEDULER_ENABLED=true switch remains a compatibility alias for indexed when no engine is configured.

Scheduler mode (scheduler_mode, via Admin Settings):

ModeBehavior
round_robin (default)Round-robin across available accounts per health tier, weighted by dispatch score
remaining_quotaPrioritizes accounts with lower usage percent; round-robin for ties
fill_firstKeeps draining the account with the least remaining quota until it is exhausted or rate-limited, then falls to the next (A → B → C)

Credit accounts (per-account flags):

When an account has a credit-based billing model instead of a usage-based Free/Pro plan, you can mark it so the scheduler skips usage-window penalties:

FieldTypeEffect
credit_enabledboolMark account as credit-based billing
credit_skip_usage_windowboolWhen true, skip 7d/5h usage-window penalties for this account

Windowed USD cost: The accounts table displays per-account billed cost over two windows -- the past 5 hours and the past 7 days -- aligned with each account's usage reset boundaries. This shows actual spending per account rather than estimated token costs.


Project Structure

codex2api/
|- main.go                      # Application entrypoint
|- Dockerfile                   # Multi-stage image build
|- docker-compose.yml           # Image deployment template
|- docker-compose.local.yml     # Local source build template
|- .env.example                 # Environment variable example
|- admin/                       # Admin API
|- auth/                        # Account pool, scheduler, token management
|- cache/                       # Redis and cache wrappers
|- config/                      # Environment loading
|- database/                    # Database access layer
|- proxy/                       # Public proxy, forwarding, rate limiting
`- frontend/                    # React + Vite admin dashboard
   |- src/pages/                # Dashboard / Accounts / API Keys / Proxies / Images / Prompt Filter / Ops / Usage / Settings / Docs
   |- src/components/           # UI components
   |- src/locales/              # zh/en locales
   `- vite.config.js            # Vite config

Notes

  • docker-compose.yml pulls the GHCR image for deployment. docker-compose.local.yml uses build: . for local source builds.
  • The frontend base path is fixed at /admin/ for both local development and production.
  • Before manually building the Go binary, run npm run build in frontend/.
  • .env controls physical runtime settings such as port, database, and Redis. Business settings are stored in the database and managed from the admin dashboard.
  • API keys are stored in the database and configured through the admin dashboard.

Community

Join the group to discuss deployment, usage, and development questions.


Disclaimer and License

  • This project is for learning, research, and technical discussion only.
  • This project is released under the MIT License.
  • The project provides no warranty for direct or indirect consequences. Production use is at your own risk.

Star History

Star History Chart

Contributors

(top 30 of 38)

james-6-23

1,185 commits

ifThink404

212 commits

DeliciousBuding

118 commits

huangye123

40 commits

james-6-23/codex2api

Codex2API 是一个基于 Go + Gin + React/Vite 的 Codex 反向代理与管理后台项目

2,075

stars

1,673

commits

Go

primary language

Sep 10, 2026

updated

codex2api-latest-vu8j.onrender.com
2api
codex

README

Codex2API

English | 中文

Go Gin React Vite Database Cache API Docker

Turn a Codex account pool into an observable, schedulable, operations-ready OpenAI / Anthropic compatible gateway. Codex2API is not a thin forwarding proxy. It is a long-running Codex access hub: it exposes /v1/chat/completions, /v1/responses, /v1/messages, Images, Videos (Grok Imagine), and Models endpoints while managing Refresh Token / Access Token accounts, health scoring, dynamic concurrency, rate-limit recovery, usage tracking, and admin operations behind the scenes.

Run it as a full PostgreSQL + Redis production stack or as a single-container SQLite + in-memory cache deployment. Point Codex CLI, Claude Code, the OpenAI SDK, or any compatible client at one Base URL, then manage accounts, proxies, API keys, prompt filtering, image workflows, and runtime settings from the built-in dashboard.

One compatible gatewayOpenAI-style Chat Completions / Responses / Images, Anthropic Messages, prefixless compatibility routes, and native Codex Responses forwarding are all exposed through one service.
Account-pool schedulerSelection is driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery, and recent usage so unhealthy accounts are avoided automatically. Supports round_robin and remaining_quota modes, with per-account credit billing flags.
Visual admin consoleThe embedded React / Vite dashboard covers account import and testing, API keys, proxy pools, image studio (text-to-image + image-to-image), prompt filtering, usage analytics, operations, scheduler board, and system settings.
Two deployment shapesUse PostgreSQL + Redis for production or SQLite + Memory for lightweight single-node deployments; Docker images, source builds, local development, and the interactive deploy script are ready to use. SQLite mode binds to 127.0.0.1 by default for security.
Billing and observabilityPer-account 5h/7d windowed USD cost tracking, credit quota support, API key usage tracking, OAuth PKCE token acquisition, prompt filtering, and a usage dashboard with request logs and trend charts.

Live Demo

The demo is only for trying the admin dashboard and basic UI flows. Do not upload real Refresh Tokens, Access Tokens, API keys, or any other sensitive data.


Screenshots

Screenshots use demo data. The actual dashboard depends on your account pool, request logs, and runtime environment.

CodexProxy Dashboard

More admin dashboard screenshots
AccountsDashboard Trends
AccountsDashboard Trends
Image StudioPrompt Filter
Image StudioPrompt Filter
OperationsUsage
OperationsUsage
Usage GuideAPI Reference
Usage GuideAPI Reference

Sponsors

Want to appear here? Open an issue on GitHub.

FastAITokenFastAIToken is a developer-first AI API gateway providing unified access to leading models including OpenAI, Claude, and Gemini. Fully OpenAI-API compatible and works seamlessly with Claude Code, Codex, Gemini CLI, Cherry Studio, Cline, and Continue. With a 1:1 top-up ratio (¥1 = $1 API credit) and routes ranging from 0.02× OpenAI (limited time) to 1.2× Claude Max, plus a public status page and 24/7 human support. Enterprise-ready with invoice support and 99% SLA dedicated account pools.
AiXorAiXor provides cost-effective AI model API access with support for mainstream models including OpenAI, Claude, and Gemini. Top-up ratio of ¥0.2 = $1 credit, bringing per-call costs down to under 10% of official pricing. Plans start at ¥25/28 days; the Premium plan (¥129/28 days) includes about $4,752 in model credit (plans cover OpenAI models only), with high-concurrency support and 95%+ SLA stability.
星辰·AI星辰·AI provides stable and high-speed relay services for Claude Code / Codex / Gemini, suitable for both individual developers and teams.

Contents


Quick Start

For detailed deployment instructions, see DEPLOYMENT.md.

Deployment Modes

ModeFileUse Case
Docker image deploymentdocker-compose.ymlRecommended for servers and test environments using the prebuilt image
Local source container builddocker-compose.local.ymlFull container verification after local source changes
SQLite lightweight deploymentdocker-compose.sqlite.ymlSingle-node deployment without PostgreSQL or Redis
SQLite local source builddocker-compose.sqlite.local.ymlLocal source verification for the lightweight SQLite mode
Local developmentgo run . + npm run devBackend and frontend development

Commands

Standard image mode:

git clone https://github.com/james-6-23/codex2api.git
cd codex2api
cp .env.example .env
docker compose pull
docker compose up -d
docker compose logs -f codex2api

Standard local build mode:

cp .env.example .env
docker compose -f docker-compose.local.yml up -d --build
docker compose -f docker-compose.local.yml logs -f codex2api

SQLite image mode:

cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.yml pull
docker compose -f docker-compose.sqlite.yml up -d
docker compose -f docker-compose.sqlite.yml logs -f codex2api

SQLite local build mode:

cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.local.yml up -d --build
docker compose -f docker-compose.sqlite.local.yml logs -f codex2api

After startup:

  • Admin dashboard: http://localhost:8080/admin/
  • Health check: http://localhost:8080/health

Notes:

  • Standard and SQLite modes both read .env.
  • Before switching deployment modes, replace .env with the matching example file.
  • The SQLite lightweight mode runs a single codex2api container and stores data at /data/codex2api.db.
  • SQLite compose files bind to 127.0.0.1 by default for security. To expose the SQLite service on all interfaces, set BIND_HOST=0.0.0.0 in .env or override the port binding in the compose file. The standard compose files bind to 0.0.0.0 by default.
  • The image studio library is stored under /data/images; uploaded admin backgrounds are stored under /data/backgrounds; Docker configurations persist /data.
  • docker compose down does not delete named volumes by default. Data is removed only by commands such as docker compose down -v, docker volume rm, or docker volume prune.

Antigravity channel (experimental API Key path)

Antigravity accounts are managed as a dedicated Google channel with browser/imported OAuth credentials and an optional Google API Key credential shape. Admin tooling includes secret-bearing JSON/ZIP credential export plus sanitized state, explicit control-plane sync, and bounded capability probing. OAuth requests use the Cloud Code v1internal adapter. API Key requests target the Generative Language v1beta/interactions endpoint, but ordinary API-key dispatch is fail-closed by default and requires ANTIGRAVITY_ENABLE_EXPERIMENTAL_INTERACTIONS=true. The opt-in real-upstream integration test has not succeeded in this environment, so this path remains experimental rather than production-certified. See docs/ANTIGRAVITY.md for endpoints, test instructions, models, channel restrictions, plaintext credential-storage risk, and the certification checklist.

Documentation

DocumentDescriptionPath
Chinese READMEMain Chinese project overviewREADME.zh-CN.md
API DocumentationAPI endpoints, request and response examples, error codesdocs/API.md
Antigravity IntegrationGoogle OAuth and experimental API Key channel, models, risks, and protocol statusdocs/ANTIGRAVITY.md
Deployment GuideDeployment modes, upgrade guide, backup and restoredocs/DEPLOYMENT.md
Configuration GuideEnvironment variables, system settings, configuration prioritydocs/CONFIGURATION.md
ArchitectureSystem architecture, scheduling algorithm, storage designdocs/ARCHITECTURE.md
TroubleshootingCommon issues, diagnostic scripts, fixesdocs/TROUBLESHOOTING.md
ContributingDevelopment rules, PR workflow, code standardsdocs/CONTRIBUTING.md

Upgrade and Local Development

Upgrade the standard image deployment:

git pull && docker compose pull && docker compose up -d && docker compose logs -f codex2api

Back up the database before upgrading:

docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sql

Restore from a backup if needed:

docker exec -i codex2api-postgres psql -U codex2api codex2api < backup_xxx.sql

Unless you explicitly need to recreate resources, avoid docker compose down during upgrades. pull + up -d keeps existing containers and named volumes.

Local Development

Backend:

cp .env.example .env
cd frontend && npm ci && npm run build && cd ..
go run .

The frontend must be built before the first backend run because Go embeds frontend/dist through go:embed.

Frontend dev server:

cd frontend && npm ci && npm run dev

Vite proxies /api and /health to the backend. During development, open http://localhost:5173/admin/.


Configuration

Environment Variables

For the full configuration reference, see CONFIGURATION.md.

VariableDescription
CODEX_PORTHTTP port, default 8080
CODEX_MAX_REQUEST_BODY_SIZE_MBHTTP request body limit in MB, default 48
ADMIN_SECRETAdmin dashboard secret. When set, /admin prompts for authentication
DATABASE_DRIVERDatabase driver: postgres or sqlite
DATABASE_PATHSQLite database file path, used when DATABASE_DRIVER=sqlite
DATABASE_HOSTPostgreSQL host
DATABASE_PORTPostgreSQL port, default 5432
DATABASE_USERPostgreSQL user
DATABASE_PASSWORDPostgreSQL password
DATABASE_NAMEPostgreSQL database name
DATABASE_SSLMODEPostgreSQL SSL mode, default disable
CACHE_DRIVERCache driver: redis or memory
REDIS_ADDRRedis address, for example redis:6379, redis://default:pass@host:6379/0, or rediss://default:pass@host:6379/0
REDIS_USERNAMEOptional Redis ACL username
REDIS_PASSWORDRedis password
REDIS_DBRedis database number
REDIS_TLSEnable TLS for host:port Redis addresses
REDIS_INSECURE_SKIP_VERIFYSkip Redis TLS certificate verification, default false
TZTimezone, for example Asia/Shanghai

Cloud Redis providers such as Aiven and Upstash often require TLS. Prefer a rediss://... URL when your provider gives one.

The standard .env.example declares DATABASE_DRIVER=postgres and CACHE_DRIVER=redis. For the lightweight SQLite mode, use .env.sqlite.example.

Runtime Settings

Runtime business settings are stored in the database SystemSettings table and can be updated from the admin settings page.

Examples include MaxConcurrency, GlobalRPM, TestModel, TestContent, TestConcurrency, ProxyURL, PgMaxConns, RedisPoolSize, AdminSecret, SchedulerMode, and auto-cleanup switches.

Default settings are written automatically on first startup.

Response Context Cache

Locally reconstructed HTTP Responses continuations that use previous_response_id are protected by a bounded, per-process L1 cache. Its defaults are 64 MiB of logical retained JSON payload, 8 MiB per admitted entry, 2,000 entries, a 10-minute absolute TTL, and at most 200 raw items per entry.

The Settings page exposes three persisted integer-MiB budgets:

BudgetDefaultAllowed Range
Local L1 total64 MiB8-4096 MiB
Local L1 entry admission8 MiB1-256 MiB and no greater than the total
Backend reconstruction64 MiB8-512 MiB

With Redis, a shared context that is within the reconstruction limit but above the L1 admission budget can still serve the request; it is not promoted into the local cache. Memory mode has no shared response-context fallback, so a dependent continuation whose context was oversized or evicted can return HTTP 409 response_context_unavailable. A dependent continuation can return HTTP 503 when its shared backend is temporarily unavailable and no eligible relay fallback can preserve previous_response_id.

Each successful budget change receives a read-only generation and is polled by every instance every five seconds. Operations shows effective/applied generations, synchronization state, logical cache bytes and counters, process memory, Go heap fields, and GC count. Logical cache bytes do not include Go/container overhead and are not an RSS or process-memory hard limit. During a rolling upgrade, a newer frontend tolerates an older backend that omits the new settings or Operations fields.

API Keys and Admin Secret

  • Public API keys come from the database API Keys table. If no key is configured, /v1/* skips API key authentication.
  • Admin Secret priority:
    • If ADMIN_SECRET is set in .env, the environment variable wins.
    • Otherwise, the database AdminSecret value is used.
    • After login, the frontend sends X-Admin-Key when calling /api/admin/*.

Public API

EndpointDescription
POST /v1/chat/completionsChat Completions style endpoint
POST /v1/responsesResponses style endpoint
POST /v1/images/generationsOpenAI Images generation endpoint (gpt-image-2 via Codex, grok-imagine via Grok)
POST /v1/images/editsOpenAI Images edit endpoint
POST /v1/videos/generationsGrok Imagine video generation (async, returns request_id)
POST /v1/videos/edits / POST /v1/videos/extensionsGrok Imagine video edit / extension
GET /v1/videos/:idPoll video task status (video.url rewritten to the gateway content proxy)
GET /v1/videos/:id/contentDownload the generated video through the gateway (Range supported)
GET /v1/modelsList available models (includes gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, gpt-image-2, grok-imagine-*, etc.)
GET /healthHealth check

Pricing: gpt-5.5 is billed at $5.00/M input and $30.00/M output (standard tier). Priority tier: $12.50/M input, $75.00/M output. Other models follow pricing rules in the billing engine.

See API.md for full request formats, response formats, and error codes.

Token Upload and Account Management

The following admin endpoints require the X-Admin-Key header.

Add Refresh Token Accounts

# Single account
curl -X POST http://localhost:8080/api/admin/accounts \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-account", "refresh_token": "rt_xxxxxxxxxxxx"}'

# Batch import, newline separated, up to 100 tokens per request
curl -X POST http://localhost:8080/api/admin/accounts \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "batch", "refresh_token": "rt_xxx1\nrt_xxx2\nrt_xxx3"}'

Add Access Token Accounts

# Single AT-only account
curl -X POST http://localhost:8080/api/admin/accounts/at \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-at", "access_token": "eyJhbGciOiJSUzI1NiIs..."}'

# Batch import, newline separated
curl -X POST http://localhost:8080/api/admin/accounts/at \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"access_token": "eyJtoken1...\neyJtoken2...\neyJtoken3..."}'

File Import

# Import Refresh Tokens from TXT, one token per line
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@tokens.txt" \
  -F "format=txt"

# Import Refresh Tokens from JSON
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@credentials.json" \
  -F "format=json"

# Import Access Tokens from TXT, one token per line
curl -X POST http://localhost:8080/api/admin/accounts/import \
  -H "X-Admin-Key: your-admin-secret" \
  -F "file=@access_tokens.txt" \
  -F "format=at_txt"

Import endpoints deduplicate tokens automatically. Existing tokens are not inserted again.

OAuth PKCE Authorization

Codex2API supports acquiring Refresh Tokens through the OAuth PKCE flow, useful when manual token extraction is impractical:

# Step 1: Generate an authorization URL
curl -X POST http://localhost:8080/api/admin/oauth/generate-auth-url \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{}'

# Step 2: Open the returned auth_url in a browser, complete authorization
# Step 3: Exchange the authorization code for a token (auto-creates account)
curl -X POST http://localhost:8080/api/admin/oauth/exchange-code \
  -H "X-Admin-Key: your-admin-secret" \
  -H "Content-Type: application/json" \
  -d '{"session_id": "...", "code": "...", "state": "..."}'

See API.md for the full OAuth flow and all admin endpoints.


Admin Dashboard

Open /admin/ in a browser.

PagePathDescription
Dashboard/admin/Overview metrics, request trends, latency trends, token breakdown, model ranking
Accounts/admin/accountsImport, test, batch actions, scheduler state
API Keys/admin/api-keysAPI key creation, inspection, deletion, and credential management
Proxies/admin/proxiesProxy pool management, account proxy assignment, connectivity checks
Image Studio/admin/images/studioText-to-image, image-to-image, prompt templates, task history, server-side image library
Image Studio portal (non-admin)/image-studioStandalone studio for teammates using their own API key; toggle on the API Keys page
Prompt Filter/admin/prompt-filter/overviewRules, hit logs, testing, and handling mode configuration
Usage/admin/usageRequest logs, metric cards, charts, log cleanup
Operations/admin/opsRuntime overview, response-context logical cache metrics, process memory, Go heap, and GC
Scheduler Board/admin/ops/schedulerScheduler health, penalties, and score breakdown
Settings/admin/settingsRuntime parameters, response-context cache budgets, and admin secret settings
Usage Guide/admin/docsCodex CLI and Claude Code integration examples
API Reference/admin/api-referenceOpenAI-style endpoints and admin API reference

Core Capabilities

Positioning

Codex2API is not just a forwarding proxy. It is a long-running Codex gateway with a full admin dashboard:

  • Exposes a unified OpenAI-style API surface.
  • Maintains a Refresh Token account pool and Access Token lifecycle.
  • Coordinates persistence and runtime state through PostgreSQL + Redis or SQLite + in-memory cache.
  • Provides operational observability through the /admin dashboard.

Request Flow

Public request flow:

Client -> Gin RPM limiter -> proxy.Handler API key check -> auth.Store scheduler -> upstream request -> response + usage logging

Admin flow:

Browser -> embedded /admin frontend -> /api/admin/* -> database / account pool / cache layer

Scheduler

The scheduler lives in auth.Store. It evaluates availability, scheduler priority, health tier, dynamic concurrency, historical errors, and recent usage before selecting an account.

Runtime state:

  • Status: ready, cooldown, error
  • HealthTier: healthy, warm, risky, banned
  • SchedulerScore: real-time scheduling score based on a baseline of 100
  • DynamicConcurrencyLimit: concurrency limit adjusted by health tier
  • SchedulerPriority: strict account priority; higher-priority accounts are considered before health tier, score, or current load

Selection strategy:

  1. Filter unavailable accounts, including error, banned, cooldown accounts, and accounts without an Access Token.
  2. Recompute health tier, scheduler score, and dynamic concurrency.
  3. Exclude accounts that have reached their concurrency limit.
  4. Prefer higher SchedulerPriority, then healthy > warm > risky > banned; within the same priority and tier, prefer higher score and lower concurrency.
  5. In indexed mode, use a per-tier cursor or deterministic affinity offset inside the highest valid priority/health segment.

When multiple end users share one downstream API key, send X-Codex2API-Affinity-Key with a stable user or conversation identifier. Codex2API hashes it for local account affinity only and never forwards it upstream.

Concurrency rules:

TierConcurrency Limit
healthySystem MaxConcurrency
warmBase concurrency / 2, at least 1
riskyFixed at 1
bannedFixed at 0, not schedulable

The persistent upstream WebSocket pool is also capped by each account's current DynamicConcurrencyLimit, so connection reuse cannot grow beyond the account's effective concurrency.

Observability:

  • GET /api/admin/accounts shows health tier, scheduler score, and penalty details.
  • GET /api/admin/ops/overview shows scheduler engine, indexed/legacy selections, scan volume, event waiters, sparse routing-cache state, shadow parity, and outbox lag in addition to runtime and connection-pool state.
  • /admin/ops/scheduler provides the scheduler board.

Scheduler engine (scheduler_engine, via Admin Settings, or CODEX_SCHEDULER_ENGINE):

EngineBehavior
legacyCompatibility path that scans the immutable account snapshot
shadowLegacy remains authoritative while 1 in 64 requests compares indexed candidate availability
indexedPriority/health buckets, sparse API-key sub-pools, and event-driven availability waits are authoritative

For a production rollout, use legacy → shadow → indexed. CODEX_SCHEDULER_ENGINE overrides the database setting and can pin an instance for a canary or emergency rollback. The old FAST_SCHEDULER_ENABLED=true switch remains a compatibility alias for indexed when no engine is configured.

Scheduler mode (scheduler_mode, via Admin Settings):

ModeBehavior
round_robin (default)Round-robin across available accounts per health tier, weighted by dispatch score
remaining_quotaPrioritizes accounts with lower usage percent; round-robin for ties
fill_firstKeeps draining the account with the least remaining quota until it is exhausted or rate-limited, then falls to the next (A → B → C)

Credit accounts (per-account flags):

When an account has a credit-based billing model instead of a usage-based Free/Pro plan, you can mark it so the scheduler skips usage-window penalties:

FieldTypeEffect
credit_enabledboolMark account as credit-based billing
credit_skip_usage_windowboolWhen true, skip 7d/5h usage-window penalties for this account

Windowed USD cost: The accounts table displays per-account billed cost over two windows -- the past 5 hours and the past 7 days -- aligned with each account's usage reset boundaries. This shows actual spending per account rather than estimated token costs.


Project Structure

codex2api/
|- main.go                      # Application entrypoint
|- Dockerfile                   # Multi-stage image build
|- docker-compose.yml           # Image deployment template
|- docker-compose.local.yml     # Local source build template
|- .env.example                 # Environment variable example
|- admin/                       # Admin API
|- auth/                        # Account pool, scheduler, token management
|- cache/                       # Redis and cache wrappers
|- config/                      # Environment loading
|- database/                    # Database access layer
|- proxy/                       # Public proxy, forwarding, rate limiting
`- frontend/                    # React + Vite admin dashboard
   |- src/pages/                # Dashboard / Accounts / API Keys / Proxies / Images / Prompt Filter / Ops / Usage / Settings / Docs
   |- src/components/           # UI components
   |- src/locales/              # zh/en locales
   `- vite.config.js            # Vite config

Notes

  • docker-compose.yml pulls the GHCR image for deployment. docker-compose.local.yml uses build: . for local source builds.
  • The frontend base path is fixed at /admin/ for both local development and production.
  • Before manually building the Go binary, run npm run build in frontend/.
  • .env controls physical runtime settings such as port, database, and Redis. Business settings are stored in the database and managed from the admin dashboard.
  • API keys are stored in the database and configured through the admin dashboard.

Community

Join the group to discuss deployment, usage, and development questions.


Disclaimer and License

  • This project is for learning, research, and technical discussion only.
  • This project is released under the MIT License.
  • The project provides no warranty for direct or indirect consequences. Production use is at your own risk.

Star History

Star History Chart

Contributors

(top 30 of 38)

james-6-23

1,185 commits

ifThink404

212 commits

DeliciousBuding

118 commits

huangye123

40 commits

Languages

Go

76.0%

TypeScript

22.6%

JavaScript

1.0%