API
Error codes
All errors use the OpenAI format. Branch on
error.code (stable), not on message (may change).{
"error": {
"message": "Insufficient balance: this request may cost up to $0.002014 (max_tokens=1000), available balance is $0.0005. Top up your wallet or lower max_tokens.",
"type": "insufficient_quota",
"code": "insufficient_balance"
}
}The OpenAI SDK maps statuses to exceptions: 400 → BadRequestError, 401 → AuthenticationError, 402 → APIStatusError (check e.status_code), 403 → PermissionDeniedError, 404 → NotFoundError, 422 → UnprocessableEntityError, 429 → RateLimitError, 5xx → InternalServerError. Every error response includes the X-Request-Id header.
API /v1#
- 400
invalid_request- Meaning
- Invalid body: missing model, empty messages, max_tokens not a positive integer, stream not a boolean; embeddings: empty/wrong-type input, more than 2,048 items, invalid dimensions…
- What to do
- Fix the request as described in the returned message.
- 400
invalid_json- Meaning
- The body is not valid JSON.
- What to do
- Check Content-Type: application/json and the JSON syntax.
- 400
model_type_mismatch- Meaning
- Wrong model type for the endpoint: an embedding model on
/v1/chat/completionsor a chat model on/v1/embeddings. - What to do
- Use the endpoint named in the message, or switch to a model of the right type (Type column in the pricing table).
- 400
unsupported_parameter- Meaning
- Unsupported parameter (currently: n other than 1).
- What to do
- Remove the parameter or send several requests.
- 400 / 413 / 422
upstream_invalid_request- Meaning
- The model/provider rejected the request (e.g. context window exceeded, a parameter the model doesn’t accept). If the provider returns a safe code such as
context_length_exceeded, that code is passed through unchanged. - What to do
- Shorten the prompt, lower max_tokens or remove parameters the model doesn’t support. Not billed.
- 401
missing_api_key- Meaning
- No Authorization: Bearer header.
- What to do
- Add the header; see authentication.
- 401
invalid_api_key- Meaning
- The key is wrong or has been revoked.
- What to do
- Check the key or create a new one.
- 402
insufficient_balance- Meaning
- The available balance doesn’t cover the request’s maximum hold.
- What to do
- Top up or lower
max_tokens. Don’t retry automatically. See holds.
- 402
key_spend_limit_exceeded- Meaning
- The key has reached its spend limit (including in-flight requests).
- What to do
- Raise the key’s limit in the dashboard or use another key.
- 403
model_not_allowed- Meaning
- This key is not allowed to use that model.
- What to do
- Add the model to the key’s allowed models.
- 403
account_suspended- Meaning
- The account is suspended.
- What to do
- Contact support.
- 404
model_not_found- Meaning
- The model doesn’t exist or is disabled.
- What to do
- Get the correct name from
GET /v1/models.
- 404
null- Meaning
- Wrong endpoint path (code is null).
- What to do
- Check that the base URL includes
/v1.
- 413
request_too_large- Meaning
- The body is larger than 10 MB.
- What to do
- Reduce the size (images, conversation history).
- 429
rate_limit_exceeded- Meaning
- The key’s rpm, the account’s rpm or the concurrency limit was exceeded.
- What to do
- Wait as indicated by the
Retry-Afterheader, then retry. See Rate limits.
- 429
upstream_rate_limited- Meaning
- The upstream provider is temporarily rate limiting.
- What to do
- Retry after a few seconds (backoff). Not billed.
- 502
upstream_error- Meaning
- The provider failed, timed out, was unreachable or returned an invalid response.
- What to do
- Retry with backoff. The hold is released; not billed.
- 503
price_not_configured- Meaning
- The model temporarily has no selling price.
- What to do
- Retry later or use another model; contact support if it persists.
- 200 (SSE)
upstream_error- Meaning
- An error during a stream, after data was sent: a
data: {"error": …}event, then the stream closes. - What to do
- The generated part is billed; resend the request if you need the complete answer.
Which errors are billed?
Only successful requests (or streams that already produced content) are billed. Any error before the model responds — including provider errors — releases the hold.
Dashboard (/api)#
Errors you may see when using the dashboard or calling the dashboard API directly.
- 401
unauthenticated- Meaning
- The session has expired or the token is invalid.
- What to do
- Sign in again (the dashboard refreshes sessions automatically).
- 401
invalid_credentials- Meaning
- Wrong email or password.
- What to do
- Try again.
- 401
invalid_refresh_token- Meaning
- The refresh token has expired / been revoked.
- What to do
- Sign in again.
- 403
permission_denied- Meaning
- Your role doesn’t have permission.
- What to do
- —
- 403
not_a_partnerpartner_disabled- Meaning
- Partner pages: the account is not a partner, or the partner has been disabled.
- What to do
- Contact support.
- 409
email_taken- Meaning
- The email is already registered.
- What to do
- Sign in or use a different email.
- 409
too_many_codes- Meaning
- The partner already has the maximum number of active referral codes.
- What to do
- Deactivate some old codes.
- 400
amount_too_small- Meaning
- The transfer amount is below the minimum (10,000 VND by default, after conversion if you enter USD).
- What to do
- Increase the amount.
- 400
amount_too_large- Meaning
- The transfer amount exceeds the maximum for a single QR code (1,000,000,000 VND).
- What to do
- Split it into several top-ups.
- 400
too_many_keyskey_revoked- Meaning
- You already have 50 active keys / you tried to edit a revoked key.
- What to do
- Revoke unused keys / create a new key.
- 400
invalid_cursor- Meaning
- Invalid pagination cursor.
- What to do
- Start again from the first page.
- 404 / 409
not_foundconflict- Meaning
- Not found / state conflict.
- What to do
- Reload the page.
- 422
invalid_request- Meaning
- Invalid form data.
- What to do
- Fix it as described in the message.
- 503
deposits_not_configured- Meaning
- The server has no receiving bank account configured.
- What to do
- Tell an administrator.
- 503
fx_rate_unavailable- Meaning
- No USD/VND exchange rate is available yet, so a QR code can’t be created.
- What to do
- Retry later or tell an administrator.
Admin & webhooks#
Only seen in the admin console (admin/root) and the payment webhook.
- 403
root_only- Meaning
- This action is reserved for root.
- What to do
- Sign in as root.
- 409
root_protected- Meaning
- The root account can’t be changed via the API (it is managed in .env).
- What to do
- Edit ROOT_* in .env and restart.
- 409
loss_risk- Meaning
- The new price / commission rate makes
list × (1 − r) < cost. The body includeserror.risks[]. - What to do
- Adjust it, or resend with
?confirm_loss=true.
- 409
model_not_ready- Meaning
- Enabling a model that has no deployment with a passing test, or no price.
- What to do
- Add a deployment + price, then enable it again.
- 409
role_managed_by_partner- Meaning
- Changing the role of a partner account.
- What to do
- Use the Partners page.
- 409
idempotency_key_reused- Meaning
- A wallet adjustment reused an Idempotency-Key with a different body.
- What to do
- Use a new key.
- 409
use_assign- Meaning
- Confirming a deposit with a transaction that already exists.
- What to do
- Assign the transaction on the Bank transactions page.
- 409
nothing_payabledeductions_exceed_payablepayout_would_be_negative- Meaning
- Creating a payout when no commission is pending, or when clawbacks exceed it.
- What to do
- Pick another period / wait for more commission.
- 422
invalid_price_version- Meaning
- The price version has an invalid effective_from.
- What to do
- Choose a different effective time.
- 500
credential_encryption_error- Meaning
- The provider key can’t be decrypted (did SECRET_ENCRYPTION_KEY change?).
- What to do
- Restore the correct SECRET_ENCRYPTION_KEY or re-enter the provider key.
- 501
not_supported- Meaning
- The provider doesn’t support listing remote models.
- What to do
- Enter the model name manually.
- 401 / 400 / 503
invalid_signatureinvalid_payloadwebhook_not_configured- Meaning
- SePay webhook: bad HMAC signature, IP not in the allowlist, invalid body, or SEPAY_WEBHOOK_SECRET not set.
- What to do
- Check the SePay configuration (README).