# HeadHunter API (hh.ru): GET /vacancies — Поиск по вакансиям

Неизвестные параметры игнорируются. Без токена после первого запроса может потребоваться капча. Глубина выдачи — не больше 2000 (`per_page=10&page=199` можно, `page=200` — ошибка). Параметры, где указано «можно несколько», передаются как `key=value&key=value`.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `text` | query | string | нет | Поисковая фраза (поддерживается язык запросов) |
| `search_field` | query | string | нет | Область поиска из vacancy_search_fields в /dictionaries; можно несколько |
| `area` | query | string | нет | Регион из /areas; можно несколько |
| `metro` | query | string | нет | Ветка или станция метро из /metro; можно несколько |
| `professional_role` | query | string | нет | Профессиональная роль из /professional_roles |
| `industry` | query | string | нет | Индустрия компании из /industries; можно несколько |
| `employer_id` | query | string | нет | Работодатель; можно несколько |
| `experience` | query | string | нет | Опыт из experience в /dictionaries; можно несколько |
| `employment_form` | query | string | нет | Тип занятости из vacancy_search_employment_form; можно несколько |
| `work_format` | query | string | нет | Формат работы из work_format; можно несколько |
| `work_schedule_by_days` | query | string | нет | График работы; можно несколько |
| `working_hours` | query | string | нет | Рабочие часы в день; можно несколько |
| `salary` | query | number | нет | Размер зарплаты; валюта по умолчанию RUR |
| `currency` | query | string | нет | Код валюты из currency в /dictionaries (только вместе с salary) |
| `label` | query | string | нет | Метки вакансий из vacancy_label (например, with_salary); можно несколько |
| `excluded_text` | query | string | нет | Исключить вакансии с этими словами (через запятую) |
| `education` | query | string | нет | not_required_or_not_specified, special_secondary, higher |
| `period` | query | number | нет | Поиск за последние N дней |
| `date_from` | query | string | нет | Нижняя граница даты публикации (ISO 8601); нельзя вместе с period |
| `date_to` | query | string | нет | Верхняя граница даты публикации; нельзя вместе с period |
| `top_lat` | query | number | нет | Верхняя граница широты (передавать все четыре гео-параметра) |
| `bottom_lat` | query | number | нет | Нижняя граница широты |
| `left_lng` | query | number | нет | Левая граница долготы |
| `right_lng` | query | number | нет | Правая граница долготы |
| `order_by` | query | string | нет | Сортировка из vacancy_search_order; для distance нужны sort_point_lat, sort_point_lng |
| `clusters` | query | boolean | нет | Вернуть кластеры поиска (по умолчанию false) |
| `describe_arguments` | query | boolean | нет | Вернуть описание применённых параметров (arguments) |
| `no_magic` | query | boolean | нет | Отключить автоматическое преобразование текстового запроса в параметры |
| `responses_count_enabled` | query | boolean | нет | Добавить поле counters с числом откликов |
| `page` | query | number | нет | Номер страницы, по умолчанию 0 |
| `per_page` | query | number | нет | Элементов на странице, по умолчанию 10, максимум 100 |

## Базовые URL

- Боевой: `https://api.hh.ru`
- Запросы ко всем сайтам группы идут на один адрес; нужный сайт задаётся параметром  (по умолчанию ), локаль: `?host=`

## Авторизация

Тип: OAuth 2.0

OAuth 2.0. Токен передаётся в заголовке `Authorization: Bearer {ACCESS_TOKEN}`.

- Токен пользователя (authorization code): пользователь открывает `https://hh.ru/oauth/authorize?response_type=code&client_id={client_id}&state={state}&redirect_uri={redirect_uri}`, затем `authorization_code` из редиректа обменивается на `access_token` и `refresh_token` запросом `POST https://api.hh.ru/token`. Поддерживается PKCE (`code_challenge`, `code_challenge_method=S256`).
- Обновление: `POST https://api.hh.ru/token` с `refresh_token`; refresh-токен одноразовый и работает только после истечения `access_token` (срок — `expires_in`, в секундах).
- Токен приложения (client credentials): срок жизни не ограничен, при повторном запросе прежний отзывается; запрашивать не чаще раза в 5 минут. Актуальный токен виден владельцу на `https://dev.hh.ru/admin`.

Параметры `/oauth/authorize`: `skip_choose_account=true` — не показывать выбор аккаунта, `force_login=true` — всегда показывать форму входа, `role` (`applicant` или `employer`) с `force_role=true` — требовать нужную роль.

В каждом запросе обязателен заголовок `User-Agent` или `HH-User-Agent` (при обоих учитывается `HH-User-Agent`); без него — `400 Bad Request`.

```
User-Agent: MyApp/1.0 (my-app-feedback@example.com)
```

## Нюансы

- Пагинация: `page=N&per_page=M`, нумерация с нуля; ответ — `found`, `per_page`, `pages`, `page`, `items`.
- Неизвестные и недокументированные параметры игнорируются; недокументированные поля в ответах не рекомендуется использовать.
- Длинные ответы сжимаются gzip.
- Поддерживается CORS; для отладки есть `/cors` (HEAD, GET, POST, PUT, DELETE), для JSONP — `?callback=callback_name`.
- Вебхуки: на одно приложение — один URL. Ваш сервер отвечает `2xx` или `409` для дубликата (определяется по `id`). Без ответа за 5 секунд колбэк отправляется повторно; доставка не гарантирована. При долгих сбоях подписка блокируется, при отзыве доступа удаляется.
- Методы `/negotiations/{nid}/messages` устарели — переписка ведётся через `/common/chats`.
- Просмотр резюме с контактами списывает контакт один раз на компанию; если контакты скрыты соискателем, просмотр всё равно спишется — проверяйте `hidden_fields`.

## Сценарии с этим методом

- [Найти вакансии по запросу](https://mcp-everything.ru/integrations/hh-api/scenarios/nayti-vakansii-po-zaprosu.md)

---

Если этого недостаточно — официальная документация: https://api.hh.ru/openapi/redoc
Вся интеграция одним документом: https://mcp-everything.ru/integrations/hh-api.md
