Skip to Content
TypyBłędy

Błędy

Gdy żądanie się nie powiedzie, API zwraca kopertę z success: false i obiektem error. Struktura jest spójna w całym API.

Koperta błędu

NameTypeDefault
successfalse

Zawsze false dla odpowiedzi błędnej

data{ error: { type: string; message: string; params?: Record<string, Record<string, string>>; }; }

Status HTTP 418 — najważniejsze

Status 418 to w tym API generyczny błąd walidacji żądania, a nie wyłącznie przekroczenie limitu zapytań. Zdecydowana większość 418 to type: "invalid_data" — brakujące lub nieprawidłowe pole. Sprawdzaj data.error.type i data.error.params, zanim uznasz błąd za rate limit.

Typowe 418 (invalid_data) — brak wymaganego pola:

brak fetch_mode
{ "success": false, "data": { "error": { "type": "invalid_data", "message": "Given data is invalid, please check the documentation or contact Administrator", "params": { "fetch_mode": { "_required": "This field is required" } } } } }

Status HTTP 404 — trzy różne przyczyny

404 w tym API nie oznacza po prostu „zły adres”. Rozróżnisz przypadki po tym, co przyszło w treści:

Treść odpowiedziZnaczenieCo zrobić
{"success": false, "message": ""}Trasa nie istnieje albo żądanie jest nieuwierzytelnione (wtedy poprzedza je 302 na …/users/login)Sprawdź pisownię ścieżki (niżej), a potem token
Strona HTML z nagłówkiem „Error / Not Found”Trasa istnieje, ale wskazany zasób nie — albo akcja w ogóle nie dostała identyfikatoraSprawdź, czy parametr idzie tam, gdzie trzeba (query string vs ciało) i czy zasób należy do Twojego konta

Nieważny lub brakujący token daje 302, a po przekierowaniu 404 — nie 401. Żądanie bez nagłówka Authorization oraz z tokenem po terminie ważności dostaje 302 z nagłówkiem Location na /api/<moduł>/users/login, a pod tym adresem czeka 404 {"success": false, "message": ""} — dokładnie to samo, co po literówce w ścieżce. Klient podążający za przekierowaniami (curl -L, requests, axios) pokaże 404; Postman z wyłączonym podążaniem zatrzyma się na 302. Zanim zaczniesz debugować ścieżkę, pobierz świeży token (patrz Autoryzacja). Komunikat jest pusty celowo, produkcyjne API nie ujawnia szczegółów wyjątku.

Konwencja adresów — najczęstsza przyczyna 404

Ścieżka ma postać /api/<moduł>/<sekcja>/<kontroler>/<akcja>, przy czym człony i akcja rządzą się różnymi regułami:

  • Moduł, sekcja i kontroler: snake_casevisibility_analysis, ai_overviews, serp_analysis.
  • Akcja: camelCasegetDomainStatistics, getKeywordHistory. Zamiana akcji na snake_case albo kebab-case daje 404, mimo że endpoint istnieje.
  • Myślnik zamiast podkreślenia w module (visibility-analysis) też kończy się 404.
  • Pominięty człon sekcji (/api/visibility_analysis/dashboard/… zamiast …/reports/dashboard/…) — 404.
ta sama akcja, cztery adresy
/api/visibility_analysis/reports/dashboard/getDomainStatistics → 200 /api/visibility_analysis/reports/dashboard/get_domain_statistics → 404 akcja w snake_case /api/visibility-analysis/reports/dashboard/getDomainStatistics → 404 myślnik w module /api/visibility_analysis/dashboard/getDomainStatistics → 404 brak członu "reports"

Sama wielkość liter w nazwie akcji akurat nie ma znaczenia (getdomainstatistics też odpowie 200) — decyduje brak separatorów. Nie opieraj się jednak na tym: trzymaj się pisowni podanej na stronie endpointu.

Kategorie błędów (type)

