English | 中文
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, 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 gateway | OpenAI-style Chat Completions / Responses / Images, Anthropic Messages, prefixless compatibility routes, and native Codex Responses forwarding are all exposed through one service. |
| Account-pool scheduler | Selection is driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery, and recent usage so unhealthy accounts are avoided automatically. |
| Visual admin console | The embedded React / Vite dashboard covers account import and testing, API keys, proxy pools, image studio, prompt filtering, usage analytics, operations, scheduler board, and system settings. |
| Two deployment shapes | Use 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. |
- Demo URL: https://codex2api-latest-vu8j.onrender.com
- Demo password:
codex2api
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 use demo data. The actual dashboard depends on your account pool, request logs, and runtime environment.
More admin dashboard screenshots
| Accounts | Dashboard Trends |
|---|---|
![]() |
![]() |
| Image Studio | Prompt Filter |
|---|---|
![]() |
![]() |
| Operations | Usage |
|---|---|
![]() |
![]() |
| Usage Guide | API Reference |
|---|---|
![]() |
![]() |
- Live Demo
- Screenshots
- Sponsors
- Quick Start
- Documentation
- Upgrade and Local Development
- Configuration
- Public API
- Admin Dashboard
- Core Capabilities
- Project Structure
- Notes
- Disclaimer and License
- Star History
- Links
Want to appear here? Open an issue on GitHub.
| 星辰·AI | Thanks to 星辰·AI for sponsoring this project! 星辰·AI provides stable and high-speed relay services for Claude Code / Codex / Gemini, suitable for both individual developers and teams. |
For detailed deployment instructions, see DEPLOYMENT.md.
| Mode | File | Use Case |
|---|---|---|
| Docker image deployment | docker-compose.yml |
Recommended for servers and test environments using the prebuilt image |
| Local source container build | docker-compose.local.yml |
Full container verification after local source changes |
| SQLite lightweight deployment | docker-compose.sqlite.yml |
Single-node deployment without PostgreSQL or Redis |
| SQLite local source build | docker-compose.sqlite.local.yml |
Local source verification for the lightweight SQLite mode |
| Local development | go run . + npm run dev |
Backend and frontend development |
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 codex2apiStandard 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 codex2apiSQLite 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 codex2apiSQLite 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 codex2apiAfter 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
.envwith the matching example file. - The SQLite lightweight mode runs a single
codex2apicontainer and stores data at/data/codex2api.db. - The image studio library is stored under
/data/images; Docker configurations persist/data. docker compose downdoes not delete named volumes by default. Data is removed only by commands such asdocker compose down -v,docker volume rm, ordocker volume prune.
| Document | Description | Path |
|---|---|---|
| Chinese README | Main Chinese project overview | README.zh-CN.md |
| API Documentation | API endpoints, request and response examples, error codes | docs/API.md |
| Deployment Guide | Deployment modes, upgrade guide, backup and restore | docs/DEPLOYMENT.md |
| Configuration Guide | Environment variables, system settings, configuration priority | docs/CONFIGURATION.md |
| Architecture | System architecture, scheduling algorithm, storage design | docs/ARCHITECTURE.md |
| Troubleshooting | Common issues, diagnostic scripts, fixes | docs/TROUBLESHOOTING.md |
| Contributing | Development rules, PR workflow, code standards | docs/CONTRIBUTING.md |
Upgrade the standard image deployment:
git pull && docker compose pull && docker compose up -d && docker compose logs -f codex2apiBack up the database before upgrading:
docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sqlRestore from a backup if needed:
docker exec -i codex2api-postgres psql -U codex2api codex2api < backup_xxx.sqlUnless you explicitly need to recreate resources, avoid docker compose down during upgrades. pull + up -d keeps existing containers and named volumes.
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 devVite proxies /api and /health to the backend. During development, open http://localhost:5173/admin/.
For the full configuration reference, see CONFIGURATION.md.
| Variable | Description |
|---|---|
CODEX_PORT |
HTTP port, default 8080 |
ADMIN_SECRET |
Admin dashboard secret. When set, /admin prompts for authentication |
DATABASE_DRIVER |
Database driver: postgres or sqlite |
DATABASE_PATH |
SQLite database file path, used when DATABASE_DRIVER=sqlite |
DATABASE_HOST |
PostgreSQL host |
DATABASE_PORT |
PostgreSQL port, default 5432 |
DATABASE_USER |
PostgreSQL user |
DATABASE_PASSWORD |
PostgreSQL password |
DATABASE_NAME |
PostgreSQL database name |
DATABASE_SSLMODE |
PostgreSQL SSL mode, default disable |
CACHE_DRIVER |
Cache driver: redis or memory |
REDIS_ADDR |
Redis address, for example redis:6379, redis://default:pass@host:6379/0, or rediss://default:pass@host:6379/0 |
REDIS_USERNAME |
Optional Redis ACL username |
REDIS_PASSWORD |
Redis password |
REDIS_DB |
Redis database number |
REDIS_TLS |
Enable TLS for host:port Redis addresses |
REDIS_INSECURE_SKIP_VERIFY |
Skip Redis TLS certificate verification, default false |
TZ |
Timezone, 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 business settings are stored in the database SystemSettings table and can be updated from the admin settings page.
Examples include MaxConcurrency, GlobalRPM, TestModel, TestConcurrency, ProxyURL, PgMaxConns, RedisPoolSize, AdminSecret, and auto-cleanup switches.
Default settings are written automatically on first startup.
- 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_SECRETis set in.env, the environment variable wins. - Otherwise, the database
AdminSecretvalue is used. - After login, the frontend sends
X-Admin-Keywhen calling/api/admin/*.
- If
| Endpoint | Description |
|---|---|
POST /v1/chat/completions |
Chat Completions style endpoint |
POST /v1/responses |
Responses style endpoint |
POST /v1/images/generations |
OpenAI Images generation endpoint |
POST /v1/images/edits |
OpenAI Images edit endpoint |
GET /v1/models |
List available models |
GET /health |
Health check |
See API.md for full request formats, response formats, and error codes.
The following admin endpoints require the X-Admin-Key header.
# 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"}'# 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..."}'# 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.
Open /admin/ in a browser.
| Page | Path | Description |
|---|---|---|
| Dashboard | /admin/ |
Overview metrics, request trends, latency trends, token breakdown, model ranking |
| Accounts | /admin/accounts |
Import, test, batch actions, scheduler state |
| API Keys | /admin/api-keys |
API key creation, inspection, deletion, and credential management |
| Proxies | /admin/proxies |
Proxy pool management, account proxy assignment, connectivity checks |
| Image Studio | /admin/images/studio |
Text-to-image, prompt templates, task history, server-side image library |
| Prompt Filter | /admin/prompt-filter/overview |
Rules, hit logs, testing, and handling mode configuration |
| Usage | /admin/usage |
Request logs, metric cards, charts, log cleanup |
| Operations | /admin/ops |
Runtime monitoring and system overview |
| Scheduler Board | /admin/ops/scheduler |
Scheduler health, penalties, and score breakdown |
| Settings | /admin/settings |
Runtime parameters and admin secret settings |
| Usage Guide | /admin/docs |
Codex CLI and Claude Code integration examples |
| API Reference | /admin/api-reference |
OpenAI-style endpoints and admin API reference |
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
/admindashboard.
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
The scheduler lives in auth.Store. It evaluates availability, health tier, dynamic concurrency, historical errors, and recent usage before selecting an account.
Runtime state:
Status:ready,cooldown,errorHealthTier:healthy,warm,risky,bannedSchedulerScore: real-time scheduling score based on a baseline of 100DynamicConcurrencyLimit: concurrency limit adjusted by health tier
Selection strategy:
- Filter unavailable accounts, including
error,banned, cooldown accounts, and accounts without an Access Token. - Recompute health tier, scheduler score, and dynamic concurrency.
- Exclude accounts that have reached their concurrency limit.
- Prefer
healthy > warm > risky > banned; within the same tier, prefer higher score and lower concurrency. - Apply a 15% random shuffle to reduce hotspots and starvation.
Concurrency rules:
| Tier | Concurrency Limit |
|---|---|
healthy |
System MaxConcurrency |
warm |
Base concurrency / 2, at least 1 |
risky |
Fixed at 1 |
banned |
Fixed at 0, not schedulable |
Observability:
GET /api/admin/accountsshows health tier, scheduler score, and penalty details.GET /api/admin/ops/overviewshows runtime and connection pool state./admin/ops/schedulerprovides the scheduler board.
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
docker-compose.ymlpulls the GHCR image for deployment.docker-compose.local.ymlusesbuild: .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 buildinfrontend/. .envcontrols 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.
- 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.








