go2llm API documentation

API errors

Always check both the HTTP code and the response body. For gateway errors the object carries error.type, error.code, error.message and error.request_id; an upstream may return the compatible error format of its own protocol.

HTTPCode or reasonWhat to do
400invalid_requestcheck your JSON and the required fields
400unsupported_content_typeremove the image, audio, video, PDF or binary block from a text request
400model_protocol_mismatchpick the endpoint listed in /v1/models
400stateful_responses_unsupporteddrop previous_response_id and store: true, send the history in input
401no-keysend a valid API key
402insufficient_balancetop up the balance or lower max_tokens
403model, inactive, expired, ipcheck the key's settings
404model_not_foundrefresh the catalog and copy the exact model ID
404endpoint_not_foundthere is no such route under /v1/; compare with the list in error.message
405method_not_allowedthe route exists but takes a different method — it is named in the allow header
409idempotency_conflictdo not reuse one Idempotency-Key for different image requests
429quota, rate_limitcheck the quota; respect Retry-After
502upstream_unavailableretry a safe text request after a delay
503product_paused, no_eligible_routecheck /status and retry later

A miss on the route

Any unknown path under /v1/ answers with JSON in the same shape as every other error, not with plain text — an SDK can parse that and show a human the reason instead of garbage.

curl -i https://go2llm.tech/v1/embeddings
{
  "error": {
    "type": "invalid_request_error",
    "code": "endpoint_not_found",
    "message": "/v1/embeddings is not published by this gateway. Available: POST /v1/messages, POST /v1/chat/completions, POST /v1/responses, POST /v1/images/generations, POST /v1/messages/count_tokens, GET /v1/models, GET /v1/models/{id}, GET /v1/me. See https://go2llm.tech/docs/endpoints",
    "request_id": "gw_..."
  }
}

If the path is published but the method is wrong, you get 405 method_not_allowed with an allow header — that way a typo in the path is distinguishable from a wrong method.

curl -i -X GET https://go2llm.tech/v1/messages   # 405, allow: POST

OPTIONS on the routes that take an API key also returns 405, with an explanation that browser-side calls are unsupported on purpose: a key in a browser bundle is readable by every visitor. CORS is open only on public reads of the catalog, prices and status; details are in API endpoints.

Stateful Responses

POST /v1/responses is implemented as a stateless adapter: the gateway keeps no response history. The fields previous_response_id, store: true and background: true are rejected with 400 stateful_responses_unsupported, and the message says the gateway stores no response state and the full history must be sent in input. How to restructure the loop is on the Responses API page.

Request ID

x-go2llm-request-id is now on every /v1/* response, including failed and streamed ones. On errors the same identifier is duplicated in the body as error.request_id; the prefix is gw_.

curl -sD - -o /dev/null https://go2llm.tech/v1/models | grep -i x-go2llm-request-id

Log that header on your side: with it a support request can be traced to a specific call, without it it cannot.

Everything else

Do not automatically retry a media request that came back with ambiguous_upstream_result: the provider may have accepted it. Keep the request_id for support, but never send your full API key.

The gateway does not emit X-RateLimit-Remaining or X-RateLimit-Reset. Retry-After arrives on 429, on 409 request_in_progress and on 503 product_paused; on 502 upstream_unavailable it does not — build your own retry strategy. To check the remaining budget before a long run, so you don't hit a 402 halfway through a task, call GET /v1/me — see Balance and spending.