Skip to content

Errors and limits

HTTP status codes, error bodies, per-key monthly limits and how to retry safely.

Error format

Errors are returned with a non-2xx HTTP status and a JSON body with an error field. Depending on where the error comes from, error is either a string or an object:

Gateway checks: a string

Validation, authentication, insufficient balance and internal errors:

400 Bad RequestJSON
{  "error": "Missing required fields: model, messages"}

Key limits and provider errors: an object

Per-key monthly limits and errors passed through from the model provider use the OpenAI-style object with message and a code:

402 Payment RequiredJSON
{  "error": {    "message": "Monthly spend limit reached for this API key",    "type": "insufficient_quota",    "code": "key_monthly_limit"  }}
429 Too Many RequestsJSON
{  "error": {    "message": "Rate limit exceeded, please retry shortly",    "code": 429  }}

Handle both shapes when you parse errors yourself:

// Works for both error shapes returned by Promptixfunction errorMessage(body) {  if (typeof body?.error === 'string') return body.error;  return body?.error?.message ?? 'Unknown error';} const res = await fetch('https://promptix.tn/api/v1/chat/completions', { /* ... */ });if (!res.ok) {  const body = await res.json().catch(() => null);  const code = typeof body?.error === 'object' ? body.error.code : undefined;  throw new Error(`${res.status}${code ? ` ${code}` : ''}: ${errorMessage(body)}`);}

Status codes

StatusMeaningRetry
400Invalid request: the body is not JSON (Invalid JSON body), model or messages is missing or has the wrong type, or the provider rejected the request (unknown model, invalid parameter, prompt too long).No
401Missing, malformed, unknown or revoked API key, or deactivated account. See Authentication.No
402Balance below 0.100 TND (Insufficient credits), or the key reached its monthly limit (code key_monthly_limit).No
404The provider could not find the requested model or resource.No
413The request is too large for the model. Shorten the prompt or pick a model with a longer context.No
422The provider could not process the request as sent (for example an unsupported parameter combination).No
429The upstream provider is rate limiting this model. Retry with exponential backoff, or switch model.Yes
500Unexpected error in Promptix or upstream. Retry with backoff; contact support if it persists.Yes

Insufficient credits

A request is accepted only if your balance is at least 0.100 TND when it starts. Otherwise:

402 Payment RequiredJSON
{  "error": "Insufficient credits. Please top up your account."}

The cost of a request is deducted after it completes, so a long request that starts with a small balance can take it slightly below zero. Top up to continue; requests work again as soon as the payment is confirmed. Promptix emails you when your balance drops below 5 TND, so you can top up before this happens (you can turn this alert off in Settings).

Monthly key limit reached

When a key has a monthly limit and its spend since the first day of the month (UTC) has reached it, requests with that key return 402 with "code": "key_monthly_limit" and "type": "insufficient_quota". Nothing is billed. Raise or remove the limit in API keys, use another key, or wait for the next month. Details in Authentication.

Rate limits

Promptix does not add a requests-per-minute limit of its own. Throughput is limited by each model's provider: when a provider throttles, you receive its 429. Free models have much tighter limits than paid ones.

  • Retry 429 and 5xx responses with exponential backoff and jitter (for example 1 s, 2 s, 4 s, then give up).
  • Do not retry 400, 401, 402, 404, 413 or 422: the same request will fail again.
  • For bulk jobs, cap concurrency (a few parallel requests) rather than sending everything at once.
  • If one model stays throttled, fall back to an equivalent model from another provider.

Errors while streaming

Errors detected before a stream starts use the status codes above. If the provider fails after streaming has begun, the status is already 200; Promptix sends a final event and closes the stream without data: [DONE]:

text/event-streamtext
data: {"error":{"message":"Streaming failed","type":"stream_error"}}

See Streaming.

Handling errors with the OpenAI SDKs

The SDKs raise typed exceptions from the HTTP status and retry 408, 409, 429 and 5xx responses automatically (twice by default). A 402 is not retried.

import osimport openaifrom openai import OpenAI client = OpenAI(    base_url="https://promptix.tn/api/v1",    api_key=os.environ["PROMPTIX_API_KEY"],    max_retries=3,  # retries 408, 409, 429 and 5xx with exponential backoff    timeout=120,) try:    completion = client.chat.completions.create(        model="openai/gpt-4o-mini",        messages=[{"role": "user", "content": "Hello"}],    )except openai.AuthenticationError:    print("401: check PROMPTIX_API_KEY")except openai.RateLimitError:    print("429: the provider is throttling, retry later")except openai.APIStatusError as e:    if e.status_code == 402:        body = e.response.json()        err = body.get("error")        if isinstance(err, dict) and err.get("code") == "key_monthly_limit":            print("402: this key reached its monthly limit")        else:            print("402: balance too low, top up in the dashboard")    else:        print(e.status_code, e.message)

Timeouts

A request, including a stream, can run for up to 300 seconds on Promptix. Set your client timeout a little above the longest answer you expect, and use streaming for long generations so the connection is never idle.

Need help?

If an error persists, contact support with the time of the request, the model and, when you have it, the generation id.