Docs/API
Errors, and what each one charged
What does each status mean, and did it cost me anything?
Checked against the code on
Errors use standard HTTP status codes and the OpenAI error envelope. The column that matters most is the last one: some failures happen after the model has already run, and those are charged.
{ "error": { "message": "Not enough credits. This request needs about 12. Add credits at https://heyaskr.ai/wallet", "type": "insufficient_quota", "param": null, "code": null } }Before the model runs
None of these charge anything. The reservation, if one was made, is released.
| Status | Type | Message | What to do |
|---|---|---|---|
| 400 | invalid_request_error | messages is required and must be a non-empty array. | Send a messages array. |
| 400 | invalid_request_error | Unsupported message role: X | Use system, user or assistant. |
| 400 | invalid_request_error | No usable messages were provided. | Send at least one message with string content. |
| 400 | invalid_request_error | The conversation is too long. | Trim below 120,000 characters. |
| 400 | invalid_request_error | That model has no published rate and cannot be billed. | Pick a model from the catalog. |
| 401 | authentication_error | Missing or invalid API key. | Check the header; make a new key if in doubt. |
| 402 | insufficient_quota | Not enough credits. This request needs about N. ... | Add credits. N is the worst case for this request, so a smaller max_tokens can get it through. |
| 404 | invalid_request_error | The model 'x' does not exist. | Ids are exact. Copy from the catalog. |
| 429 | rate_limit_error | This key's daily cap of N credits would be exceeded. ... | Raise the cap in the wallet or wait for the window to roll. |
| 429 | (plain body) | {"statusCode":429,"error":"Too Many Requests","message":"Rate limit exceeded, retry in 1 minute"} | 120 per minute per IP. This one is not in the OpenAI envelope. Back off and retry. |
| 503 | api_error | Model access is temporarily unavailable. Nothing was charged. | Retry shortly. |
| 502 | api_error | The model gateway is unavailable. | Retry with backoff. |
After the model has run
| Status | Type | Message | Charged? | What to do |
|---|---|---|---|---|
| 429 | rate_limit_error | The upstream gateway is busy. Retry shortly. | No | Retry after a short delay. |
| 502 or 400 | api_error | The model gateway rejected the request. | No | 502 when the provider failed, 400 when it refused the request. Check the prompt and the model. |
| 502 | api_error | The model returned no content. Nothing was charged. | No | A request that returns nothing is an error, not an empty answer. Retry or change the prompt. |
| 502 | api_error | The gateway sent an unreadable response. It was billed upstream, so the reserved credits were charged. | Yes, the reservation | Do not retry blindly. Check your activity first. |
| 504 | api_error | The model took longer than the gateway deadline. It was generated and billed upstream, so the reserved credits were charged. | Yes, the reservation | Lower max_tokens or pick a faster model. Do not retry blindly. |
A retry loop that treats every 5xx as free will double-spend on the two charged cases. Retry 503, 502 with unavailable or rejected, and 429. Log 504 and the unreadable 502 and look before retrying.
Backoff that behaves
import time, requests
RETRY = {429, 503}
def call(payload, tries=4):
for attempt in range(tries):
r = requests.post("https://heyaskr.ai/v1/chat/completions", json=payload,
headers={"Authorization": "Bearer askr_live_..."}, timeout=130)
if r.status_code == 200:
return r.json()
body = r.json().get("error", {})
charged = "reserved credits were charged" in body.get("message", "")
if r.status_code in RETRY or (r.status_code == 502 and not charged):
time.sleep(2 ** attempt)
continue
raise RuntimeError(f"{r.status_code}: {body.get('message')}")