typeZnaczenieCzęsta przyczyna
invalid_dataŻądanie nie przeszło walidacjiBrak wymaganego pola, zła wartość (np. nieznany fetch_mode, country_id, aggregation_type)
invalid_filteringNieprawidłowy parametr filteringKlucz filtra nieobsługiwany przez ten endpoint
unauthorized / Unauthorized accessBrak dostępu do zasobuCudzy lub nieistniejący project_id / group_id / keyword_id
unreachable_dataDane chwilowo niedostępneProblem po stronie źródła danych
timeoutPrzekroczono czas przetwarzaniaBardzo szeroki zakres / duża domena
databaseBłąd warstwy danychBywa zwracany także jako HTTP 500 z surową stroną HTML (patrz niżej)

Częste pułapki

Cudzy/nieistniejący zasób → 418 Unauthorized access, nie 404. Podanie project_id lub group_id spoza konta zwraca błąd walidacji dostępu, a nie „nie znaleziono”. Konto administratora (role_id = 1) omija część kontroli dostępu.

Zła metoda HTTP. Część akcji akceptuje wyłącznie GET (parametry w query stringu) — wysłanie ich metodą POST w ciele JSON zwraca 405 (Method Not Allowed) albo 418, bo walidator widzi puste pola. Metoda jest podana na stronie każdego endpointu.

Konto bez dostępu do API → 403, nie 418. Ważny token na koncie bez aktywnego planu albo bez dodatku Dostęp do API daje 403 {"success": false, "message": ""}. Treść jest pusta, więc ten przypadek rozpoznajesz po samym statusie (patrz Dostęp do API).

HTTP 500 z surową stroną HTML. Niektóre endpointy zwracają obecnie nieobsłużony wyjątek (500, treść to strona HTML, nie JSON) niezależnie od poprawności żądania — to znane usterki backendu, nie błąd Twojej integracji. Buduj klienta odpornie: gdy odpowiedź nie jest JSON-em, potraktuj ją jako błąd serwera.

Odwrócony komunikat zakresu dat. W części raportów przy date_min > date_max komunikat błędu bywa odwrócony (mówi o date_max, choć problem dotyczy date_min). Waliduj kolejność dat po swojej stronie.

Odpowiedź 200, ale dane są puste lub zerowe

To nie jest błąd — żądanie przeszło walidację, tylko dla podanych kryteriów nie ma danych. Kolejność sprawdzania, od najczęstszej przyczyny:

  1. Zły fetch_mode. Host z subdomeną (blog.example.com) w trybie topLevelDomain liczy wyłącznie frazy, na których rankuje ten konkretny host — a tych zwykle nie ma. Zwalidowane: blog.senuto.com w topLevelDomain zwraca 0, a w subdomain — 316 fraz w TOP10. Patrz fetch_mode.
  2. Domena spoza indeksu. Senuto liczy widoczność na własnym zbiorze fraz per rynek. Domena, która nie rankuje w TOP50 na żadną frazę z bazy, zwróci zera — tak samo jak domena nieistniejąca (sprawdzone: dla wymyślonej domeny raport dashboardu odpowiada 200 z samymi zerami, nie błędem).
  3. Zły rynek (country_id). Bez tego pola raporty liczą na bazie domyślnej (Polska 1.0). Domena czeska sprawdzana na polskiej bazie da zera. Część danych istnieje wyłącznie w bazie PL 2.0 (country_id: 200) — np. raport intencji AI Overviews na country_id: 1 zwraca pustą tablicę dla każdej domeny.
  4. Zakres dat sprzed pojawienia się domeny w bazie — raporty historyczne zwrócą pustą serię dla okresu, w którym nie było jeszcze pomiarów.
  5. filtering odcina wszystko. Filtr niepasujący do żadnego wiersza daje pustą tablicę, a nie błąd — sprawdź go, usuwając filtry po kolei.

