OpenCode Go Usage API

August 13, 2026 · View on GitHub

Important

This project is no longer maintained (2026-08-14) and is kept only as an archive.

Why: OpenCode now provides an official JSON usage API — GET https://opencode.ai/zen/go/v1/usage — authenticated with the regular Authorization: Bearer <API_KEY> header (the standard Anthropic-compatible API key); no workspace ID or auth cookie is needed. This endpoint is not covered by the official documentation; it was discovered in farion1231/cc-switch#6433, which also includes a ready-to-use script for CC Switch's custom usage template. To try it:

curl -H "Authorization: Bearer <API_KEY>" https://opencode.ai/zen/go/v1/usage

The discontinuation condition set when this project started (CC Switch natively supporting OpenCode Go usage queries, or OpenCode providing a JSON usage API) has been met, so no new features, fixes, or issue responses should be expected. Please migrate to the official endpoint.

中文文档:README.md

When accessed, this service fetches the specified OpenCode Go workspace page in real time, parses the usage data, and returns JSON. It supports configuring multiple OpenCode Go accounts in a single service, and is designed for the usage-query feature of CC Switch.

This project was discontinued on 2026-08-14: OpenCode's undocumented /v1/usage endpoint was publicized in #6433, meeting the discontinuation condition set when this project started (CC Switch officially supporting OpenCode Go usage queries, or OpenCode providing a JSON usage API). Previously tracked issues and PRs: #2260, #3606

API

Query usage

  • GET /usage: queries the default account specified in config.toml.
  • GET /usage/{account_id}: queries a specific account, e.g. /usage/backup.

Both endpoints require the Authorization: Bearer <API_TOKEN> header, and successful responses share the same format:

{
  "success": true,
  "reason": "",
  "data": "Rolling 0% (5h) | Weekly 7% (3d16h) | Monthly 3% (29d22h)"
}
  • success: true when at least one usage group is parsed.
  • reason: explains the cause when fetching or parsing fails.
  • data: usage and reset countdown, customizable via the response template.

Expired credentials, fetch failures, and parse failures for known accounts still return HTTP 200, indicated by success:false. Unknown accounts return HTTP 404, and authentication failures return HTTP 401.

Health check

GET /health requires no authentication and returns {"status":"ok"}. This endpoint only checks that the service is alive; it does not fetch any account pages.

Configuration

The service always reads config.toml from the current working directory. Copy the example and restrict file permissions:

cp config.example.toml config.toml
chmod 600 config.toml

Full example:

[server]
api_token = "It's recommended to generate a strong random value with openssl rand -hex 32"
host = "0.0.0.0"
port = 18443
ssl_certfile = "certs/cert.pem"
ssl_keyfile = "certs/key.pem"

[fetch]
timeout = 10
retries = 1
locale = "zh"
user_agent = "Mozilla/5.0 ..."

[response]
data_template = "Rolling {rolling_percent}% ({rolling_reset}) | Weekly {weekly_percent}% ({weekly_reset}) | Monthly {monthly_percent}% ({monthly_reset})"

[account]
default = "main"

[accounts.main]
auth_cookie = "auth cookie value of the main account"
workspace_id = "wrk_main"

[accounts.backup]
auth_cookie = "auth cookie value of the backup account"
workspace_id = "wrk_backup"

Account IDs support 1–64 characters of uppercase/lowercase letters, digits, _, and -. The first character must be a letter or digit, and IDs are case-sensitive.

The configuration is validated at startup. After modifying the config file, the service must be restarted for changes to take effect.

Configuration options

OptionDefaultDescription
server.api_tokenNoneAPI access token, required
server.host0.0.0.0Listen address
server.port18443Listen port
server.ssl_certfile / ssl_keyfileEmptyMust both be set; HTTP is used when both are empty
fetch.timeout10Timeout in seconds for a single fetch
fetch.retries1Number of retries after a network error
fetch.localezhOpenCode's oc_locale cookie
fetch.user_agentBuilt-in browser UAUser-Agent for upstream requests
response.data_templateBuilt-in templateTemplate for the data field in the response
account.defaultNoneDefault account ID, required
accounts.<id>.auth_cookieNoneThe raw auth cookie value of that account
accounts.<id>.workspace_idNoneThe workspace ID of that account
  • Workspace ID: https://opencode.ai/workspace/<here>/go
  • Getting the cookie: open https://opencode.ai/workspace/wrk_XXX/go in your browser and inspect it via developer tools (F12)

Customizing the data format

