--- title: "Historia fraz: spadki (`getLosses`)" source: https://docs.senuto.com/modules/visibility_analysis/va-history-keywords-getLosses api: POST /api/visibility_analysis/reports/history/keywords/getLosses --- # Historia fraz: spadki (`getLosses`) **`POST /api/visibility_analysis/reports/history/keywords/getLosses`** Zwraca frazy, których pozycja **pogorszyła się** między `date_min` a `date_max` (tryb `MODE_DECREASE` tego samego komponentu danych co `getData`). W danych spadek oznacza **dodatni** `statistics.position.diff` — np. przejście z pozycji 2 na 5 daje `diff: 3`. Struktura żądania i odpowiedzi jest identyczna jak w `getData`; zmienia się wyłącznie zestaw zwracanych wierszy. > **Ostrzeżenie:** > **Ta akcja nie zawiera fraz utraconych — i nie jest symetryczna wobec `getWins`.** > > Frazy, które wypadły poza TOP50 na `date_max`, **nie pojawią się tutaj**, mimo że formalnie „spadły". Znajdziesz je wyłącznie w [`getLost`](/modules/visibility_analysis/va-history-keywords-getLost). Ta akcja pokazuje więc wyłącznie ruch **wewnątrz** TOP50: fraza musi rankować zarówno na `date_min`, jak i na `date_max`. > > Siostrzana [`getWins`](/modules/visibility_analysis/va-history-keywords-getWins) działa **odwrotnie** — zawiera też frazy nowo pozyskane. Konsekwencje przy liczeniu: > > - **Pełny obraz strat** = `getLosses` + `getLost`. Zbiory są rozłączne, więc możesz je bezpiecznie skleić. > - **Pełny obraz zysków** = samo `getWins`. Doklejenie `getAcquired` **zdubluje** wiersze. > - Zestawianie `count` z `getWins` i `getLosses` porównuje dwie różnie zdefiniowane wielkości — zyski są zawyżone o pozyskane, straty zaniżone o utracone. > > Zachowanie może się w przyszłości ujednolicić — na dziś traktuj powyższe jako obowiązujący kontrakt. | Fraza | ID frazy | KID | Domena | Liczba słów | Pozycja | Pozycja poprz. | Zmiana pozycji | Wzrosty | Spadki | Bez zmian | Widoczność | Widoczność poprz. | Δ widoczności | Widoczność % | URL bieżący | URL poprzedni | URL zmiana | CPC | Wyszukiwania/mies. | Trend (12 mies.) | Szczyt trendu | Trudność | Snippety SERP | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ochnik | 14897112 | c9dba6c1c694aa2bd10bceab8716e8d7 | zalando.pl | 1 | 5 | 2 | 3 | 0 | 1 | 0 | 22635 | 78840 | -56205 | -0.7129 | zalando.pl/ochnik/ | zalando.pl/ochnik/ | 0 | 0.42 | 450000 | [368000,301000,301000,368000,450000,673000,823000,823000,673000,550000,450000,368000] | | 60 | ["map","people_also_ask","wiki_right"] | | pinko torebka | 11672176 | 9e41576fb002d977104a4c8f9fac9015 | zalando.pl | 2 | 3 | 2 | 1 | 0 | 1 | 0 | 5321.25 | 8672.4 | -3351.15 | -0.3864 | zalando.pl/akcesoria-torby-kobiety/pinko/ | zalando.pl/akcesoria-torby-kobiety/pinko/ | 0 | 0.14 | 49500 | [60500,49500,49500,40500,49500,40500,49500,60500,40500,40500,74000,74000] | | 34 | ["image_thumbs","people_also_ask"] | _zalando.pl, sort: widoczność malejąco — frazy, których pozycja się pogorszyła (dodatni „diff”, ujemna Δ widoczności). Wszystkie pola wiersza (poza mapą historii `statistics.position.history`, która ma zmienne klucze-daty — jest w JSON i sekcji „Struktura odpowiedzi”)._ --- ## Żądanie `POST` `/api/visibility_analysis/reports/history/keywords/getLosses` Nagłówki: `Authorization: Bearer `, `Content-Type: application/json`. ### Struktura żądania **Podstawowy** ```jsonc filename="żądanie-podstawowe.jsonc" { "domain": "zalando.pl", "fetch_mode": "topLevelDomain", "date_min": "2026-06-20", "date_max": "2026-06-29", "country_id": 1, "order": { "prop": "statistics.visibility.current", "dir": "desc" } } ``` **Rozszerzony** ```jsonc filename="żądanie-rozszerzone.jsonc" { "domain": "zalando.pl", "fetch_mode": "topLevelDomain", "date_min": "2026-06-20", "date_max": "2026-06-29", "country_id": 1, "order": { "prop": "statistics.visibility.current", "dir": "desc" }, "limit": 10, "page": 1 } ``` **cURL** ```bash curl --location --request POST 'https://api.senuto.com/api/visibility_analysis/reports/history/keywords/getLosses' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer $YOUR_TOKEN_HERE' \ --data-raw '{ "domain": "zalando.pl", "fetch_mode": "topLevelDomain", "date_min": "2026-06-20", "date_max": "2026-06-29", "country_id": 1, "order": { "prop": "statistics.visibility.current", "dir": "desc" } }' ``` ### Parametry ```ts type HistoryKeywordsGetLossesRequest = { /** * **Wymagane**. Domena, subdomena, katalog lub URL do analizy — interpretowane zgodnie z `fetch_mode`. */ domain: string; /** * **Wymagane**. Sposób interpretacji `domain`. * - `topLevelDomain` — cała domena (najczęstszy przypadek) * - `subdomain` — pojedyncza subdomena * - `catalog` — ścieżka/katalog * - `url` — dokładny URL * * Wartość `domain` nie istnieje. */ fetch_mode: 'topLevelDomain' | 'subdomain' | 'catalog' | 'url'; /** * **Wymagane**. Początek zakresu dat, `YYYY-MM-DD`. Musi być nie późniejszy niż `date_max`. * Dostępne daty pobierzesz akcją `getDates`. */ date_min: string; /** * **Wymagane**. Koniec zakresu dat, `YYYY-MM-DD`. Musi być nie wcześniejszy niż `date_min`. */ date_max: string; /** * **Wymagane**. Id kraju (bazy danych). Polska = `1`. Nieznana wartość → `418` "Unknown country_id". */ country_id: number; /** * **Wymagane**. **Pojedyncza** dyrektywa sortowania (jeden obiekt — nie tablica). * `prop` to jedna z dozwolonych właściwości sortowalnych; `dir` to kierunek. * * Dozwolone wartości `prop`: * - `keyword` * - `statistics.position.current` * - `statistics.position.previous` * - `statistics.position.diff` * - `statistics.visibility.current` * - `statistics.visibility.previous` * - `statistics.visibility.diff` * - `statistics.difficulty.current` * - `statistics.searches.current` * - `statistics.cpc.current` * - `statistics.url.is_change` */ order: { prop: | 'keyword' | 'statistics.position.current' | 'statistics.position.previous' | 'statistics.position.diff' | 'statistics.visibility.current' | 'statistics.visibility.previous' | 'statistics.visibility.diff' | 'statistics.difficulty.current' | 'statistics.searches.current' | 'statistics.cpc.current' | 'statistics.url.is_change'; dir: 'asc' | 'desc'; }; /** * Liczba wierszy na stronę. * @default 10 */ limit?: number; /** * Numer strony. * @default 1 */ page?: number; } export default HistoryKeywordsGetLossesRequest ``` > **Ostrzeżenie:** > **`order` to pojedynczy obiekt** (`{ prop, dir }`) — nie tablica. Błędna wartość `prop` zwraca `418` `invalid_data` z komunikatem (dosłownym): `This value is not allow. Please use correct colum name`. > **Ostrzeżenie:** > Pięć parametrów jest **wymaganych**: **`domain`**, **`fetch_mode`**, **`date_min`**, **`date_max`** oraz **`country_id`**, a także pojedynczy obiekt **`order`**. Wartość `fetch_mode` musi być jedną z `topLevelDomain` / `subdomain` / `catalog` / `url` — wartość `domain` **nie istnieje**. `order` to **pojedynczy obiekt** `{ prop, dir }`, nie tablica. Pominięcie któregokolwiek wymaganego pola zwraca `418` z `invalid_data`; nieznane `country_id` → `418` z komunikatem `Unknown country_id`. ## Filtrowanie Opcjonalny parametr `filtering` (tablica grup filtrów) zawęża wyniki. Endpoint korzysta z **tego samego mechanizmu i tych samych kluczy filtrów** co `positions/getData` oraz `history/keywords/getData` — szczegóły i pełną listę kluczy znajdziesz na stronie [typów filtrów](/types/filter). ## Odpowiedź W przypadku powodzenia otrzymujesz `data` (tablicę wierszy z frazami, których pozycja się pogorszyła) oraz `pagination`. Pozycja `51` to wartość specjalna oznaczająca frazę poza TOP50. **Skrócona** ```json filename="przykładowa-odpowiedź (skrócona)" { "success": true, "data": [ { "keyword_id": 14897112, "keyword": "ochnik", "statistics": { "position": { "current": 5, "previous": 2, "diff": 3 }, "visibility": { "current": 22635 } /* … */ } } ], "pagination": { "page_count": 3004, "current_page": 1, "has_next_page": true, "has_prev_page": false, "count": 6007, "limit": 2 } } ``` **Pełna** ```json filename="przykładowa-odpowiedź (200)" { "success": true, "data": [ { "keyword_id": 14897112, "kid": "c9dba6c1c694aa2bd10bceab8716e8d7", "domain": "zalando.pl", "keyword": "ochnik", "words_count": 1, "statistics": { "position": { "current": 5, "previous": 2, "diff": 3, "changes": { "wins": 0, "losses": 1, "no_changes": 0 }, "history": { "2026-05-17": { "position": 2, "has_serp": true }, "2026-06-21": { "position": 5, "has_serp": true } } }, "visibility": { "current": 22635, "previous": 78840, "diff": -56205, "percent": -0.7129, "history": null }, "url": { "current": "zalando.pl/ochnik/", "previous": "zalando.pl/ochnik/", "is_change": 0 }, "cpc": { "current": 0.42 }, "searches": { "current": 450000 }, "trends": { "history": [368000, 301000, 301000, 368000, 450000, 673000, 823000, 823000, 673000, 550000, 450000, 368000], "peak": null }, "difficulty": { "current": 60 }, "snippets": { "current": ["map", "people_also_ask", "wiki_right"] } } }, { "keyword_id": 11672176, "kid": "9e41576fb002d977104a4c8f9fac9015", "domain": "zalando.pl", "keyword": "pinko torebka", "words_count": 2, "statistics": { "position": { "current": 3, "previous": 2, "diff": 1, "changes": { "wins": 0, "losses": 1, "no_changes": 0 }, "history": { "2026-05-25": { "position": 2, "has_serp": true }, "2026-06-26": { "position": 3, "has_serp": true } } }, "visibility": { "current": 5321.25, "previous": 8672.4, "diff": -3351.15, "percent": -0.3864, "history": null }, "url": { "current": "zalando.pl/akcesoria-torby-kobiety/pinko/", "previous": "zalando.pl/akcesoria-torby-kobiety/pinko/", "is_change": 0 }, "cpc": { "current": 0.14 }, "searches": { "current": 49500 }, "trends": { "history": [60500, 49500, 49500, 40500, 49500, 40500, 49500, 60500, 40500, 40500, 74000, 74000], "peak": null }, "difficulty": { "current": 34 }, "snippets": { "current": ["image_thumbs", "people_also_ask"] } } } ], "pagination": { "page_count": 3004, "current_page": 1, "has_next_page": true, "has_prev_page": false, "count": 6007, "limit": 2 } } ``` ### Struktura odpowiedzi ```ts type HistoryKeywordsGetLossesResponse = { /** `true` przy powodzeniu; przy błędzie `false` i koperta z `error` */ success: boolean; /** Zwrócone wiersze z frazami, których pozycja się pogorszyła */ data: KeywordRow[]; /** Metadane paginacji */ pagination: { page_count: number; current_page: number; has_next_page: boolean; has_prev_page: boolean; count: number; limit: number; }; } type KeywordRow = { keyword_id: number; kid: string; domain: string; keyword: string; words_count: number; statistics: { /** Dla spadków `diff` jest dodatni (np. 2 → 5 daje diff = 3). Wartość 51 oznacza pozycję poza TOP50. */ position: { current: number; previous: number; diff: number; changes: { wins: number; losses: number; no_changes: number }; history: Record }; visibility: { current: number; previous: number; diff: number; percent: number; history: null }; /** `is_change` jest liczbowe: 0 lub 1 */ url: { current: string; previous: string; is_change: 0 | 1 }; cpc: { current: number }; searches: { current: number }; trends: { history: number[]; peak: number | null }; difficulty: { current: number }; snippets: { current: string[] }; }; } export default HistoryKeywordsGetLossesResponse ``` ## Błędy ```ts type ErrorResponse = { success: false; data: { error: { /** np. invalid_data */ type: string; message: string; /** pole -> reguła -> komunikat (dla invalid_data) */ params?: Record>; }; }; } export default ErrorResponse ``` > **Błąd:** > **`418`** zwracany jest również dla błędów walidacji. Brak wymaganego pola → `invalid_data`; nieznane `country_id` → `Unknown country_id`; błędny `order.prop` → `This value is not allow. Please use correct colum name`. > > **Znany błąd — odwrócony komunikat.** Przy `date_min > date_max` komunikat reguły `DateRangeRules` jest odwrócony i brzmi `"date_max must be less or equal than date_min"`. Należy go odczytywać jako niepowodzenie reguły zakresu dat, a nie jako dosłowną instrukcję. ## Powiązane akcje - [`getData`](/modules/visibility_analysis/va-history-keywords) — frazy w zakresie dat (`MODE_DATA`) - [`getWins`](/modules/visibility_analysis/va-history-keywords-getWins) — frazy, które poprawiły pozycje (taka sama struktura żądania) - `getLosses` — frazy, które straciły pozycje (ta strona) - `getAcquired` / `getLost` — frazy nowo pozyskane / całkowicie utracone w zakresie (taka sama struktura żądania) - `getDates` — dostępne daty (POST, wymaga tylko `country_id`)