HeadHunter API (hh.ru): Опубликовать вакансию от имени работодателя

Сценарий из mcp-everything. Актуально на 2026-10-24.

Размещать вакансии из своей ATS или карьерного сайта сразу на hh.ru.

  1. Зарегистрируй приложение на dev.hh.ru. Отправь менеджера работодателя на https://hh.ru/oauth/authorize с response_type = code, client_id и redirect_uri.
  2. Обменяй код на токены: POST /token с grant_type = authorization_code, client_id, client_secret, code и redirect_uri (тело — form-urlencoded). Обновить пару — тот же метод с refresh_token, но только после истечения access_token.
  3. Узнай ID работодателя: GET /me — поле employer.id.
  4. Опубликуй: POST /vacancies с name, description (HTML), area, professional_roles и при необходимости salary_range, experience, work_format, key_skills. Ответ 201. Услуги списываются с пакета работодателя; все вакансии проходят модерацию и появляются в поиске через несколько минут.
  5. Изменить вакансию — PUT /vacancies/{vacancy_id} (составные поля вроде salary_range передавай целиком). Снять с публикации — PUT /employers/{employer_id}/vacancies/archived/{vacancy_id}.
curl -X POST https://api.hh.ru/vacancies \
  -H "Authorization: Bearer $HH_TOKEN" \
  -H 'HH-User-Agent: MyApp/1.0 (dev@example.ru)' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "Python-разработчик",
        "description": "<p>Разрабатываем сервисы для логистики.</p><ul><li>Python 3, FastAPI</li></ul>",
        "area": {"id": "1"},
        "professional_roles": [{"id": "96"}],
        "salary_range": {"from": 200000, "to": 300000, "currency": "RUR", "gross": false, "mode": {"id": "MONTH"}, "frequency": {"id": "TWICE_PER_MONTH"}},
        "key_skills": [{"name": "Python"}, {"name": "PostgreSQL"}]
      }'

Базовые URL

Авторизация

Тип: OAuth 2.0

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

Параметры /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)

Методы сценария

POST /token — Получение access-токена

Тело — application/x-www-form-urlencoded. Набор полей зависит от grant_type (получение токена пользователя, обновление пары токенов, токен приложения). Ниже — поля для обмена authorization_code.

В ответе: access_token, token_type (bearer), expires_in, refresh_token.

Параметр Где Тип Обяз. Описание
HH-User-Agent header string да Название приложения и почта разработчика
grant_type body string да authorization_code
client_id body string да Идентификатор приложения
client_secret body string да Секретный ключ приложения
code body string да Полученный authorization_code
redirect_uri body string да URI перенаправления (если не указан — из настроек приложения)
code_verifier body string нет Верификатор PKCE; обязателен, если передавался code_challenge

GET /me — Информация о текущем пользователе

В ответе: auth_type, id, email, first_name, last_name, is_applicant, is_employer, employer, manager, counters и др.

Параметр Где Тип Обяз. Описание
HH-User-Agent header string да Название приложения и почта разработчика

POST /vacancies — Публикация вакансии

При успешной публикации списываются услуги работодателя; конкретный пакет задаётся employer_service_id, иначе выбирается автоматически. Все вакансии проходят ручную модерацию и появляются в поиске через несколько минут. Успех — 201.

Параметр Где Тип Обяз. Описание
ignore_duplicates query boolean нет Принудительно добавить дубликат
name body string да Название
description body string да Описание в HTML
area body object да Регион
professional_roles body array да Профессиональные роли
vacancy_properties body object нет Свойства публикации (заменяет устаревшие type и billing_type)
employer_service_id body string нет Пакет услуг из suitable_packages[].employer_service_id
salary_range body object нет Зарплата (поле salary устарело)
address body object нет Адрес
experience body object нет Опыт работы
employment_form body object нет Тип занятости
work_format body array нет Форматы работы
work_schedule_by_days body array нет Графики работы
working_hours body array нет Рабочие часы в день
key_skills body array нет Ключевые навыки
contacts body object нет Контакты; при использовании нужен атрибут phones
code body string нет Внутренний код вакансии
department body object нет Департамент работодателя
manager body object нет Менеджер вакансии
previous_id body string нет ID архивной вакансии для связи с новой
response_letter_required body boolean нет Обязательно сопроводительное письмо
test body object нет Тест для вакансии

PUT /vacancies/{vacancy_id} — Редактирование вакансии

Изменяет переданные поля. Составные поля (salary_range, contacts, professional_roles) передаются целиком. billing_type и manager меняются отдельным запросом.

Параметр Где Тип Обяз. Описание
vacancy_id path string да Идентификатор вакансии
ignore_duplicates query boolean нет Игнорировать появление дубликата (по умолчанию false)
ignore_replacement_warning query boolean нет Игнорировать ошибку о значительном изменении (по умолчанию true, есть риск блокировки)
name body string нет Название
description body string нет Описание в HTML
salary_range body object нет Зарплата (целиком)
contacts body object нет Контакты (целиком)
professional_roles body array нет Профессиональные роли (целиком)

PUT /employers/{employer_id}/vacancies/archived/{vacancy_id} — Архивация вакансии

Успех — 204.

Параметр Где Тип Обяз. Описание
employer_id path string да Идентификатор работодателя
vacancy_id path string да Идентификатор вакансии

Нюансы

Другие сценарии


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