Rozróżnienie, które warto zaszyć w kliencie: data: [] (albo same zera) = brak danych dla kryteriów, success: false = odrzucone żądanie. Pierwsze nie jest powodem do retry — powtórzone da to samo.

418 w trakcie długiego pobierania albo w pętli

Typowy zgłaszany scenariusz: integracja (n8n, Make, własny skrypt) pobiera dane od kilku minut i nagle zaczyna dostawać 418, choć te same żądania wcześniej działały. Prawdziwe przyczyny, w kolejności:

  • Wyczerpany limit dobowy. Najczęstsza. Komunikat wygląda tak: You have reached daily limit of queries. Daily limit value is N. Limity są per konto, nie per token, więc pętla w integracji rywalizuje o ten sam licznik co praca w aplikacji. Stan sprawdzisz przez GET /api/users/getLimits — ten odczyt nic nie zużywa.
  • Zmienna w pętli, która czasem jest pusta. Iterując po liście domen czy fraz łatwo trafić na wiersz z pustą wartością — walidator zwróci 418 z params wskazującym pole. Zaloguj data.error.params, a znajdziesz sprawcę w jednym kroku.
  • Zasób spoza konta. project_id albo group_id innego użytkownika daje 418 Unauthorized access (a nie 404), co w pętli po projektach wygląda jak losowa awaria.

Nie myl tego z wygaśnięciem tokenu — token po terminie ważności daje 302 na …/users/login, a po przekierowaniu 404 z pustym message, nie 418. Jeśli integracja działała miesiąc i nagle „wszystkie endpointy zniknęły”, to token (patrz Status HTTP 404).

Klienci HTTP i platformy no-code często opakowują treść błędu we własny komunikat (np. n8n pokazuje „Your request is invalid”). Zawsze zaglądaj do surowego ciała odpowiedzi — data.error.type i data.error.params mówią, co naprawdę odrzucono.

500 / 503 — awaria czy mój błąd?

ObjawNajpewniejCo zrobić
500 na jednym endpoincie, inne działająznana usterka tego endpointu (patrz wyżej)zgłoś do supportu, obejdź innym raportem
500/503 na wszystkich endpointach, także GET /api/users/whoamiawaria po stronie APIponów z backoffem, potem zgłoś
418/404/302 na wszystkichto nie awaria — patrz sekcje wyżej (limit, token)sprawdź token i limity

Najprostszy test rozstrzygający: wywołaj GET /api/users/whoami. To najlżejszy endpoint w API — jeśli on odpowiada 200, backend żyje i problem jest w konkretnym żądaniu.

Bieżące informacje o awariach i pracach serwisowych publikujemy na komunikat.senuto.com (strona tymczasowa) — zajrzyj tam, zanim zaczniesz debugować własny kod.

Przy masowych 5xx ponawiaj z wykładniczym backoffem (np. 1 s, 2 s, 4 s, 8 s… do kilku minut), a nie w pętli co sekundę. Gdy po kilkunastu minutach nic się nie zmienia, zgłoś do supportu i podaj: pełny URL żądania, metodę, czas z dokładnością do minuty (ze strefą), ciało żądania bez tokenu oraz surową odpowiedź z nagłówkami. Z tym zestawem sprawa idzie od razu do zespołu API zamiast wracać z prośbą o szczegóły.

Obsługa po stronie klienta — wzorzec

obsługa błędu (pseudokod)
// odpowiedź = wyślij żądanie // jeśli odpowiedź nie jest JSON-em → błąd serwera (np. 500 HTML) // w przeciwnym razie: // jeśli odpowiedź.success == false: // switch (odpowiedź.data.error.type): // "invalid_data" → popraw pola z error.params (mapa pole → reguła) // "invalid_filtering"→ sprawdź klucze filtra dla tego endpointu // "unauthorized" → sprawdź dostęp do project_id / zasobu // "timeout" → zawęź zakres i ponów // inne → potraktuj jak błąd tymczasowy / zgłoś
Ostatnia aktualizacja: