Errors
HTTP statuses, stable error codes, payment challenges and rate-limit headers for SingIt Ask.
HTTP statuses
| Status | Common codes | What to do / was I charged? |
|---|---|---|
| 400 | invalid_json, invalid_request | Fix JSON or request fields. No charge. |
| 401 / 403 | unauthorized, forbidden | Check authentication and access. No answer charge. |
| 402 | payment_required | Inspect the challenge before signing. A settlement refusal has no challenge; reconcile the payment before retrying. |
| 404 | not_found, model_not_found | Check the route, symbol or available models. No charge. |
| 409 | payment_duplicate, stale_payment_permit | Signature already used, or a stale permit nonce. Check the original result; for a stale permit, wait for the previous settlement, then sign again. No new charge. |
| 413 | payload_too_large | Reduce the JSON body. No charge. |
| 422 | max_tokens_too_small, invalid_request | Fix the request; increase the output budget if reasoning left no answer. No charge. |
| 429 | rate_limited, free_tier_exhausted, free_budget_exhausted, free_tier_busy | Wait for Retry-After. No charge. |
| 502 / 504 | upstream_unavailable | Upstream or facilitator unavailable; inspect the response before retrying. |
| 503 | no_billable_answer, no_healthy_sellers, upstream_unavailable | Never charges. Wait for Retry-After where supplied, then retry. |
| 500 | internal_error | Unclassified error. Inspect the result and reconcile any submitted payment. |
Stable code vocabulary
Use code for programmatic handling and message for explanation. Clients must tolerate unknown codes, including existing route-specific and provider-specific values. A status can carry more than one code.
| Code | Meaning |
|---|---|
invalid_json | Unreadable JSON. |
invalid_request | Request fields cannot be accepted. |
payload_too_large | JSON body exceeds 128 KiB (131,072 bytes). |
model_not_found | Requested model unavailable. |
not_found | Route or price symbol unavailable. |
rate_limited | Request allowance exhausted. |
free_tier_exhausted | Visitor or shared daily answer allowance exhausted. |
free_budget_exhausted | Shared daily free budget spent; resets at midnight UTC. |
free_tier_busy | Free answer concurrency full. |
payment_required | Payment challenge or settlement refusal. |
payment_duplicate | Payment signature already used. |
stale_payment_permit | Obtain a fresh payment challenge. |
no_billable_answer | Nothing billable returned. |
no_healthy_sellers | No healthy seller for the model. |
max_tokens_too_small | Reasoning consumed output allowance without an answer. |
upstream_unavailable | Catalogue, facilitator or provider unavailable. |
unauthorized | Authentication refused. |
forbidden | Access refused. |
internal_error | Unclassified server error. |
invalid_identity | Direct payment identity validation failed. |
request_changed | Direct request conflicts with prepared quote. |
already_prepared | Direct quote already prepared. |
previous_quote_pending | Previous direct quote still pending. |
unknown_model | Direct quote model lookup failed. |
already_paid | Direct quote already paid. |
already_submitted | Direct quote already submitted. |
quote_unavailable | Direct quote unavailable for submission. |
invalid_payment | Direct payment validation failed. |
terms_changed | Direct payment terms changed. |
verification_unavailable | Direct payment verification unavailable. |
verification_refused | Direct payment verification refused. |
payment_unresolved | Direct settlement unresolved. |
Error envelopes
OpenAI-style errors contain error.type, error.message and error.code. On /v1/messages the Anthropic envelope adds top-level type: "error" and also uses error.code. Bare string errors keep error as a string and add a sibling top-level code. The OpenAPI components.schemas include ErrorResponse, AnthropicErrorResponse, PaymentRequired402 and RateLimited429.
Verified 31 October 2026: malformed JSON
{
"error": {
"type": "invalid_request_error",
"message": "Send valid JSON.",
"code": "invalid_json"
}
}Verified 31 October 2026: unknown route
{
"error": {
"type": "invalid_request_error",
"message": "Cannot GET /nope",
"code": "not_found"
}
}Schema example: Messages envelope
{
"type": "error",
"error": {
"type": "api_error",
"message": "No answer came back. Try again.",
"code": "no_billable_answer"
}
}402: challenge or settlement refusal
An unpaid POST /v1/chat/completions returns x402Version, accepts, error: "payment_required" and code: "payment_required". x402Version and accepts equal the corresponding fields of the decoded PAYMENT-REQUIRED header. This was verified against ask.singitai.app on 31 October 2026 (Europe/Prague). Select only an offer you intend to sign. Existing spend-limit metadata can also be present.
If a submitted payment could not be settled, the 402 has no PAYMENT-REQUIRED header, no x402Version and no accepts. Do not treat that response as a new offer:
Source example: settlement refusal
{
"error": "payment_required",
"code": "payment_required"
}429: read the headers
Retry-After is in seconds. Free-tier daily exhaustion includes X-RateLimit-Limit (configured visitor allowance), X-RateLimit-Remaining: 0 and X-RateLimit-Reset (Unix seconds at the next UTC midnight). The shared budget can deny access before your visitor allowance is used: free_budget_exhausted has only Retry-After until midnight UTC, without per-visitor X-RateLimit headers. Busy free-tier responses have only Retry-After: 5, without these daily limit headers.
/v1/prices uses fixed minute windows. Its 429 includes X-RateLimit-Limit (60 per visitor or 3000 overall, whichever blocks), X-RateLimit-Remaining: 0 and X-RateLimit-Reset (the next minute boundary). Retry-After: 60 is a conservative wait and can extend beyond that boundary. Successful price responses do not acquire these rate-limit headers.