Skip to Content
Eksporty i zadania async

Eksporty i zadania asynchroniczne

Trzy różne sposoby wyciągania danych z API — mylenie ich to najczęstsza przyczyna timeoutów przy „dużych pobraniach”.

TrybKiedyCo dostajesz
Raport synchronicznydomyślnie, większość endpointówJSON w odpowiedzi, stronicowany (paginacja)
Zadanie asynchronicznenarzędzia SERP (crawl SERP-a, TOP100, listy URL-i)task_id od razu, dane po zakończeniu zadania
Eksport plikowygdy chcesz plik zamiast JSON-aCSV/plik do pobrania, bez koperty {success, data}

Nie ma ogólnego mechanizmu „zleć raport i odbierz później”. Zwykłe raporty (np. positions/getData, dashboard/getDomainStatistics) liczą się w trakcie żądania — nie zwracają identyfikatora zadania i nie da się ich zakolejkować. Duże pobranie dzielisz paginacją i zakresem dat, a nie zleceniem w tle. Kolejkowanie istnieje wyłącznie w rodzinach tasks/management/* opisanych niżej.

Jak rozpoznać, w którym trybie działa Twój endpoint

Tryb rozpoznasz po ścieżce i wymaganych parametrach:

Sygnał w endpoincieTrybCo to znaczy
ścieżka zaczyna się od /api/tasks/management/…zadanie asynchronicznecreate zwraca task_id, wyniki odbierasz po check
endpoint wymaga task_id w parametrachodbiór wyników zadaniazadanie musi być już zakończone
w ścieżce jest segment exportseksport plikowyodpowiedzią jest plik (CSV), nie JSON
nic z powyższychraport synchronicznydane liczą się w trakcie żądania; brak job ID i brak kolejkowania

Innymi słowy: job ID istnieje wyłącznie w trzech rodzinach tasks/management/* wymienionych niżej. Jeśli Twojego endpointu tam nie ma i nie przyjmuje task_id, to nie da się go „zlecić i odebrać później” — zostaje paginacja, zawężenie zakresu albo eksport plikowy.


1. Duże pobranie z raportu synchronicznego

Gdy raport przerywa się timeoutem (data.error.type = "timeout" — patrz Błędy), zawężaj żądanie, zamiast je ponawiać w tej samej postaci:

  • Stronicuj. limit + page; łączną liczbę wierszy podaje pagination.count, a pagination.has_next_page mówi, kiedy przestać. Maksymalny limit zależy od endpointu (często 100) — wyższa wartość to 418, nie szybsze pobranie.
  • Tnij zakres dat. Raporty historyczne (date_min / date_max) kosztują tym więcej, im szerszy zakres i im większa domena. Miesiąc po miesiącu przechodzi tam, gdzie rok naraz się wywraca.
  • Ogranicz zbiór na wejściu. filtering po stronie API jest tańsze niż pobranie wszystkiego i filtrowanie u siebie.
  • Rozważ eksport plikowy (sekcja 3) — dla tych samych danych zwraca CSV jednym żądaniem, bez składania stron.

Odpowiedź 200 z pustym data: [] to nie timeout ani błąd — dla tej domeny i tego zakresu po prostu nie ma danych. Sprawdź fetch_mode, zakres dat i pisownię domeny.


2. Zadania asynchroniczne (tasks/management/*)

Narzędzia, które muszą najpierw zebrać dane z Google, działają w cyklu createcheck (polling) → odbiór wyników. create zwraca task_id natychmiast; dane pojawiają się dopiero, gdy zadanie się zakończy.

RodzinacreatecheckWyniki
Analiza SERPPOST /api/tasks/management/serp_analysis/createGET …/serp_analysis/checkraporty serp_analysis/reports/*
TOP100 crawlPOST /api/tasks/management/top100_crawl/createGET …/top100_crawl/checktop100_crawl/getData lub eksport CSV
URLs crawlPOST /api/tasks/management/urls_crawl/createGET …/urls_crawl/checkurls_crawl/getList lub eksport CSV

Skąd wiadomo, że zadanie jest gotowe

check przyjmuje task_id w query stringu i zwraca obiekt zadania. Sygnał gotowości różni się między rodzinami — dlatego czytaj konkretne pole, a nie „jakikolwiek status”:

  • Analiza SERPprogress.has_serp_data = true (crawl SERP gotowy) oraz progress.has_keywords_analysis_data = true (dane Bazy słów gotowe). Odpytanie raportu wcześniej zwraca błąd walidacji Unfinished task.
  • TOP100 / URLs crawlstatus = "completed" (świeżo utworzone zadanie ma waiting) oraz progress = {all, finished, unfinished}, po którym widać postęp.

Czas realizacji zależy od rodzaju i wielkości zadania — od minut po godziny. Nie zakładaj stałej wartości: odpytuj check w odstępach (np. co 30–60 s) i przerwij po własnym limicie czasu.

Przechowuj task_id

create zwraca identyfikator tylko raz — zapisz go po swojej stronie. Zadanie nie wygasa: raporty zakończonego zadania odpytasz również następnego dnia, bez tworzenia nowego i bez konsumpcji limitu. Zgubiony task_id oznacza zlecenie analizy od nowa, czyli kolejną jednostkę limitu.

Szkic pętli

polling.py
import time, requests H = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"} BASE = "https://api.senuto.com" # 1. zlecenie zadania — zużywa limit narzędzi (tools_daily_limit) task = requests.post(f"{BASE}/api/tasks/management/top100_crawl/create", headers=H, json={"keywords": ["buty"], "country_id": 1}).json() task_id = task["data"]["id"] # 2. polling — task_id w QUERY STRINGU, nie w ciele deadline = time.time() + 3600 while time.time() < deadline: state = requests.get(f"{BASE}/api/tasks/management/top100_crawl/check", headers=H, params={"task_id": task_id}).json()["data"] if state["status"] == "completed": break time.sleep(60) else: raise TimeoutError(f"zadanie {task_id} nie zdążyło — sprawdź je później przez /list") # 3. odbiór wyników rows = requests.post(f"{BASE}/api/serp_analysis/tools/top100_crawl/getData", headers=H, json={"task_id": task_id, "limit": 100, "page": 1}).json()

create zużywa limitserp_analysis_daily_limit dla Analizy SERP, tools_daily_limit (plus limit wejściowy narzędzia) dla crawlów. check, list i odczyt wyników limitu nie zużywają, więc polling jest bezpieczny — podobnie jak ponowienie create po timeoucie (Ponowienia po timeoucie). Stan liczników: GET /api/users/getLimits.


3. Eksporty plikowe (CSV)

Endpointy z segmentem exports zwracają plik, nie kopertę JSON — nie mają playgroundu i nie parsuj ich jak zwykłej odpowiedzi. Przydają się tam, gdzie alternatywą jest przejście przez kilkadziesiąt stron paginacji.

ModułEndpointZawartość
Analiza SERPPOST /api/serp_analysis/tools/exports/top100_crawl/getDatawyniki zadania TOP100 crawl
Analiza SERPPOST /api/serp_analysis/tools/exports/urls_crawl/getListwyniki zadania URLs crawl
Baza słów kluczowychPOST /api/keywords_analysis/tools/exports/statistics/getKeywordsfrazy z raportu statystyk

Eksporty narzędziowe (tools/exports/*) zużywają tools_daily_limit — tak samo jak wywołanie samego narzędzia. Powtórzenie tego samego eksportu w ciągu 24 h już nie nalicza kolejnej jednostki (patrz Ponowienia po timeoucie), ale eksport z innym zestawem parametrów to nowa jednostka.


Ponowienia po timeoucie

Timeout po stronie klienta nie mówi, czy operacja wykonała się po stronie Senuto. Nie ma nagłówka Idempotency-Key — i nie jest potrzebny, bo każdy z trzech trybów ma własny sposób bezpiecznego ponowienia. Wybierz właściwy dla swojego endpointu:

TrybJak sprawdzić, czy operacja przeszłaCzy ponowienie kosztuje
Raport synchronicznyusage w GET /api/users/getLimits; dla domeny w Analizie widoczności — checkQueryNie — identyczne zapytanie w oknie 24 h trafia w Grace Window (szczegóły)
Zadanie async (tasks/management/*)…/list — zwraca wszystkie zadania konta z ich task_id i statusamiAnaliza SERP: nie (create zwraca istniejące zadanie dla tej samej frazy i kraju). Crawle: powstanie nowe zadanie, ale tools_daily_limit nie naliczy się drugi raz dla identycznego payloadu w 24 h
Narzędzie z public_id (KA statistics/create)brak listy — public_id odzyskasz tylko z odpowiedzi, checkData sprawdza znany public_idNie dla identycznego payloadu w oknie 24 h, ale wynik dostaniesz pod nowym public_id
Eksport plikowybrak — to zwykłe pobranie plikuNie dla powtórzenia tego samego eksportu w 24 h

Zasady, które warto zaszyć w kliencie:

  • Retry wysyłaj bajt w bajt. Klucz Grace Window liczy się z parametrów żądania, więc zmieniona kolejność fraz w keywords albo dorzucony opcjonalny parametr tworzy nową jednostkę limitu.
  • Zanim ponowisz create zadania — zajrzyj do list. To najtańszy sposób ustalenia, czy zadanie już istnieje, i jedyny sposób odzyskania zgubionego task_id.
  • public_id zapisuj natychmiast po odebraniu odpowiedzi. Jest generowany losowo i nie ma endpointu, który wylistuje wyniki narzędzi konta — utracony public_id oznacza ponowne wywołanie create (kosztowo bezpieczne w oknie 24 h, ale wynik dostaniesz pod nowym identyfikatorem).
  • Podnieś timeout, zamiast ponawiać agresywnie. Ciężkie wywołania (create z kilkuset frazami, szerokie raporty historyczne) potrafią liczyć się minutami — ustaw timeout klienta rzędu 120 s.
  • Dwie operacje naliczają się przy każdym wywołaniu i nie mają Grace Window: refresh w Analizie SERP oraz ręczne odświeżanie pozycji w Monitoringu. Tutaj retry realnie kosztuje.

Co dalej

  • Paginacjalimit, page i pole pagination.
  • Limity zapytań — które liczniki zużywają zadania i eksporty.
  • Błędytimeout, 418 i pozostałe kategorie.
  • Analiza SERP — pełny opis rodzin zadań i raportów.
Ostatnia aktualizacja: