English | 简体中文 | Tiếng Việt | Italiano
A Go gateway for OpenCode Zen and Zen Go. It exposes Chat Completions, Responses, and Anthropic Messages endpoints, translates between their native protocols, and manages upstream keys and proxies.
The executable includes the WebUI. Running the service requires no Node.js runtime or database.
public credential.sota / sweet model groups with ordering, failure fallback, streaming protection, and persisted state.See the management console guide (Chinese) for the new pages and configuration.
|
IPWO residential proxies provide flexible network connectivity for AI development and API workflows, covering 195+ countries and regions with HTTP(S) and SOCKS5 support. Suitable for cross-region network testing, compliant data collection, and automated development. Dynamic, static, and unlimited proxy plans are available, with free testing and region selection. Discount code: 0200. |
Download a binary from GitHub Releases, or build with Go 1.24 or newer:
git clone https://github.com/jasonxu114514/opencode2api.git
cd opencode2api
cp config.example.json config.json
go build -o opencode2api ./cmd/opencode2api
Before starting, edit config.json:
server_keys with your own local API key.webui.password. The example enables the WebUI with username admin../opencode2api -config config.json
On Windows, use Copy-Item config.example.json config.json, build with go build -o opencode2api.exe ./cmd/opencode2api, then run .\opencode2api.exe -config config.json.
The example listens on 127.0.0.1:8080 for the API and 0.0.0.0:8081 for the WebUI. Open http://localhost:8081 locally. Restrict management access and use an HTTPS reverse proxy when accessing it over a network.
Command-line options:
| Option | Default | Purpose |
|---|---|---|
-config |
config.json |
Configuration file path. |
-listen |
Unset | Override the API listen address. |
-web-listen |
Unset | Override the WebUI listen address. |
The configuration directory must be writable for password migration, configuration saves, and model caches.
The published image is ghcr.io/jasonxu114514/opencode2api.
cp config.example.json config.json
# Configure keys and replace the WebUI password before starting.
docker compose up -d
docker compose logs -f
Compose imports the host configuration into the opencode2api-state volume only on first startup. Subsequent changes should be made through the WebUI. To import an edited host configuration again:
docker compose cp config.json opencode2api:/var/lib/opencode2api/config.json
docker compose restart
The container runs the service as an unprivileged user. Compose uses a read-only root filesystem, a writable state volume, and a temporary /tmp filesystem.
WARP needs only outbound UDP (Cloudflare endpoint port 2408), so the image's non-root, no-NET_ADMIN setup still works; do not switch to host networking or add --cap-add for it. If the container network blocks UDP, enabling WARP fails at startup.
| Compose variable | Default | Effect |
|---|---|---|
OPENCODE2API_VERSION |
latest |
Image tag. Pin a release tag for a fixed version. |
OPENCODE2API_PORT |
8080 |
Host port mapped to container port 8080. |
OPENCODE2API_WEBUI_PORT |
8081 |
Host port mapped to container port 8081. |
OPENCODE2API_LISTEN |
Unset | Explicit container API listen override. |
OPENCODE2API_WEBUI_LISTEN |
Unset | Explicit container WebUI listen override. |
The last two variables become LISTEN_ADDRESS and WEBUI_LISTEN_ADDRESS inside the container. Empty values defer to the configuration file. While initializing a configuration, the entrypoint changes the example API address 127.0.0.1:8080 to 0.0.0.0:8080 so published ports can reach it.
Changing host ports does not change container listeners. If you change the internal API port, also update the port mapping and the image health check, which uses port 8080.
For a local image:
docker build -t opencode2api:local .
docker volume create opencode2api-state
docker run -d --name opencode2api \
-p 8080:8080 -p 8081:8081 \
-e CONFIG_SEED_PATH=/run/config/opencode2api.json \
-v "$(pwd)/config.json:/run/config/opencode2api.json:ro" \
-v opencode2api-state:/var/lib/opencode2api \
opencode2api:local
A proxyfile used in Docker must also be available inside the container at the configured path.
server_keys authenticate clients to this gateway. They are separate from zen_keys and go_keys and are never used as upstream credentials.
Send Authorization: Bearer YOUR_LOCAL_API_KEY or x-api-key: YOUR_LOCAL_API_KEY. Health checks require no authentication.
| Method | Path | Description |
|---|---|---|
| GET | /v1/models |
Models that can be routed with the current configuration. |
| POST | /v1/chat/completions |
Chat Completions. |
| POST | /v1/responses |
Responses. |
| POST | /v1/messages |
Anthropic Messages. |
| POST | /v1/systemone |
System One structured decisions. |
| GET | /healthz |
Readiness and resource summary. |
Discover an available model first:
curl http://localhost:8080/v1/models \
-H "Authorization: Bearer YOUR_LOCAL_API_KEY"
Replace MODEL_ID below with an ID from that response.
Chat Completions
curl http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer YOUR_LOCAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","messages":[{"role":"user","content":"Hello"}]}'
Responses
curl http://localhost:8080/v1/responses \
-H "Authorization: Bearer YOUR_LOCAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","input":"Hello"}'
Anthropic Messages
curl http://localhost:8080/v1/messages \
-H "x-api-key: YOUR_LOCAL_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","max_tokens":512,"messages":[{"role":"user","content":"Hello"}]}'
For streaming, add "stream": true to the body and use curl -N. Responses include an x-request-id for correlation. API request bodies are limited to 32 MiB.
System One
curl http://localhost:8080/v1/systemone \
-H "Authorization: Bearer YOUR_LOCAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"MODEL_ID","state":"1 + 1 = 2","questions":{"arithmetic":{"type":"noul","instructions":"Is 1 + 1 equal to 2?"}}}'
System One pairs a free-form state with typed questions and returns typed answers, so the payload shares no shape with the chat/responses bridge and is relayed verbatim, never translated. Only models whose native protocol is System One are served here; a decision payload submitted on a message endpoint (/v1/chat/completions, /v1/responses) is likewise relayed verbatim instead of converted. Streaming upstream replies are relayed as-is without reset recovery.
Requests using the upstream's native protocol retain provider-specific fields. Requests crossing protocols pass through a common representation; not every option has an equivalent. For example, Chat JSON output constraints and seed are not forwarded to Anthropic Messages. Unsupported content or tool types may be rejected.
The gateway exposes the routes listed above. It does not implement embeddings, file uploads, image generation, or Responses retrieval and cancellation. It does not store conversation history; clients must supply the history or use features supported by the actual upstream.
The gateway refreshes Zen/Go /v1/models and OpenCode's capability catalog on the configured interval. Native protocols and model limits are tracked separately for each tier. OpenCode's Zen/Go documentation is a fallback for protocol discovery.
models.protocols overrides discovery:
{
"models": {
"refresh_seconds": 300,
"protocols": {
"custom-model": "chat"
}
}
}
Allowed protocol values are chat, responses, and anthropic. Models usin
| 日期 | 榜单 | 排名 | 周期新增 | 总 STAR |
|---|