# Obsługa błędów

> Sprawdź format odpowiedzi z błędem, wszystkie kody i zasady ponawiania requestów.

Canonical: https://transcript1.com/pl/docs/errors
Language: pl
Last updated: 2026-11-05

API może odrzucić request od razu albo przyjąć transkrypcję, która później się nie uda. To dwa różne przypadki. W drugim z nich pole `status` transkrypcji ma wartość `failed`.

## Jak wygląda odpowiedź z błędem

Endpointy `/v1` zwracają błędy requestów w takim formacie:

```json
{
  "error": {
    "code": "insufficient_minutes",
    "message": "Not enough minutes",
    "retryable": false,
    "action_url": "https://transcript1.com/dashboard/billing",
    "minutes_needed": 20,
    "minutes_remaining": 3
  }
}
```

Logikę obsługi błędów oprzyj na `code`. Treść `message` pokazuj użytkownikowi, ale nie uzależniaj od niej działania aplikacji, bo może się zmienić. Jeśli `retryable` ma wartość `true`, ten sam request ma szansę udać się później.

Zależnie od błędu obok `retryable` mogą pojawić się dodatkowe pola:

| Pole | Kiedy je dostaniesz | Co zawiera |
|---|---|---|
| `action_url` | `insufficient_minutes`, `no_active_plan`, `topup_needs_user` | Link do zakupu planu lub doładowania. |
| `minutes_needed`, `minutes_remaining` | `insufficient_minutes` | Liczbę minut potrzebnych do transkrypcji (`null`, jeśli jeszcze jej nie znamy) oraz dostępną pulę minut. |
| `reason`, `packs` | `topup_needs_user` | Powód, dla którego karta nie została obciążona, i liczbę zamówionych pakietów. |
| `supported_platforms` | `unsupported_platform` | Listę obsługiwanych platform: `["youtube", "x", "tiktok", "instagram", "facebook", "bluesky", "twitch", "dailymotion", "pinterest", "linkedin", "snapchat"]`. |
| `missing_chunks` | `upload_incomplete` | Indeksy części pliku, których brakuje na serwerze. |
| `max_bytes` | `media_too_large` | Twój limit rozmiaru pliku w bajtach. |
| `params` | `invalid_request` | Przy błędach walidacji body i query: obiekt, którego klucze wskazują pola, a wartości opisują, co trzeba poprawić. |

## Gdy API odrzuci request

