GlexirDocs
Dashboard

Billing & limits

HTTP error codes

Every error from the Glexir gateway uses OpenAI's error shape, so OpenAI-compatible clients handle it without changes. This page lists every status, type and code the gateway returns, what causes it, and how to fix it.

Error shape

JSON
{
  "error": {
    "message": "Your Glexir credit balance is too low (available $0.42, this request needs up to $1.10). Add credits or enable auto-recharge.",
    "type": "insufficient_quota",
    "param": null,
    "code": "credit_balance_exhausted"
  }
}
messagestringoptional
A readable explanation. It can change, so do not match on it.
typestringoptional
The broad error class, such as invalid_request_error or rate_limit_error.
paramstring | nulloptional
The request field that caused the error, when there is one (for example model, tools[0] or service_tier).
codestring | nulloptional
A stable machine-readable code. Branch on this. Some errors have no code.

Every response, success or error, carries an x-request-id header (req_...). Include it when you contact support.

Handle errors in code

Branch on status and code, not on message.

import Glexir, { APIConnectionError, APIError, RateLimitError } from "@glexir/sdk";

const glexir = new Glexir({ apiKey: process.env.GLEXIR_API_KEY });

try {
  const response = await glexir.responses.create({ model: "gpt-5.4-mini", input: "Say hello." });
  console.log(response.output_text);
} catch (err) {
  if (err instanceof APIConnectionError) {
    // No HTTP response: network failure or timeout. Already retried.
    console.error("connection problem", err.message);
  } else if (err instanceof RateLimitError) {
    console.error("429", err.code, err.headers?.get("retry-after"));
  } else if (err instanceof APIError && err.status === 402) {
    console.error("out of credit or over a spend limit:", err.code, err.param);
  } else if (err instanceof APIError) {
    console.error(err.status, err.type, err.code, err.param, err.requestID);
  } else {
    throw err;
  }
}

APIConnectionError extends APIError, so test for it first. The SDK has no class for 402 or 413; those are plain APIError instances. See Errors & retries for the full class list and retry rules.

Summary

StatustypecodeMeaning
400invalid_request_errornull, model_not_found, unsupported_on_glexirThe request is malformed or uses something Glexir does not support.
401authentication_errorinvalid_api_keyThe API key is missing, wrong or revoked.
402insufficient_quotacredit_balance_exhausted, spend_limit_exceededNot enough credit, or a monthly spend limit would be passed.
403permission_error, invalid_request_erroraccount_suspended, model_not_priced, tier_not_allowedYour organization, the model or the service tier is not allowed.
404invalid_request_errorunknown_endpoint, model_not_found, nullThe endpoint, model or object does not exist for you.
409invalid_request_erroridempotency_request_in_progress, idempotency_stream_replay, cross_account_referenceAn idempotency conflict, or objects that can't be combined.
413invalid_request_errorrequest_too_large, file_too_largeThe body or file is over the size limit.
422invalid_request_erroridempotency_key_reusedThe Idempotency-Key was used for a different request.
429rate_limit_errorrate_limit_exceeded, concurrency_limit_exceeded, rate_limitedToo many requests, too many at once, or upstream is busy.
500server_errornullAn unexpected error in the gateway.
502server_error, upstream_errorupstream_unreachable, upstream_auth_failed, upstream code or nullThe upstream provider failed or could not be reached.
503service_unavailable_error, server_errorcapacity_unavailable, upstream code or nullGlexir is temporarily out of upstream capacity.

You are not charged for a request that ends in an error response. The credit reserved for it is released. Streams are the exception: see Errors during a stream.

400 Bad request

type is invalid_request_error.

codeCauseFix
nullThe body is not valid JSON or not a JSON object; a required field is missing (input on embeddings, metadata on an update, input_file_id on a batch); a multipart endpoint got another content type; Idempotency-Key is longer than 255 characters (param is Idempotency-Key).Read message and param, and fix the request.
model_not_foundmodel is missing; the model is not valid for this endpoint (for example an embedding model on /v1/responses); the model is not enabled for Glexir; or the model only works on /v1/responses and you called /v1/chat/completions. param is model.Use a model from GET /v1/models that matches the endpoint. Models with -pro in the name only work on the Responses API.
unsupported_on_glexirThe request uses a feature Glexir does not offer: an OpenAI-hosted tool (web search, file search, code interpreter, MCP, image generation, shell, computer use, apply patch, tool search), input items those tools produce, a tool_choice that targets them, audio input or output, web_search_options, or a dashboard prompt template. param points at the field.Remove the feature. Use function or custom tools that you run yourself, send instructions in instructions, and send audio to /v1/audio/transcriptions. See Migrate from OpenAI.

