Billing Rules and Error Codes
The token billing formula, group multipliers, how to reconcile your bill, and a troubleshooting order plus retry strategy for 401/404/429/5xx errors.
The billing formula
Per-token models:
cost = model base price × group multiplier × token usage- Base price: the "USD per 1M tokens" on the pricing page, input and output priced separately
- Group multiplier: default = ×1.0; Claude official / OpenAI official / Gemini premium = ×1.5
- Token counts are converted with each model's tokenizer; expect small (±5%) differences from local estimates
Per-call models (image / video / 3D): billed at the flat "$/call" price on the pricing page.
Reconciling your bill in three steps
- Console → logs: find the call, confirm model, group and timestamp
- Multiply
usage(prompt_tokens / completion_tokens) by the pricing-page unit price - Compare with the charge record; mismatches usually mean a non-default group was used
Groups
| Group | Multiplier | Notes |
|---|---|---|
| default | ×1.0 | Every model, first choice |
| Claude official | ×1.5 | Pure official-channel Claude, stability first |
| OpenAI official | ×1.5 | Pure official-channel OpenAI |
| Gemini premium | ×1.5 | Premium Gemini channel, full video analysis |
Error code reference
| Status | Meaning | Fix |
|---|---|---|
| 401 | Invalid key or bad format | Check the sk- prefix, stray spaces, disabled status |
| 403 | No permission for model/group | Confirm group and model availability in the console |
| 404 | Model name doesn't exist | Copy the exact name from the models page |
| 429 | Rate limited | Exponential backoff; contact support for a quota raise |
| 500/502/503 | Upstream channel issue | Auto channel rotation; retry 2–3 times |
| Timeout | Long input or slow upstream | Stream + shorter max_tokens |
Error body format:
{
"error": {
"message": "This token cannot use model xxx",
"type": "forbidden"
}
}Retry template
import time, random
def with_retry(fn, attempts=4):
for i in range(attempts):
try:
return fn()
except Exception as e:
status = getattr(e, "status_code", None)
if status in (429,) or (status and status >= 500):
wait = (2 ** i) + random.random()
time.sleep(wait)
continue
raise
raise RuntimeError("retries exhausted")Principle: only retry idempotent, potentially-recoverable errors (429, 5xx). 400/401/404 mean fix your configuration — retries are pointless.
Cost control checklist
- Set
max_tokenson every call - Keep system prompt prefixes stable to hit prompt caching
- Prefer low-priced default-group models for high-frequency paths
- Watch the daily usage curve in the console; investigate spikes same-day
For billing disputes, use the channels on the contact page with timestamps, model names and log screenshots.