| Kod HTTP | `code` | Ponowić bez zmian? | Co sprawdzić |
|---|---|---|---|
| 400, 422 | `invalid_request` | Nie | Brakuje pola lub parametru, ma on błędną wartość albo body nie jest poprawnym JSON-em. Niedozwolone połączenia opcji to m.in. `diarize` z `source: "captions"` i `reuse_recent` z `webhook_url`. |
| 422 | `invalid_url` | Nie | Link musi prowadzić do nagrania z YouTube, X, TikToka, Instagrama, Facebooka, Bluesky lub innej platformy z [listy obsługiwanych linków](https://transcript1.com/pl/docs/sources-and-options). Sprawdź też, czy `platform` zgadza się z linkiem. |
| 422 | `unsupported_platform` | Nie | Wartość `platform` nie znajduje się na liście obsługiwanych platform. |
| 422 | `unsupported_media` | Nie | Rozszerzenie wysłanego pliku nie jest obsługiwane. |
| 401 | `unauthorized` | Nie | Brakuje danych uwierzytelniających albo są one błędne, wygasły lub je unieważniono. Ten kod oznacza też błędny lub wygasły token uploadu. |
| 403 | `insufficient_scope` | Nie | Tokenowi OAuth brakuje uprawnienia `transcriptions:read` lub `transcriptions:write`. |
| 403 | `email_not_verified` | Nie | Najpierw potwierdź e-mail, potem zleć transkrypcję lub utwórz sesję na żywo. |
| 402 | `insufficient_minutes` | Nie | Masz 0 minut lub za mało na tę transkrypcję, a w sesji na żywo mniej niż jedną rozpoczętą minutę. Jeśli [automatyczne doładowanie](https://transcript1.com/pl/docs/billing-and-limits#auto-top-up) jest włączone, transcript1 najpierw próbuje doładować konto. Kup minuty przez `action_url` albo pozwól agentowi kupić je przez `POST /v1/topups` lub narzędzie MCP `top_up`. |
| 402 | `no_active_plan` | Nie | Doładowanie wymaga aktywnego płatnego planu. Ten błąd zwracają `POST /v1/topups` i endpointy rozliczeń w panelu, nie endpointy transkrypcji. |
| 402 | `topup_needs_user` | Tylko przy `pending` i `in_progress` | `POST /v1/topups` nie obciążył karty. `reason` podaje powód: `not_allowed` (te dane uwierzytelniające nie mogą kupować doładowań albo ich użytkownik nie jest adminem zespołu), `cap_reached` (miesięczny limit dla agentów nie ma już wolnej kwoty), `card_declined`, `authentication_required` lub `no_card`. Użytkownik może kupić pakiety przez `action_url`. Przy `pending` (płatność nie jest jeszcze potwierdzona) i `in_progress` (trwa inne doładowanie) płatność może jeszcze przejść: spróbuj później z tym samym `Idempotency-Key`, zamiast odsyłać użytkownika do zakupu. |
| 404 | `not_found` | Nie | Nie ma takiej transkrypcji lub należy ona do innego zespołu. |
| 409 | `upload_incomplete` | Nie | Doślij brakujące części pliku i jeszcze raz zakończ upload. |
| 409 | `invalid_state` | Nie | Transkrypcja nie czeka na upload. Nie możesz już dosyłać części ani kończyć uploadu. |
| 409 | `session_ended` | Nie | Sesja na żywo już się zakończyła, więc `POST /v1/live/sessions/:id/token` nie wystawi tokena. Wysyłany też jako zdarzenie `error` na WebSocket. |
| 422 | `unsupported_language` | Nie | `language` sesji na żywo nie jest obsługiwany. |
| 422 | `unsupported_translation` | Nie | Język `translate_to` sesji na żywo nie jest obsługiwany albo tłumaczenie na żywo jest niedostępne. |
| 409 | `idempotency_conflict` | Nie | Pod tym `Idempotency-Key` wysłano już request z innymi parametrami. |
| 413 | `media_too_large` | Nie | Przekroczono limit rozmiaru pliku. Sprawdź [zasady wysyłania plików](https://transcript1.com/pl/docs/uploads). |
| 413 | `invalid_request` | Nie | JSON w body przekracza 1 MB. Dla zbyt dużych plików kodem błędu jest `media_too_large`. |
| 429 | `rate_limited` | Tak | Przekraczasz liczbę requestów na minutę. Odczekaj tyle sekund, ile wskazuje `Retry-After`. |
| 429 | `too_many_active_jobs` | Tak | Masz za dużo trwających transkrypcji lub otwartych uploadów. Odczekaj tyle sekund, ile wskazuje `Retry-After`. |
| 429 | `too_many_live_sessions` | Tak | Wszystkie równoczesne sesje na żywo z twojego planu są w użyciu. Poczekaj `Retry-After` sekund (30). |
| 500 | `internal_error` | Tak | Błąd po naszej stronie. Odczekaj chwilę i spróbuj ponownie. |
| 503 | `service_unavailable` | Tak | API transcript1 jest chwilowo niedostępne. Ponów request za chwilę. |
| 503 | `live_capacity` | Tak | Cała pojemność transkrypcji na żywo jest zajęta. Poczekaj `Retry-After` sekund (30) i utwórz sesję ponownie. |
| 503 | `live_unavailable` | Nie | Transkrypcja na żywo jest teraz niedostępna. |

Jeśli przeglądarka używa cookie logowania zamiast tokenu bearer, sprawdzamy też origin. Request z innej strony dostanie `403 forbidden_origin`. To sprawdzanie nie dotyczy wywołań API z nagłówkiem `Authorization`.

Przy każdej odpowiedzi `429` nagłówek `Retry-After` podaje czas oczekiwania w sekundach. Konkretne limity znajdziesz w [dokumentacji rozliczeń i limitów](https://transcript1.com/pl/docs/billing-and-limits).

## Kiedy powtórzyć request

- Ponów request bez zmian tylko jeśli `retryable` ma wartość `true`. Dotyczy to `rate_limited`, `too_many_active_jobs`, `too_many_live_sessions`, `live_capacity`, `internal_error`, `service_unavailable` oraz `topup_needs_user` z `reason` równym `pending` lub `in_progress`. Jeśli jest nagłówek `Retry-After`, odczekaj wskazany czas. Jeśli go nie ma, wydłużaj przerwy między próbami.
- Przy ponawianiu `POST /v1/transcriptions` lub `POST /v1/topups` zachowaj ten sam `Idempotency-Key`. Dzięki temu nie zapłacisz drugi raz, jeśli pierwsza próba jednak się udała.
- Przy pozostałych kodach najpierw popraw request, dopiero potem wyślij go ponownie.

## Transkrypcja na żywo

`POST /v1/live/sessions` i pozostałe endpointy live używają tej samej koperty błędu. Obowiązują je też `invalid_request`, `unsupported_language`, `insufficient_minutes` i `email_not_verified`, razem z kodami live z tabeli powyżej. Tworzenie sesji nie jest idempotentne, więc ponowienie po `too_many_live_sessions` lub `live_capacity` tworzy nową sesję.

Gdy sesja już istnieje, problemy docierają przez WebSocket jako zdarzenia `error` i kody zamknięcia, a nie jako błędy HTTP. Wszystkie zdarzenia opisuje strona [Transkrypcja na żywo](https://transcript1.com/pl/docs/live#websocket-protocol).

| Kod zamknięcia | Znaczenie |
|---|---|
| `1000` | Normalne zamknięcie, po `session.ended`. |
| `1011` | Nieoczekiwany błąd serwera. Wznów sesję z nowym tokenem. |
| `1012` | Restart serwera, po `reconnect`. Wznów sesję z nowym tokenem. |
| `4001` | Nieprawidłowy, wygasły albo już użyty token. |
| `4004` | Nie znaleziono sesji albo już się zakończyła. |
| `4008` | Naruszenie protokołu: ramka audio o nieparzystej długości albo zbyt duża. |
| `4010` | Zastąpione nowszym połączeniem z tą samą sesją. |

Sesja na żywo, która kończy się z powodu takiego jak `balance_exhausted` lub `idle_timeout`, nie jest błędem: wysyła `session.ended` z powodem zakończenia i zostaje zapisana. Zobacz [Powody zakończenia](https://transcript1.com/pl/docs/live#end-reasons).

## Gdy transkrypcja się nie uda

Błąd może pojawić się już po odpowiedzi API. Jeśli `status` zmieni się na `failed`, w obiekcie transkrypcji znajdziesz `error: { "code", "message" }`. Sprawdzaj pole `error` podczas odpytywania API lub w [webhooku](https://transcript1.com/pl/docs/webhooks) `transcription.failed`. Gdy tłumaczenie się nie powiedzie, wysyłany jest webhook `transcription.translation.failed`, a transkrypcja nigdy przez to nie kończy się błędem.

| `error.code` | Co się stało | Czy próbować ponownie? |
|---|---|---|
| `media_unavailable` | Nagranie nie istnieje lub nie da się już do niego dotrzeć. | Nie. Sprawdź link. |
| `media_private` | Nagranie jest prywatne. | Nie. Podaj publiczny post albo nagranie z YouTube o widoczności publicznej lub niepublicznej (unlisted). |
| `login_required` | Bez logowania platforma nie udostępni nagrania. | Nie. Traktujemy ten błąd jako trwały i nie ponawiamy transkrypcji. |
| `no_audio` | W filmie nie ma ścieżki audio. | Nie. Traktujemy ten błąd jako trwały i nie ponawiamy transkrypcji. |
| `age_restricted` | Nagranie ma ograniczenie wiekowe. | Nie. Zamiast linku wyślij plik. |
| `live_stream` | Transmisja jeszcze trwa lub dopiero ma się zacząć. | Poczekaj, aż transmisja się skończy. |
| `no_captions` | Wybrano `source` o wartości `captions`, ale nie ma napisów, z których można skorzystać. | Zmień ustawienie na `source: "auto"` lub `"stt"`. |
| `media_too_long` | Nagranie przekracza limit 5 godzin dla transkrypcji AI. | Nie. Najpierw podziel nagranie. |
| `unsupported_media` | Pliku nie da się odczytać lub brakuje w nim ścieżki audio. | Nie. Wyślij plik w obsługiwanym formacie. |
| `no_speech` | Nie wykryto mowy. | Nie. |
| `unsupported_language` | Nie obsługujemy języka tego nagrania. | Nie. Podaj obsługiwany kod w `language` lub ustaw `"auto"`. |
| `insufficient_minutes` | Zabrakło minut w momencie rozliczania transkrypcji, a automatyczne doładowanie, jeśli było włączone, nie zdołało ich dodać. | Tak, gdy doładujesz minuty. |
| `fetch_failed` | Mimo kilku prób nie udało się pobrać nagrania. | Tak, spróbuj później. |
| `transcription_failed` | Transkrypcja AI nie powiodła się mimo kilku prób. | Tak, spróbuj później. |

Jeśli transkrypcja się nie uda albo ją anulujesz, nic nie płacisz. Jeśli zdążyliśmy pobrać minuty, zwrócimy je na konto.