Batch input files are checked line by line when you upload them. A failing line returns 400 with param: "file", a message that starts with Batch line N:, and the code of the underlying problem (for example unsupported_on_glexir). Other upload errors: purpose must be user_data or batch, and batch files must end in .jsonl, contain at most 50,000 requests, use one model and one URL, and must not stream.

Errors that OpenAI returns for your request's content (for example an invalid parameter value) are passed through with OpenAI's status, type, code and param. Any OpenAI organization or project identifiers in the message are redacted.

401 Authentication failed

typecodeCauseFix
authentication_errorinvalid_api_keyNo Authorization: Bearer header, an unknown key, or a revoked key.Send Authorization: Bearer glx_live_... with an active key from the dashboard.

A revoked key can keep working for up to 30 seconds while the gateway's key cache expires. Do not retry a 401; the SDK does not.

402 Payment required

Glexir is prepaid. Before a request goes upstream, the gateway reserves its worst-case cost from your balance. A 402 means that reservation was refused. type is insufficient_quota.

codeparamCauseFix
credit_balance_exhaustednullYour available balance (credit minus what in-flight requests have reserved) can't cover this request's reservation. The message shows both amounts.Add credits or turn on auto-recharge on the Billing page. Set max_output_tokens (or max_completion_tokens) so the reservation is smaller.
spend_limit_exceededorganizationThe request would push your organization past its monthly spend limit.Raise the limit on the Limits page, or wait for the next calendar month.
spend_limit_exceededapi_keyThe request would push this API key past its own monthly limit.Raise the key's limit on the API keys page, or use another key.

The reservation is an upper bound. When you set no output cap, the gateway reserves for 32,000 output tokens, so a small balance can be refused even for a short request. After the request finishes you are charged the actual usage and the rest is released. See Credits & billing.

Neither SDK retries a 402. Retrying will not help until you add credit or change the limit.

403 Forbidden

typecodeparamCauseFix
permission_erroraccount_suspendednullYour organization is suspended, frozen or closed.Contact support.
invalid_request_errormodel_not_pricedmodelThe model has no price in Glexir's price book, so Glexir does not sell it. Dated snapshot names (for example gpt-5.4-mini-2026-03-17) are not sold; use the alias.Use a model listed by GET /v1/models or on Pricing.
permission_errortier_not_allowedservice_tierYour account tier does not allow this service_tier for this model, or the model is not sold on that tier. For example, priority needs account tier 2 or higher.Drop service_tier or use one your tier allows. See Rate limits & spend limits.

404 Not found

type is invalid_request_error.

codeCauseFix
unknown_endpointThe path is not served by Glexir, for example POST /v1/images/generations or POST /v1/audio/speech. The message names the method and path.Use a supported endpoint. See What Glexir rejects.
model_not_foundGET /v1/models/{model} for a model Glexir does not sell.Pick a model from GET /v1/models.
nullA response, conversation, chat completion, file or batch ID that does not exist or belongs to another organization. Both cases look the same. The message is No <object> found with id '<id>'.Check the ID, and that you created it with a key from the same organization. Objects created directly on OpenAI do not exist on Glexir.

409 Conflict

type is invalid_request_error.

codeCauseFix
idempotency_request_in_progressAnother request with the same Idempotency-Key is still running.Wait and retry with the same key. You will get the stored result once the first request finishes.
idempotency_stream_replayThe original request with this key was a stream. Streams are not stored, so they can't be replayed.Do not retry a finished stream with the same key. Send a new request with a new key if you need the output again.
cross_account_referenceThe request references stored objects (files, a previous response, a conversation) that live in different Glexir regions and can't be used together.Use objects that were created together, or upload the file again and reference the new ID.

The @glexir/sdk and the official OpenAI SDKs retry every 409 up to maxRetries times. That helps with idempotency_request_in_progress but not with the other two codes.

413 Payload too large

type is invalid_request_error.

codeparamCauseFix
request_too_largenullA JSON body is over 20 MB, for example because of large base64 images or PDFs.Upload large files with purpose: "user_data" and reference them by file_id.
file_too_largefileAn audio file is over 25 MB, a user_data file is over 50 MB, or a batch file is over 20 MB.Split audio into chunks. Split batch input across several files.

