EN ZalogujZałóż konto
Startujemy w październiku 2026. Działają konta, katalog modeli, kalkulator i dokumentacja. Studio jest dostępne w podglądzie; generowanie czeka na uruchomienie.

Błędy

Wszystkie strony dokumentacji

Jantaris używa standardowych kodów HTTP. 2xx znaczy, że zapytanie przeszło. Każdy inny kod ma ciało JSON z typem błędu, na którym możesz oprzeć logikę.

Format

/v1/generate, /v1/tasks, /v1/models i /v1/balance zwracają:

json
{ "error": { "type": "insufficient_balance", "message": "Available balance is lower than the estimated cost of this task." } }

Endpointy czatu zachowują format SDK, z którym są zgodne, więc istniejąca obsługa błędów dalej działa:

EndpointFormat błędu
/v1/chat/completionsOpenAI: {"error": {"message": "...", "type": "..."}}
/v1/messagesAnthropic: {"type": "error", "error": {"type": "...", "message": "..."}}

message jest dla ludzi i może się zmienić. Logikę opieraj na kodzie HTTP i polu type.

Typy błędów

HTTPtypeZnaczenieCo zrobić
400invalid_requestŹle zbudowane zapytanie, np. uszkodzony JSON albo brak modelPopraw zapytanie
401authentication_errorBrak klucza, zły format albo klucz usuniętySprawdź klucz i nagłówek, patrz Uwierzytelnianie
402insufficient_balanceDostępne saldo niższe niż koszt albo blokadaDoładuj saldo
403permission_errorKlucz osiągnął miesięczny limit wydatków. Komunikat: This key reached its monthly spend limit. Create a new key with a higher limit in the dashboard or use another key.Utwórz nowy klucz z wyższym limitem albo użyj innego klucza
404not_foundNieznane id modelu albo zadaniaSprawdź id w Modelach
422invalid_requestinput nie pasuje do input_schema modeluPrzeczytaj komunikat, wskazuje pole
429rate_limitZa dużo zapytań na ten kluczZwolnij i ponów z rosnącym odstępem
429rate_limit_error25 nieudanych generacji na koncie w ciągu ostatnich 24 h; nowe zlecenia /v1/generate są wstrzymanePoczekaj tyle sekund, ile podaje nagłówek Retry-After, i popraw prompt albo parametry
502upstream_errorDostawca modelu zwrócił błądPonów po krótkiej przerwie
504timeoutModel nie odpowiedział na czasPonów, przy czacie rozważ krótszą odpowiedź

Limity zapytań

Domyślne limity na klucz API:

EndpointLimit
POST /v1/generate60 zapytań na minutę
/v1/chat/completions, /v1/messages600 zapytań na minutę
POST /v1/generate, nieudane generacje25 na konto w ciągu 24 h (okno przesuwne), potem 429 rate_limit_error z nagłówkiem Retry-After

Po przekroczeniu limitu dostajesz 429 rate_limit. Rozłóż zapytania w czasie albo daj osobne klucze osobnym zadaniom.

Nieudane zadanie to nie błąd HTTP

Generowanie, które wystartowało i potem się wysypało, nie daje błędu HTTP. POST /v1/generate zwraca 202, a później zadanie ma status: "failed" i obiekt error:

json
{ "id": "task_3xq1...", "status": "failed", "error": { "type": "upstream_error", "message": "..." }, "cost": { "amount": "0.00", "currency": "PLN" } }

Blokada wraca na saldo, płacisz 0. Sprawdzaj status każdego zakończonego zadania, patrz Zadania.

Kiedy ponawiać

Ponawiaj 429, 502 i 504 z wykładniczo rosnącym odstępem. Nie ponawiaj 400, 401, 402, 403, 404 ani 422 bez zmiany czegoś po swojej stronie, bo to samo zapytanie skończy się tak samo.

Nie ponawiaj w pętli zadań, które kończą się status: "failed". Nieudane generacje nic nie kosztują, ale po 25 porażkach w ciągu doby konto dostaje 429 rate_limit_error i nowe zlecenia czekają, aż minie czas z nagłówka Retry-After. Zanim ponowisz, zmień prompt albo parametry.

python
import os, random, time, requests

RETRY = {429, 502, 504}

def call(method: str, url: str, **kwargs) -> requests.Response:
    headers = {"Authorization": f"Bearer {os.environ['JANTARIS_API_KEY']}"}
    for attempt in range(5):
        r = requests.request(method, url, headers=headers, timeout=130, **kwargs)
        if r.status_code not in RETRY:
            break
        time.sleep(min(2 ** attempt, 30) + random.random())
    if r.status_code >= 400:
        err = r.json().get("error", {})
        raise RuntimeError(f"{r.status_code} {err.get('type')}: {err.get('message')}")
    return r

task = call("POST", "https://jantaris.com/v1/generate",
            json={"model": "gpt-image-2.5", "input": {"prompt": "Czerwony rower"}}).json()
javascript
const RETRY = new Set([429, 502, 504]);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function call(url, init = {}) {
  let res;
  for (let attempt = 0; attempt < 5; attempt++) {
    res = await fetch(url, {
      ...init,
      headers: { Authorization: `Bearer ${process.env.JANTARIS_API_KEY}`, "Content-Type": "application/json", ...init.headers },
    });
    if (!RETRY.has(res.status)) break;
    await sleep(Math.min(2 ** attempt * 1000, 30000) + Math.random() * 1000);
  }
  if (!res.ok) {
    const { error } = await res.json();
    throw new Error(`${res.status} ${error?.type}: ${error?.message}`);
  }
  return res.json();
}

SDK OpenAI i Anthropic mają ponowienia wbudowane. Oba domyślnie kilka razy ponawiają limity i błędy serwera, a liczbę prób ustawiasz przez max_retries (Python) albo maxRetries (JavaScript).

python
from openai import OpenAI
client = OpenAI(base_url="https://jantaris.com/v1", api_key="sk-jt-...", max_retries=4)

Bezpieczne ponawianie /v1/generate

Każde udane wywołanie /v1/generate tworzy nowe zadanie i blokuje pod nie środki. Jeśli zapytanie przekroczyło czas po twojej stronie i nie wiesz, czy doszło do serwera, nie wysyłaj go w pętli na ślepo. Zapisz sytuację w logach, a jeśli korzystasz z webhooków, poczekaj na doręczenie, zanim uruchomisz duplikat.