API Docs

API Docs

OpenAI-compatible. Set base_url to https://api.tokengp.com/v1 and your existing SDK code works.

Looking for the Merchant Management API?

This page covers the end-user inference API — calls to /v1/* from any OpenAI-compatible SDK. If you’re a white-label tenant admin and want to manage brand, pricing, finance, or custom domains programmatically, use the separate Merchant Management API: token prefix sk-mgmt-*, base path /api/v1/merchant/*. Mint a token from the Console under API keys; the browsable OpenAPI spec lives at admin.tokengp.com/api/v1/merchant/docs.

Quickstart

One chat completions call — pick your favorite client.

curl https://api.tokengp.com/v1/chat/completions \
  -H "Authorization: Bearer $TOKENGP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-max",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ]
  }'

Authentication

All endpoints require an API key in the Authorization header:

Authorization: Bearer sk-tokengp-<your-key>
  • • Keys are issued at /keys and shown to you ONCE — store them securely.
  • • Optional per-key spend cap, RPM limit, allowed-models list, and source-IP allowlist can be set when creating a key. If an IP allowlist is set, only those IPv4/CIDR sources may call the key (403 otherwise); leaving it empty allows any IP.
  • • Revoke compromised keys immediately from the same page; revocation is instant.
GET/v1/models

List models

Returns the catalog of models your account can call. Filters out coming-soon and disabled models.

Example

curl https://api.tokengp.com/v1/models \
  -H "Authorization: Bearer $TOKENGP_API_KEY"
  • Each entry has OpenAI-shape fields (id, object, created, owned_by) plus extras: display_name, input_price_per_1m, output_price_per_1m. Most OpenAI SDKs ignore unknown fields.
GET/v1/models/{id}

Retrieve a model

Lookup a single model by id. Used by some SDKs during client initialization to validate the model name.

Example

curl https://api.tokengp.com/v1/models/qwen3.8-max \
  -H "Authorization: Bearer $TOKENGP_API_KEY"
  • 404 model_not_found if the id is unknown or disabled.
POST/v1/chat/completions

Chat completions

OpenAI-compatible chat-completions endpoint. Supports streaming (SSE) and non-streaming. Token usage is tracked at the upstream and your balance is debited at the end of each request.

Request body

{
  "model": "qwen3.8-max",
  "messages": [
    {"role": "system", "content": "You are concise."},
    {"role": "user", "content": "Explain JWT in one sentence."}
  ],
  "max_tokens": 256,
  "temperature": 0.2,
  "stream": false
}

Example

curl https://api.tokengp.com/v1/chat/completions \
  -H "Authorization: Bearer $TOKENGP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-max",
    "messages": [{"role":"user","content":"hi"}],
    "max_tokens": 32
  }'
  • For streaming, set "stream": true. Each SSE event is "data: {...}" carrying an OpenAI-shape chunk with "choices[0].delta.content" for partial text and "choices[0].finish_reason" on the final non-DONE chunk. Consume until you see "data: [DONE]".
  • Vision and tool / function calling are passed through to upstream models that support them (e.g. qwen-vl-*, qwen3-class). See the examples below.
  • Balance is pre-checked against worst-case cost (input + max_tokens × output_price). Insufficient balance returns 402.
  • Reasoning models (e.g. DeepSeek R1) bill the chain-of-thought as output_tokens — your usage.completion_tokens may exceed the visible message length. The chain itself is not exposed in the response.

Tool / function calling

Request body

{
  "model": "qwen3.8-max",
  "messages": [
    {"role": "user", "content": "What's the weather in Paris?"}
  ],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Get the current weather for a city.",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }
  }]
}
  • The model decides whether to call the tool. When it does, the response’s "choices[0].message.tool_calls" lists the function name + JSON arguments, and "finish_reason" is "tool_calls". Send back a follow-up request with the result as a {"role":"tool", ...} message.
  • Not every upstream supports tools. Currently Qwen-class, DeepSeek, and most OpenAI-compatible models do; small open-source models often do not.

Vision (image inputs)

Request body

{
  "model": "qwen3.8-max",
  "messages": [{
    "role": "user",
    "content": [
      {"type": "text", "text": "What is in this image?"},
      {"type": "image_url", "image_url": {"url": "https://example.com/cat.jpg"}}
    ]
  }]
}
  • Pass each user message’s "content" as an array of parts instead of a plain string. "image_url" accepts either an HTTPS URL or a "data:image/<mime>;base64,<...>" data URL.
  • Use a vision-capable model (e.g. qwen3.8-max, qwen-vl-plus). Sending an image to a text-only model is upstream-dependent — it may 400 or silently drop the image.
POST/v1/messages

Anthropic Messages (compat)

Anthropic Messages API compatibility endpoint. Tools built on the Anthropic SDK — Claude Code, ZCode, and friends — work against TokenGP by pointing their base URL here. Requests are translated to chat-completions internally, so auth, model allowlists, rate limits, and billing behave identically.

Request body

{
  "model": "qwen3.8-max",
  "max_tokens": 1024,
  "system": "You are concise.",
  "messages": [
    {"role": "user", "content": "Explain JWT in one sentence."}
  ],
  "stream": false
}

Example

curl https://api.tokengp.com/v1/messages \
  -H "x-api-key: $TOKENGP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-max",
    "max_tokens": 256,
    "messages": [{"role":"user","content":"hi"}]
  }'
  • Auth accepts both the Anthropic-style "x-api-key: <key>" header and "Authorization: Bearer <key>" — same sk-tokengp-* keys as everywhere else.
  • Streaming emits standard Anthropic SSE events (message_start, content_block_delta, message_delta, message_stop). Tool use and image inputs are translated both ways.
  • The "thinking" request parameter is accepted but not forwarded — whether a model reasons is decided upstream. Models that emit reasoning (e.g. DeepSeek) return it as a standard Anthropic "thinking" content block.
  • POST /v1/messages/count_tokens returns a local estimate (~4 chars/token). It never hits the upstream and is free.

Using TokenGP from ZCode

Request body

// %USERPROFILE%\.zcode\cli\config.json  (macOS/Linux: ~/.zcode/cli/config.json)
{
  "provider": {
    "tokengp": {
      "kind": "openai-compatible",
      "name": "TokenGP",
      "options": {
        "baseURL": "https://api.tokengp.com/v1",
        "apiKey": "sk-tokengp-...",
        "apiKeyRequired": true,
        "includeUsage": true
      },
      "models": {
        "qwen3.8-max": { "name": "Qwen3.8 Max" },
        "deepseek-v4-pro":   { "name": "DeepSeek V4 Pro" }
      }
    }
  },
  "model": { "main": "tokengp/qwen3.8-max", "lite": "tokengp/deepseek-v4-pro" }
}
  • ZCode desktop: Model Settings → Add provider → API format "Chat Completions", Base URL "https://<api-host>/v1" (the /v1 suffix is required), API key sk-tokengp-..., then add model ids copied verbatim from the /models page or GET /v1/models.
  • ZCode CLI (headless): create the config.json shown above. Model references use "provider/model-id" format.
  • Models configured with thinking levels make ZCode call /v1/messages instead of /chat/completions — supported either way as of this endpoint.
POST/v1/embeddings

Embeddings

Generate vector embeddings for one or more strings. Only models with modality=embedding are accepted here (chat models return 400 wrong_endpoint).

Request body

{
  "model": "text-embedding-v3",
  "input": "Hello, world."
}

Example

curl https://api.tokengp.com/v1/embeddings \
  -H "Authorization: Bearer $TOKENGP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "text-embedding-v3",
    "input": ["hello", "world"]
  }'
  • input accepts a single string or an array of strings.
  • Billing is by input tokens only (output_tokens = 0).
POST/v1/images/generations

Image generation

Generate images from a text prompt. We wrap Aliyun’s async task API so the client sees a synchronous response — typical latency is 3-10s. Charged per image regardless of resolution.

Request body

{
  "model": "qwen-image-plus",
  "prompt": "a red apple on a wooden table",
  "n": 1,
  "size": "1024x1024"
}

Example

curl https://api.tokengp.com/v1/images/generations \
  -H "Authorization: Bearer $TOKENGP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-plus",
    "prompt": "a red apple on a wooden table",
    "n": 1,
    "size": "1024x1024"
  }'
  • Response shape: {"created":<ts>,"data":[{"url":"<signed-oss-url>","revised_prompt":"..."}]}.
  • n is capped at 4. Sizes supported depend on the model; 1024x1024 works everywhere.
  • URLs are temporary signed OSS links — download and re-host within ~1 hour.
  • Internal polling deadline is 90s; long jobs return 504 upstream_timeout.

Error codes

All errors return JSON of shape {"error":{"code":"...","message":"...","type":"..."}}. HTTP status maps to error.code as follows.

The type field groups codes into families so you can branch on it without pattern-matching every name: auth_error (key issues), invalid_request_error (your input), rate_limit (RPM caps), billing_error (balance / cap), upstream_error (provider side), server_error (rare — our side).

HTTPerror.codeWhen you see it
400bad_requestRequired field missing or malformed body. Inspect error.message for specifics.
400wrong_endpointModel modality does not match endpoint (e.g. chat model on /v1/embeddings).
401missing_keyNo Authorization header. Send "Authorization: Bearer sk-tokengp-...".
401invalid_keyKey not found or revoked. Generate a new one at /keys.
402insufficient_balanceWorst-case cost exceeds account balance. Top up via /recharge.
402cap_reachedPer-key spend cap (balanceCapUsd) reached. Raise it or rotate the key.
403disabledAPI key was disabled by an admin.
403expiredAPI key expiresAt is in the past.
403model_not_allowedThis key has a model allowlist and the requested model is not on it. Edit the key at /keys or use an unrestricted key.
404model_not_foundUnknown model id. Call /v1/models to see what is available.
429rate_limit_exceededPer-key requests-per-minute (RPM) limit hit. Slow down or split across keys.
429tenant_rate_limit_exceededTenant-wide RPM ceiling reached — aggregated across every key in your tenant. Distinct from the per-key 429 above. Ask your tenant admin to raise the cap.
500pricing_misconfiguredThe model is missing required price config on our side (rare admin-side bug). Retry shortly; if it persists, contact support with the model id.
502upstream_unreachableCouldn't connect to the upstream provider. Usually transient — retry with backoff.
502upstream_errorUpstream returned an error. The response message has upstream details + upstream_status.
502image_generation_failedUpstream image task ended without success (returned FAILED or empty). Retry, change the prompt, or try a different image model.
503upstream_unavailableAll upstream tokens for the channel are in cooldown or disabled. We are aware.
504upstream_timeoutImage generation took longer than 90s. Submit again; same prompt may succeed.

Rate limits & quotas

  • Per-key RPM: each API key has a requests-per-minute limit (default 60). Exceeding it returns 429 rate_limit_exceeded. Raise the limit on a key in the /keys page.
  • Tenant-wide RPM ceiling: on white-label tenants, the tenant admin can set a tenant-level RPM cap that applies to all keys in the tenant combined. Hitting it returns 429 with tenant_rate_limit_exceeded — a distinct code from the per-key 429 so you can tell the two apart in your retry logic. Splitting traffic across more keys doesn’t help here; ask your tenant admin to raise the cap.
  • Account balance: every successful request is debited from your CNY balance. Insufficient balance returns 402; top up via /recharge.
  • Per-key spend cap: optional balanceCapUsd cuts off a key after a cumulative spend. Useful for embedding short-lived keys in client apps.
  • Upstream cooldowns: if all upstream tokens for a channel are throttled or erroring, the gateway returns 503 upstream_unavailable. Retry on backoff.
© 2026 TokenGP深圳市星驰通讯器材有限公司粤ICP备2024260232号-3客服与举报:support@tokengp.com