422 Unprocessable entity

typecodeCauseFix
invalid_request_erroridempotency_key_reusedYou sent an Idempotency-Key that was used in the last 24 hours with a different method, path or body.Use a new key for every distinct request.

429 Too many requests

type is rate_limit_error.

codeCauseFix
rate_limit_exceededYour organization sent more requests in the current minute than its account tier allows. The response has a retry-after header in seconds.Wait retry-after seconds. Both SDKs do this automatically. Spread requests out, or move bulk work to batches.
concurrency_limit_exceededYour organization already has the maximum number of requests in flight for its tier. The message shows the limit.Limit parallelism in your client, for example with a queue.
rate_limitedUpstream capacity is busy after the gateway's own retries.Retry with backoff.

The requests-per-minute limit counts every authenticated request, including ones that later fail. Limits are per organization, not per key. See Rate limits & spend limits.

5xx Server and upstream errors

StatustypecodeCause
500server_errornullAn unexpected error in the gateway.
502server_errorupstream_unreachableNo upstream connection could be made.
502upstream_errorupstream_auth_failedThe upstream provider rejected Glexir's credentials. This is Glexir's problem, not your key.
502server_errorupstream code or nullThe upstream provider returned a 5xx other than 503.
503service_unavailable_errorcapacity_unavailableGlexir is temporarily out of upstream capacity.
503server_errorupstream code or nullThe upstream provider returned 503.

All of these are safe to retry with backoff, and both SDKs retry them by default. If they persist, contact support with the x-request-id.

Upstream retries and failover

The gateway retries upstream failures (408, 429 and 5xx responses, and connection errors) before it returns an error to you:

  • Stateless requests can be served by another upstream route. These are Chat Completions requests that don't reference stored files, embeddings, transcriptions and translations, model lookups, and input token counts.
  • Requests tied to stored state stay on the route that holds that state and get one more attempt there. This covers every POST /v1/responses (responses carry encrypted reasoning bound to where they were created), anything that uses previous_response_id, a conversation or a stored file, and every file, batch and conversation endpoint.

On a retry to the same route, if the upstream asks for a delay longer than 10 seconds, the gateway does not wait. It returns the error so your client can decide.

Errors during a stream

Once a stream has started, the HTTP status is already 200. An error then arrives as an SSE error event in the same shape:

Output
event: error
data: {"error":{"message":"The upstream stream went silent and was closed.","type":"server_error","code":"stream_timeout","param":null}}
codeCause
stream_timeoutThe upstream stream sent nothing for the idle timeout (10 minutes by default) and was closed.
upstream_stream_errorThe upstream connection failed mid-stream.

Error events from the upstream stream itself are passed through unchanged. In @glexir/sdk, a mid-stream error is thrown as an APIError whose status is undefined, so check err.code. Neither SDK retries a stream after it has started.

Billing for a text stream that ends early: if the upstream reported usage, you pay that usage. If the stream ended without a usage report, you are charged an estimate of the input tokens only. A transcription stream without a usage report is charged by the audio's duration.

SDK error classes

@glexir/sdk maps statuses to classes. All extend APIError, which extends GlexirError.

ClassWhen
BadRequestError400
AuthenticationError401
PermissionDeniedError403
NotFoundError404
ConflictError409
UnprocessableEntityError422
RateLimitError429
InternalServerErrorAny status of 500 or more
APIErrorAny other status, including 402 and 413, and errors inside a stream (status is undefined)
APIConnectionErrorNo response: network failure. status is undefined.
APIConnectionTimeoutErrorNo response within timeout. Extends APIConnectionError.
APIUserAbortErrorYou aborted the request with signal.

Two errors do not come from the API. parse() throws LengthFinishReasonError when the output hit the token limit and ContentFilterFinishReasonError when the content filter cut it off. Both extend GlexirError.

APIError properties
statusnumber | undefinedoptional
HTTP status. undefined for connection errors, aborts and errors inside a stream.
codestring | null | undefinedoptional
error.code from the body.
typestring | undefinedoptional
error.type from the body.
paramstring | null | undefinedoptional
error.param from the body.
errorAPIErrorBody | undefinedoptional
The whole error object: message, type, code, param and any other fields.
headersHeaders | undefinedoptional
Response headers, for example retry-after.
requestIDstring | null | undefinedoptional
The x-request-id header. Quote it to support.
messagestringoptional
The status followed by error.message, for example "402 Your Glexir credit balance is too low ...".