Fakturnia Developers Szybki start Dokumentacja API English

Kolejka renderowania PDF

GET /documents/{id}/download renderuje PDF faktury po stronie serwera. Renderowanie obciąża procesor, więc działa w niewielkiej puli wątków roboczych z ograniczoną kolejką. Pod dużym obciążeniem kolejka może się zapełnić. Gdy tak się stanie, API nie każe Ci czekać ani nie kończy żądania timeoutem. Odpowiada natychmiast kodem 429 z kodem błędu WAIT_PDF_QUEUE, informując, że należy ponowić zapytanie za chwilę.

To co innego niż limity kwotowe. Oba zwracają 429, ale znaczą co innego:

WAIT_PDF_QUEUE Limit kwotowy
Przyczyna pula renderująca chwilowo wysycona aplikacja przekroczyła swój limit na endpoint
message WAIT_PDF_QUEUE ogólny komunikat o limicie
Czas trwania sekundy (kolejka szybko schodzi) do zresetowania okna limitu
Co robić ponów po Retry-After, bez spowalniania ogólnego tempa wycofaj się, zwolnij, uszanuj cooldown

Rozróżniaj po polu message (kodzie błędu), nigdy po samym statusie HTTP, aby odróżnić te dwa przypadki.

Co otrzymujesz w odpowiedzi

HTTP/1.1 429 Too Many Requests
Retry-After: 5
Content-Type: application/json
{
  "success": false,
  "data": null,
  "message": "WAIT_PDF_QUEUE",
  "executionTime": 2
}

Nagłówek Retry-After zawiera sugerowany czas oczekiwania w sekundach (zwykle 5). Uszanuj go: slot renderujący zwalnia się szybko, a ponowienie niemal zawsze kończy się sukcesem w kolejnym podejściu.

Jak to obsłużyć

Pobieranie to operacja odczytu, więc ponawianie jest zawsze bezpieczne. Nie potrzeba nagłówka Idempotency-Key. Ponawiaj, dopóki kod to WAIT_PDF_QUEUE, czekając między próbami przez czas z Retry-After:

async function downloadInvoicePdf(documentId: string, token: string): Promise<Blob> {
  const url = `https://prod.api.fakturnia.pl/external/v1/documents/${documentId}/download`;

  for (let attempt = 0; attempt < 10; attempt++) {
    const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });

    if (res.ok) return res.blob();

    if (res.status === 429) {
      const body = await res.clone().json().catch(() => null);
      // Przejściowe przeciążenie kolejki renderowania: poczekaj sugerowany czas i ponów.
      if (body?.message === 'WAIT_PDF_QUEUE') {
        const retryAfter = Number(res.headers.get('Retry-After')) || 5;
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        continue;
      }
    }

    // Każdy inny status (w tym kwotowe 429) to realny błąd tego wywołania.
    throw new Error(`Pobieranie nie powiodło się: ${res.status}`);
  }

  throw new Error('PDF wciąż nie jest gotowy po kilku ponowieniach');
}

Pokaż oczekiwanie użytkownikowi. W aplikacji webowej i mobilnej Fakturnia przy WAIT_PDF_QUEUE pojawia się niewielki dialog „przygotowujemy plik”, który ponawia żądanie w tle, aż PDF dotrze. Krótki, uczciwy wskaźnik postępu jest lepszy niż spinner, który wygląda na zawieszony.

Dlaczego kolejka, a nie zwykłe czekanie

Trzymanie otwartego połączenia, dopóki długi render się nie skończy, blokowałoby zasoby serwera i groziło timeoutami po stronie klienta pod obciążeniem. Ograniczona kolejka z szybką informacją zwrotną 429 utrzymuje responsywność API dla wszystkich: reszta API nie zwalnia z powodu serii pobrań w toku, a Twój klient dostaje czytelny, ponawialny sygnał zamiast nieprzejrzystego timeoutu. Zobacz Błędy, aby poznać pełną kopertę błędu, oraz Limity zapytań w sprawie zachowania kwotowego.