Template placeholders consist of a group and a field, in the format {<group>_<field>}. There are three groups:

GroupMeaning
rollingRolling usage
weeklyWeekly usage
monthlyMonthly usage

Each group supports three fields:

FieldMeaning
percentPercentage used
resetCountdown until reset
statusStatus text

Example of a compact-style configuration:

[response]
data_template = "R {rolling_percent}% ({rolling_reset}) | W {weekly_percent}% ({weekly_reset}) | M {monthly_percent}% ({monthly_reset})"

Deployment

The following example assumes the system is Ubuntu 24.04, the project directory is /opt/opencode-go-usage-api, and uv is installed.

cd /opt
git clone https://github.com/andywang425/opencode-go-usage-api.git
cd opencode-go-usage-api
uv sync
cp config.example.toml config.toml
# Edit config.toml as needed
chmod 600 config.toml

If you need a self-signed certificate:

chmod +x gen-cert.sh
./gen-cert.sh <public IP or domain>

Then write the paths of the generated certificates into config.toml:

[server]
ssl_certfile = "certs/cert.pem"
ssl_keyfile = "certs/key.pem"

Install the systemd service:

chmod +x run.sh
cp opencode-go-usage-api.service /etc/systemd/system/
# Edit /etc/systemd/system/opencode-go-usage-api.service as needed
systemctl daemon-reload
systemctl enable --now opencode-go-usage-api
systemctl status opencode-go-usage-api

If you modify the configuration later, restart the service for changes to take effect:

systemctl restart opencode-go-usage-api

Remember to allow server.port (default 18443) in your cloud provider's security group / firewall.

Verify the service (add -k when using a self-signed certificate):

curl -k https://127.0.0.1:18443/health
curl -k -H "Authorization: Bearer <API_TOKEN>" https://127.0.0.1:18443/usage
curl -k -H "Authorization: Bearer <API_TOKEN>" https://127.0.0.1:18443/usage/backup
# View logs
journalctl -u opencode-go-usage-api -f

Nginx reverse proxy

You can run the API service in HTTP mode and serve HTTPS through an Nginx reverse proxy.

First, edit config.toml:

[server]
host = "127.0.0.1" # listen on localhost only
port = 18443

ssl_certfile = "" # leave empty: use HTTP
ssl_keyfile = "" # leave empty: use HTTP

Example Nginx configuration:

upstream opencode_go_usage {
    server 127.0.0.1:18443; # must match server.port in config.toml
    keepalive 16;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com; # change to your public IP or domain

    # Enable both TLS 1.2 and 1.3 for compatibility with old and new CC Switch versions
    ssl_protocols              TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers  on;

    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256;
    ssl_session_cache  shared:SSL:10m;
    ssl_session_timeout 1d;

    # Change to your own certificates (when using the self-signed certificates generated by gen-cert.sh, fill in the paths of cert.pem and key.pem respectively)
    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    location / {
        proxy_pass http://opencode_go_usage;

        proxy_http_version 1.1;
        proxy_set_header Connection "";

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 15s;
        proxy_read_timeout    60s;
        proxy_send_timeout    60s;
    }
}

With the reverse proxy in place, you only need to allow port 443 in your security group / firewall; server.port (default 18443) does not need to be exposed publicly. The URL configured in CC Switch can also omit the port number, e.g. https://<public IP or domain>/usage/<ACCOUNT_ID>.

CC Switch integration

Click the usage-query configuration icon, select "Custom" as the preset template, and paste the following extractor code:

({
  request: {
    url: "https://<public IP or domain>:<PORT>/usage/<ACCOUNT_ID>",
    method: "GET",
    headers: {
      Authorization: "Bearer <API_TOKEN>",
    },
  },
  extractor: function (response) {
    return {
      isValid: response.success,
      invalidMessage: response.reason,
      extra: response.data,
    };
  },
});

If /<ACCOUNT_ID> is omitted, the usage of the default account is queried. If you use a self-signed certificate, you need to import the certificate into the trust store of the operating system where CC Switch runs.

How to install a self-signed certificate on Windows 11: download certs/cert.pem to your machine by any means, rename it to cert.crt, double-click it, choose Install Certificate → Store Location: Current User → Place all certificates in the following store → Browse → Trusted Root Certification Authorities → Next, Finish.

Local development

uv sync
cp config.example.toml config.toml
# Start after editing config.toml
uv run uvicorn opencode_go_usage_api:app --reload

Run tests:

uv run pytest

License

MIT