Multi-Account Management - Support multiple upstream account types (OAuth, API Key). API Key Distribution - Generate and manage API Keys for users. Precise Billing - Token-level usage tracking and cost calculation
Tools
Tools
No tool list yet. Remote servers get one after the first health check.
Copy the stdio config for Cursor, Claude Desktop, Claude Code, or VS Code on this page. It uses the publisher's install, not a PlugMCP proxy.
Does Sub2api need an API key?
No required environment variable is listed on this record.
What transport does Sub2api use?
Sub2api runs locally over stdio.
When was Sub2api last checked?
Last checked 2026-11-09. Multi-Account Management - Support multiple upstream account types (OAuth, API Key). API Key Distribution - Generate and manage API Keys for users. Precise Billing - Token-level usage tracking and cost calculation
From the publisher
Documentation
Sub2API
AI API Gateway Platform for Subscription Quota Distribution
Please read the following carefully before using this project:
🚨 Terms of Service Risk: Using this project may violate the terms of service of Anthropic and other upstream providers. Please review the relevant providers' user agreements before use; all risks arising from such use are borne solely by the user.
⚖️ Compliant Use: Use this project only in compliance with the laws and regulations of your country or region. Any unlawful use is strictly prohibited.
📖 Disclaimer: This project is provided for technical learning and research purposes only. The authors assume no liability for account bans, service interruptions, data loss, or any other direct or indirect damages resulting from the use of this project.
Key features
01. Multi-Account Management - Support multiple upstream account types (OAuth, API Key)
02. API Key Distribution - Generate and manage API Keys for users
03. Precise Billing - Token-level usage tracking and cost calculation
04. Smart Scheduling - Intelligent account selection with sticky sessions
05. Concurrency Control - Per-user and per-account concurrency limits
06. Rate Limiting - Configurable request and token rate limits
🚫 No Commercial Authorization: The developers of this project have never authorized any individual or organization to conduct any form of commercial operation based on this project. Any commercial activity conducted in the name of or based on this project is unrelated to this project and its developers, and all resulting disputes, losses, and legal liabilities shall be borne solely by the party conducting such activity.
Free trial credits: sign up via this exclusive link to claim free trial credits.
Overview
Sub2API is an AI API gateway platform designed to distribute and manage API quotas from AI product subscriptions. Users can access upstream AI services through platform-generated API Keys, while the platform handles authentication, billing, load balancing, and request forwarding.
Features
Multi-Account Management - Support multiple upstream account types (OAuth, API Key)
API Key Distribution - Generate and manage API Keys for users
Precise Billing - Token-level usage tracking and cost calculation
Smart Scheduling - Intelligent account selection with sticky sessions
Concurrency Control - Per-user and per-account concurrency limits
Rate Limiting - Configurable request and token rate limits
Built-in Payment System - Supports EasyPay, Alipay, WeChat Pay, and Stripe for user self-service top-up, no separate payment service needed (Configuration Guide)
Admin Dashboard - Web interface for monitoring and management
Composite Groups - Admin routing layer that resolves requested models to concrete providers for multi-provider groups (Operator Guide)
External System Integration - Embed external systems (e.g. ticketing) via iframe to extend the admin dashboard
Ecosystem
Community projects that extend or integrate with Sub2API:
Cross-platform app (iOS/Android/Web) for user management, account management, monitoring dashboard, and multi-backend switching; built with Expo + React Native
Tech Stack
Component
Technology
Backend
Go 1.27.0, Gin, Ent
Frontend
Vue 3.4+, Vite 5+, TailwindCSS
Database
PostgreSQL 15+
Cache/Queue
Redis 7+
Nginx Reverse Proxy Note
When using Nginx as a reverse proxy for Sub2API (or CRS) with Codex CLI, add the following to the http block in your Nginx configuration:
underscores_in_headers on;
Nginx drops headers containing underscores by default (e.g. session_id), which breaks sticky session routing in multi-account setups.
Deployment
Method 1: Script Installation (Recommended)
One-click installation script that downloads pre-built binaries from GitHub Releases.
# PostgreSQL password (REQUIRED)
POSTGRES_PASSWORD=your_secure_password_here
# JWT Secret (RECOMMENDED - keeps users logged in after restart)
JWT_SECRET=your_jwt_secret_here
# TOTP Encryption Key (RECOMMENDED - preserves 2FA after restart)
TOTP_ENCRYPTION_KEY=your_totp_key_here
# Optional: Admin account
# Leave empty to auto-generate a random email (login username) and password, shown in logs on first startup.
# Avoid guessable values such as [email protected]: they are brute-force targets.
ADMIN_EMAIL=
ADMIN_PASSWORD=
# Optional: Custom port
SERVER_PORT=8080
# Pull latest image and recreate container
docker compose -f docker-compose.local.yml pull
docker compose -f docker-compose.local.yml up -d
Easy Migration (Local Directory Version)
When using docker-compose.local.yml, migrate to a new server easily:
# On source server
docker compose -f docker-compose.local.yml down
cd ..
tar czf sub2api-complete.tar.gz sub2api-deploy/
# Transfer to new server
scp sub2api-complete.tar.gz user@new-server:/path/
# On new server
tar xzf sub2api-complete.tar.gz
cd sub2api-deploy/
docker compose -f docker-compose.local.yml up -d
Useful Commands
# Stop all services
docker compose -f docker-compose.local.yml down
# Restart
docker compose -f docker-compose.local.yml restart
# View all logs
docker compose -f docker-compose.local.yml logs -f
# Remove all data (caution!)
docker compose -f docker-compose.local.yml down
rm -rf data/ postgres_data/ redis_data/
Method 3: Apple container (macOS)
Apple-silicon Macs running macOS 26 can run the full Sub2API, PostgreSQL, and Redis stack with Apple container 1.1.0 or newer:
git clone https://github.com/Wei-Shaw/sub2api.git
cd sub2api/deploy
./apple-container.sh init
./apple-container.sh up
./apple-container.sh status
This is an operator-managed local workflow; Docker Compose remains the recommended production path. See deploy/APPLE_CONTAINER.md for lifecycle commands, persistence, upgrades, and runtime limitations.
Method 4: Build from Source
Build and run from source code for development or customization.
Prerequisites
Go 1.21+
Node.js 18+
PostgreSQL 15+
Redis 7+
Build Steps
# 1. Clone the repository
git clone https://github.com/Wei-Shaw/sub2api.git
cd sub2api
# 2. Install pnpm (if not already installed)
npm install -g pnpm
# 3. Build frontend
cd frontend
pnpm install
pnpm run build
# Output will be in ../backend/internal/web/dist/
# 4. Build backend with embedded frontend
cd ../backend
VERSION="$(./scripts/resolve-version.sh)"
go build -tags embed -ldflags="-X main.Version=${VERSION}" -o sub2api ./cmd/server
# 5. Create configuration file
cp ../deploy/config.example.yaml ./config.yaml
# 6. Edit configuration
nano config.yaml
Note: The -tags embed flag embeds the frontend into the binary. Without this flag, the binary will not serve the frontend UI.
security.csp to control Content-Security-Policy headers
billing.circuit_breaker to fail closed on billing errors
security.trust_forwarded_ip_for_api_key_acl enables legacy raw forwarded-header takeover (enabled by default for upgrade compatibility); disable it to enforce server.trusted_proxies, which should contain only the exact proxy CIDRs that connect directly to Sub2API
security.forwarded_client_ip_headers configures up to 16 third-party CDN client-IP header names; they are checked in order before the built-in headers only while legacy takeover is enabled
turnstile.required to require Turnstile in release mode
Custom client-IP headers can be set in YAML or as a comma-separated environment variable:
Header names are validated, canonicalized, and de-duplicated. The admin security settings can update the list without a restart; new installations persist YAML/environment defaults and existing installations backfill a missing database value. When legacy takeover is disabled, all custom and built-in raw forwarding headers are ignored and Gin uses only server.trusted_proxies. While takeover is enabled, firewall the origin to CDN/proxy addresses and make the edge overwrite every trusted client-IP header. See deploy/EDGE_SECURITY.md for the complete migration and trust-boundary rules.
⚠️ Security Warning: HTTP URL Configuration
When security.url_allowlist.enabled=false, the system performs minimal URL validation and allows HTTP URLs by default (dev-friendly mode; Docker Compose deployments use the same default). For production, explicitly tighten this to HTTPS-only:
security:
url_allowlist:
enabled: false # Disable allowlist checks
allow_insecure_http: false # HTTPS only (recommended for production)
✅ Testing account connectivity before obtaining HTTPS
❌ Production environments (use HTTPS only)
Example error for HTTP URLs when allow_insecure_http: false is set:
Invalid base URL: invalid url scheme: http
If you disable URL validation or response header filtering, harden your network layer:
Enforce an egress allowlist for upstream domains/IPs
Block private/loopback/link-local ranges
Enforce TLS-only outbound traffic
Strip sensitive upstream response headers at the proxy
OpenAI Responses WebSocket ingress limits
gateway.openai_ws bounds the lifetime and aggregate count of client-facing
Responses WebSocket sessions. These safeguards apply independently from
per-turn user and account concurrency slots, which are released between turns.
gateway:
openai_ws:
# Total time to receive and decompress the first client message.
client_first_message_timeout_seconds: 30
# Close a client socket idle between completed turns; 0 disables this safeguard.
ingress_inter_turn_idle_timeout_seconds: 300
# Distributed API-key limit for live client ingress sessions; 0 disables it.
max_ingress_connections_per_api_key: 64
The first-message timeout is a total read deadline. Deployments that accept
large contexts or image-heavy requests over slower links can raise it to
120-300 seconds. It expires before HTTP bridge routing, so bridge mode does not
override this limit.
The connection cap is coordinated through Redis using a 60-second lease that
is refreshed every 20 seconds. A process that cannot confirm a lease for a
full lease lifetime closes its local WebSocket rather than continuing outside
the global cap.
Enable the v2 mode router before selecting an account-level WS mode such as
http_bridge:
gateway:
openai_ws:
mode_router_v2_enabled: true
Or set GATEWAY_OPENAI_WS_MODE_ROUTER_V2_ENABLED=true in the environment.
Use http_bridge for client-WebSocket/upstream-HTTP operation when rolling out
or mitigating upstream WebSocket issues.
Force OpenAI upstream HTTP/SSE
When an egress proxy or network repeatedly reconnects OpenAI Responses
WebSockets, set the global fallback in the persisted deployment configuration:
gateway:
openai_ws:
force_http: true
For Compose and Apple container deployments, the equivalent .env setting is:
GATEWAY_OPENAI_WS_FORCE_HTTP=true
This selects HTTP/SSE for OpenAI upstream Responses traffic that would
otherwise use WebSocket. It does not change the client-facing protocol or force
HTTP/1.1; configure gateway.openai_http2.enabled (or
GATEWAY_OPENAI_HTTP2_ENABLED=false) separately when a proxy is incompatible
with HTTP/2. Unlike the account-level http_bridge mode, this global fallback
takes effect without enabling mode_router_v2_enabled. Keep the setting in the
deployment's persisted .env or config.yaml, rather than inside a running
container, so it is read again after an image update or container recreation.
⚠️ Important: Creating the Admin Account
The initial admin account is only created via the setup wizard (served at http://<host>:8080 on first run). The default.admin_email / default.admin_password fields in config.yaml are not used to create it — they exist in the template for historical reasons.
Because step 5 above pre-creates config.yaml, the setup wizard will be skipped on first run: the server detects an existing config and boots straight into normal mode with an empty users table, so the first login attempt fails with invalid email or password.
Two ways to create the admin account:
Recommended — let the wizard generate config.yaml: Skip step 5 (do not run the cp). Start ./sub2api directly; the setup wizard at http://localhost:8080 walks you through database, Redis, and admin account setup, then writes config.yaml for you.
If you already created config.yaml: Temporarily move it aside so the wizard can trigger on first run, then restore it afterwards:
mv config.yaml config.yaml.bak
./sub2api # wizard runs at http://localhost:8080 and writes a fresh config.yaml
# stop the server (Ctrl+C) once the wizard completes, then restore your config:
mv config.yaml.bak config.yaml
./sub2api # restart in normal mode and log in with the admin you just created
# 6. Run the application
./sub2api
Development Mode
# Backend (with hot reload)
cd backend
go run ./cmd/server
# Frontend (with hot reload)
cd frontend
pnpm run dev
Code Generation
When editing backend/ent/schema, regenerate Ent + Wire:
cd backend
go generate ./ent
go generate ./cmd/server
Simple Mode
Simple Mode is designed for individual developers or internal teams who want quick access without full SaaS features.
Enable: Set environment variable RUN_MODE=simple
Default groups are seeded on each startup. Set SIMPLE_MODE_AUTO_CREATE_DEFAULT_GROUPS=false (or YAML simple_mode.auto_create_default_groups: false) to manage groups yourself. The default is true; disabling it does not delete existing groups or change runtime auto-binding or admin concurrency setup.
Difference: Hides SaaS-related features and skips billing process
Optional key windows: Set SIMPLE_MODE_KEY_RATE_LIMIT_ENABLED=true to enforce each API key's configured 5-hour, daily, and 7-day spending windows. The default is false; balance and subscription debit remain bypassed when enabled.
Window enforcement uses the database as its source of truth and records only API-key window usage. It is a post-request soft cap, so concurrent in-flight requests can overshoot by their final costs. Historical simple-mode usage is not backfilled.
Security note: In production, you must also set SIMPLE_MODE_CONFIRM=true to allow startup
Asynchronous Image Tasks
Long-running OpenAI/Grok image generation and editing can be submitted through /v1/images/generations/async or /v1/images/edits/async, then polled at /v1/images/tasks/{task_id} without holding a CDN connection open. See Asynchronous Image Tasks for request and response examples.
Grok / xAI Support
Sub2API supports both Grok subscription accounts through xAI OAuth and standard xAI API-key accounts. Both account types forward OpenAI-compatible Responses traffic to xAI.
Supported Scope
Platform name: grok
Account types: OAuth subscription accounts and xAI API-key accounts
Public Responses targets: /v1/responses, /responses, and /backend-api/codex/responses, forwarded to the Grok subscription proxy for OAuth accounts or https://api.x.ai/v1/responses for API-key accounts
Public Claude-compatible target: /v1/messages, converted to xAI Responses and returned as Anthropic Messages output for Claude CLI style clients
Public Chat Completions targets: /v1/chat/completions and /chat/completions, forwarded to the account-type-specific xAI upstream
Codex CLI style Responses WebSocket ingress is accepted on the Responses targets and bridged to xAI HTTP/SSE Responses upstream
Text models: grok-4.5, grok-4.3, grok-build-0.1, grok-composer-2.5-fast, grok-4.20-0309-reasoning, grok-4.20-0309-non-reasoning, and grok-4.20-multi-agent-0309
Media targets for Grok groups: /v1/images/generations, /images/generations, /v1/images/edits, /images/edits, /v1/videos/generations, /videos/generations, /v1/videos/edits, /videos/edits, /v1/videos/extensions, /videos/extensions, /v1/videos/{request_id}, and /videos/{request_id}. Generation, editing, and extension requests require the group image-generation permission.
Media models: grok-imagine, grok-imagine-image-quality, grok-imagine-image, grok-imagine-image-2.0, grok-imagine-edit, grok-imagine-video, and grok-imagine-video-1.5
JSON image-edit and video-generation requests accept image references in image, images, reference_images, and mask objects. Use url for xAI-compatible payloads; the legacy image_url field remains accepted and is normalized to url before forwarding.
Out of scope for this provider: TTS, transcription, browser automation, cookies, and Grok web scraping
OAuth Configuration
The Grok OAuth flow uses PKCE and does not require committing private secrets. The default client details follow the public xAI OAuth flow used by compatible clients, and every value can be overridden by environment variable:
0.2.114; optional override for the client identity sent to cli-chat-proxy.grok.com. The pinned value is also the floor: an override below it is dropped
Administrators can create Grok OAuth or API-key accounts from the dashboard. OAuth authorization and reauthorization are also available through the admin API:
Endpoint
Purpose
POST /api/v1/admin/grok/oauth/auth-url
Generate an xAI OAuth authorization URL
POST /api/v1/admin/grok/oauth/exchange-code
Exchange a callback URL, query string, or code for OAuth credentials
POST /api/v1/admin/grok/oauth/refresh-token
Validate or refresh a Grok refresh token
POST /api/v1/admin/grok/accounts/:id/refresh
Refresh an existing Grok account
OAuth credential storage reuses the existing account JSON fields: access_token, refresh_token, token_type, expires_at, base_url, optional email, optional subscription_tier, and entitlement_status. OAuth inference defaults to https://cli-chat-proxy.grok.com/v1; existing OAuth accounts that stored the old https://api.x.ai/v1 default are redirected to the subscription proxy at runtime. Explicit custom upstreams remain unchanged.
For API-key accounts, select Grok → API Key in the create-account dialog. The official base URL defaults to https://api.x.ai/v1; credentials use the existing base_url and api_key account fields. OAuth accounts continue to use the subscription flow above.
Grok Build CLI Configuration
In the Sub2API admin dashboard, add either a grok OAuth account and complete xAI authorization, or add a Grok API-key account.
Create a Grok group, attach the account to it, then create a Sub2API API key assigned to that group.
In the user API-key page, click Use Key and select Grok CLI. The modal generates the correct file and base URL for macOS/Linux or Windows. It also provides an OpenCode configuration on the OpenCode tab.
If configuring manually, save the following as ~/.grok/config.toml (Windows: %USERPROFILE%\.grok\config.toml):
Back up an existing config.toml before merging the entry. The file contains a Sub2API API key, so keep it private and restrict its permissions where supported. Verify the effective configuration and make a smoke request:
grok inspect
grok -p "Reply with sub2api-ok" -m grok
The base_url above is the public Sub2API URL ending in /v1, not api.x.ai or the internal xAI OAuth proxy URL.
Usage And Quota Display
xAI quota is passive. Sub2API does not invent subscription quota values; it records whitelisted xAI rate-limit headers from successful or rate-limited upstream responses when xAI sends them. Before the first usable upstream response, the dashboard shows quota as unknown and still displays local Sub2API usage stats.
401 responses temporarily remove accounts with invalid credentials from scheduling. 403 responses are treated as access or entitlement failures instead of token-refresh loops. 429 responses use Retry-After or a short cooldown to temporarily remove the account from scheduling.
New Grok image and video generation requests use a media-specific eligibility check. API-key accounts remain eligible. OAuth accounts with explicit Free or forbidden billing evidence are excluded from new media generation. Missing or malformed observations are probed before dispatch; a successful but incomplete billing response is treated as billing_inconclusive and remains eligible for backwards compatibility, because an unknown billing schema is not proof that the account lacks media entitlement. Operators can quarantine a known-bad account with extra.grok_media_eligible=false or force-enable a verified account with true. Imports run the billing-first quota probe proactively. Chat requests and video status lookups are not affected by this media-only quarantine. If no eligible account remains, the media endpoint returns HTTP 503 with error type grok_media_no_eligible_account.
Administrators can override automatic media eligibility through the account create/update API by setting extra.grok_media_eligible to false (exclude) or true (force eligible). On update, set it to null to remove the override and return to automatic probe-based behavior; omitting the field preserves the current override. A weekly allowance period alone is not treated as a paid tier signal. Successful image responses must contain at least one actual image output; empty HTTP 200 responses trigger account failover instead of being counted and returned as successful generations.
TypeSafe / Jev Support
Sub2API supports TypeSafe API-key accounts through Jev's native, non-streaming System One protocol.
Platform: typesafe; account type: API Key
Default upstream: https://api.typesafe.ai
Public endpoint: POST /v1/systemone
Model: jev-latest, also returned by /v1/models for TypeSafe groups
Questions: noul, choice, and score
Requests and successful responses retain the native System One JSON structure. This endpoint is not compatible with Chat Completions, Responses, Anthropic Messages, or streaming clients.
Question validation follows the TypeSafe OpenAPI wire schema (also used by SDK v0.5.7). instructions may be omitted or null for all question types. Noul criteria may be omitted or null; its true/false descriptions and Choice descriptions accept strings, objects, arrays, or null. Score criteria must be a non-empty array of string, object, or array descriptions; a single level is valid. SDK integer-keyed Score maps are normalized to arrays by the SDK before sending.
curl https://your-sub2api.example.com/v1/systemone \
-H 'Authorization: Bearer sk-your-sub2api-key' \
-H 'Content-Type: application/json' \
--data '{"model":"jev-latest","state":"Text to evaluate","questions":{"safety":{"type":"noul","instructions":"Evaluate whether the text is unsafe"}}}'
The built-in jev-latest price is $0.042 per million input tokens and $0 for output tokens. Channel pricing can override both values. Credential, billing, permission, rate-limit, overload, server, and network failures (401, 402, 403, 429, 529, 5xx, transport errors) use the existing account error policy (including custom error codes and temporary-unschedulable rules) and fail over to another account; request errors (400, 413, and 422) are returned without retrying another account and never change account state. TypeSafe groups (and Composite requests routed to TypeSafe) reject Messages, Chat Completions, Responses, and count_tokens requests with 404.
Antigravity Support
Sub2API supports Antigravity accounts. After authorization, dedicated endpoints are available for Claude and Gemini models.
Antigravity accounts support optional hybrid scheduling. When enabled, the general endpoints /v1/messages and /v1beta/ will also route requests to Antigravity accounts.
⚠️ Warning: Anthropic Claude and Antigravity Claude cannot be mixed within the same conversation context. Use groups to isolate them properly.