codex2api: putting a scheduler and a dashboard in front of a Codex account pool
Codex2API 是一个基于 Go + Gin + React/Vite 的 Codex 反向代理与管理后台项目
At a glance
- What is it?
- A Go and Gin service that turns a pool of Codex accounts into one OpenAI or Anthropic compatible base URL, with account health scoring, dynamic concurrency and a React admin console.
- Who is it for?
- codex2api is a well instrumented operations layer rather than a thin forwarding proxy, and its Go dependency list, three stage Dockerfile and dual database modes all point the same way. It is genuinely good at the part that is hard to write by hand: choosing a healthy account, recovering from rate limits, and recording what each request actually cost.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the gateway actually fronts
The pitch is a single Base URL that speaks several dialects at once. The README lists `/v1/chat/completions`, `/v1/responses`, `/v1/messages`, image endpoints, a Grok Imagine video path, and a models endpoint, alongside what it calls prefixless compatibility routes and native Codex Responses forwarding. Codex CLI, Claude Code, the OpenAI SDK and anything else that speaks those shapes are all listed as clients you can point at it.
What sits behind those routes is the part worth reading twice. The project describes itself as a long running Codex access hub rather than a passthrough, and the feature table backs that up: selection driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery and recent usage, with `round_robin` and `remaining_quota` modes and per-account credit billing flags. Token and Access Token accounts are managed as a pool, and OAuth PKCE acquisition is listed among the capabilities.
The repository layout matches the description rather than the marketing. `proxy/` holds the request path, `auth/` the credential handling, `cache/` the Redis or in-memory layer, `database/` the persistence, `admin/` the dashboard API, `internal/` the shared packages, and `security/` a separate top-level directory, which tells you the author treats hardening as its own concern. `health_probe.go` sits at the repository root with a matching test, `pricing.json` holds the billing table, and `deploy.sh` plus a `deploy/` directory cover install paths.
Two deployment shapes with different security defaults
The README offers five ways to run it and one command does most of the work. The standard path pulls a prebuilt image:
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 codex2apiA lighter single node shape swaps in a different compose file and a different env template, with no PostgreSQL and no Redis:
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 codex2apiThe compose file it ships is small enough to read in full, and the service definition is where the defaults live:
name: codex2api
services:
codex2api:
image: ghcr.io/james-6-23/codex2api:latestStorage and cache are deliberately pluggable. PostgreSQL and Redis appear as separate services with their own health checks and `restart: unless-stopped`, while the lightweight path uses SQLite and process memory. The compose file comment on the database port notes it can be uncommented for local debugging, which is a small sign the author expects people to poke at it.
The security defaults are the part to check first, and they lean strict. `.env.example` ships `CODEX_PORT=8080` with `BIND_HOST` and `CODEX_BIND` commented out, and states that the SQLite mode binds to `127.0.0.1` by default. Anonymous access to `/v1/*` is off, with `CODEX_ALLOW_ANONYMOUS=false` marked as strongly discouraged to change. Admin bootstrap is gated two ways: either set `ADMIN_SECRET` as an environment variable, or complete a first run initialization page in the browser, and until one of those happens every `/api/admin/*` route returns 503 apart from the bootstrap endpoint. A `BOOTSTRAP_ALLOWED_CIDR` allowlist restricts who can complete that page, defaulting to loopback and private ranges.
The dependency list is the clearest description of the design
There is no code block to copy for the internals, so `go.mod` does the explaining. The module declares Go 1.26.6 and pulls in a set that maps almost one to one onto the README's feature list:
module github.com/codex2api
go 1.26.6`github.com/gin-gonic/gin` is the HTTP layer. `github.com/jackc/pgx/v5` and `modernc.org/sqlite` are the two database drivers, which is why both deployment modes can exist without a C toolchain, since the SQLite driver is the pure Go one. `github.com/redis/go-redis/v9` matches the cache option, and `github.com/tidwall/gjson` and `sjson` are JSON path get and set libraries, which is the natural pair for rewriting provider payloads on the fly.
Two entries are less obvious and more revealing. `github.com/refraction-networking/utls` exists to control the TLS fingerprint of the outbound Codex connection, and `github.com/gorilla/websocket` is there because the upstream transport can be forced to WebSocket. The env file confirms this: `CODEX_UPSTREAM_TRANSPORT` defaults to `http` but accepts `ws`, and a separate `USE_WEBSOCKET` variable is kept for compatibility with older behaviour. A gateway that fingerprints its upstream TLS and can speak WebSocket to it is doing more than forwarding text.
The remaining entries are unglamorous and telling. `aws-sdk-go-v2` with `service/s3` suggests object storage for generated media, `andybalholm/brotli` and `klauspost/compress` suggest compressed response handling, `joho/godotenv` is for loading `.env` files, and `golang.org/x/image` sits alongside the image endpoints. Nothing here suggests a framework doing work on your behalf. It is a service assembling its own pieces.
Billing accuracy is what the recent releases were about
The repository was last pushed on 2026-09-28 and released v3.0.4 the same day, after v3.0.3 and v3.0.2 two days earlier, so the release cadence right now is tight and the version numbers say this is well past an early prototype.
The release notes are unusually specific about what went wrong and why, which is worth more than a changelog that only lists features. v3.0.4 is about billing and usage accuracy. It completed the Excel Basispoints adapter for images, tools and streaming, after the adapter had been rejecting ordinary requests with an unhelpful message, and switched Grok Imagine to per image and per video second billing, and started recording token usage for native Gemini requests.
v3.0.3 fixed a data integrity problem in its own usage logs. v3.0.2 had overwritten the request model with the base model and written the alias suffix into the effective model field, so Daybreak traffic was logged backwards. The fix separates the downstream request name, the actual model, and the access program, and ships a one time migration. The migration deliberately refuses to guess: it moves the known suffix into a new column and leaves the already overwritten model field alone, because the original value cannot be recovered. That is a small detail and it is the clearest signal in the repository that the maintainer reasons about data loss seriously.
The v3.0.2 notes also describe capability detection per account, stored in a new `daybreak_snapshots` table, refreshed on import and on probe, with the last successful value kept when a check fails and cleared when identity or workspace changes. Per key allow and deny lists apply to the aliases, checked on HTTP, streaming and WebSocket paths, so a model mapping cannot be used to route around a deny.
The dashboard is the reason to run this instead of a script
The feature table describes an embedded React and Vite console covering account import and testing, API keys, proxy pools, an image studio with text to image and image to image, prompt filtering, usage analytics, operations, a scheduler board and system settings. Tabs like that only stay honest if the underlying state is visible, which is the argument the repository is making implicitly.
Two features are unusual enough to call out. The image studio is not an afterthought bolted onto a text gateway, it has its own workflow and its own billing rule in the recent release. And there is a quality check described as an editable pelican on a bicycle HTML or SVG animation challenge, where selected accounts, models and reasoning effort are compared, up to three tests run in the background, and history is kept with isolated animation previews, source, timing and token metrics. That is a way to see whether a pool of accounts is really behaving consistently rather than trusting aggregate counters.
Usage tracking is described as per account windowed cost over 5 hour and 7 day windows, plus credit quota support, per API key tracking, and a dashboard with request logs and trend charts. Request logs with a type column is what makes the earlier Daybreak migration visible to an operator instead of silently rewriting history.
The Dockerfile is a three stage build worth noting for anyone who wants to run this from source. A Node 20 Alpine stage builds the frontend once into static files, a Go 1.26.6 Alpine stage cross compiles the backend with `CGO_ENABLED=0` so the binary is architecture independent, and the final image is plain Alpine with certificates and timezone data added:
FROM alpine:3.19
RUN apk --no-cache add ca-certificates tzdata
EXPOSE 8080The Go stage also sets `GOPROXY=https://goproxy.cn,direct` with a comment explaining that direct connections to `proxy.golang.org` were breaking mid download. That single line tells you where a large share of this project's users are, which is also why the README is bilingual and why the compose files default the timezone to `Asia/Shanghai`.
Where the repository stops and your own policy begins
The README is long and specific about features and almost silent about terms. Its table of contents reserves a section for a disclaimer and a license, and GitHub shows no license for this project, which means the licensing question is not answered by anything in the tree you can check from the outside.
That matters more here than for most projects. The entire model is that a set of individual accounts, each holding a subscription entitlement, is pooled behind one API surface so that many clients can share it. Per-account credit billing and per-key quota control make that sharing explicit and auditable, which is to the author's credit. Whether that use sits inside the provider's terms is a question no amount of code in this repository answers, and it is the one to settle before importing credentials rather than after.
There is also a live demo instance linked from the README, with the password given in the open and a warning not to upload real tokens or keys to it. That warning is the right call and it also indicates how sensitive the input is.
For an evaluation, the honest ranking is this. If you need one endpoint that many clients share, with per key quotas, per account cost accounting and a record of what each request consumed, codex2api does more of that than a hand written forwarding script will. If you need a gateway you can reason about from source, the tree is well organized and the release notes explain their reasoning. What you will not get from the README is guidance on the account terms question, and that is the part to get right.
Editorial conclusion
codex2api is a well instrumented operations layer rather than a thin forwarding proxy, and its Go dependency list, three stage Dockerfile and dual database modes all point the same way. It is genuinely good at the part that is hard to write by hand: choosing a healthy account, recovering from rate limits, and recording what each request actually cost. What it does not settle is the licensing and account terms question that sits underneath the whole design, and that is a conversation to have before you import credentials rather than after. Start with the SQLite compose file on a loopback bind, point one client at it, and read the usage dashboard before you scale the pool out.
Frequently asked questions
What does codex2api actually convert into an API?
It pools individual Codex accounts and serves them through one Base URL. The routes cover OpenAI style chat completions and responses, Anthropic style messages, images, video and models, so several client types can share the same upstream pool without each one implementing the account rotation itself.
How does codex2api decide which account handles a request?
Selection is described as driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery and recent usage, so unhealthy accounts are skipped rather than retried blindly. Two scheduler modes are offered, `round_robin` and `remaining_quota`, and each account can carry its own credit billing flag.
Can codex2api run without PostgreSQL and Redis?
Yes. A lightweight path uses `docker-compose.sqlite.yml` with an embedded SQLite database and process memory instead of Redis, and `.env.sqlite.example` supplies the matching configuration. In that mode the service binds to `127.0.0.1` by default rather than all interfaces.
What happens to usage logs when a model alias is involved?
Recent releases separated the downstream request name, the actual model and the access program into three fields, after an earlier version overwrote the request model with the base model. A one time migration moves the known suffix into a dedicated column and deliberately leaves the already overwritten field untouched, because the original value cannot be reconstructed.
Is there a license file in the codex2api repository?
GitHub reports no license for this project, and no license file appears in the project layout, even though the README's table of contents reserves a section for a disclaimer and a license. Anyone planning to run this should settle the licensing question separately from the feature comparison.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/james-6-23-codex2api)