hh: поиск работы Data API
hh: поиск работы (HeadHunter) uses one JSON API for job search and applicant identity. The search screen loads a paginated vacancy listing (salary_range, employer, area); the vacancy card adds description, key skills and contacts; the resume tab reads the signed-in applicant's CV (first_name, last_name, contact, total_views); the applications feed lists state, linked vacancy and chat id; who-viewed-me returns employer id, name and logo; and recruiter phone numbers are fetched on demand from the vacancy contacts sheet.
hh: поиск работы (package ru.hh.android, versionName 26.35.1) is HeadHunter's Android client for vacancy search, resumes, applications and employer contacts across its regional job-board sites. The app talks to a single first-party JSON API over HTTPS: anonymous and signed-in clients share the same read endpoints, while signed-in calls attach an OAuth2 Bearer access token and a generated User-Agent string. Listing, detail, resume, application and contact payloads expose wire fields such as salary_range, first_name, last_name, employer and created_at. The surface below mirrors the shape of those calls on generalized, illustrative paths.
Screenshots
API surface
Search vacancies
GET
/v1/jobs/searchopendataReturns a paginated vacancy listing (title, salary_range, area, employer, work_format) used by the search-results screen, including nearby and similar-vacancy variants.
Auth: Optional OAuth2 Bearer access token from the app's sign-in flow. Signed requests also send a generated User-Agent ({package}/{version}, Device, Android OS, UUID).
- items
- id
- name
- published_at
- created_at
- archived
- alternate_url
- url
- salary_range
- from
- to
- currency
- gross
- mode
- frequency
- area
- employer
- trusted
- open_vacancies
- accredited_it_employer
- logo_urls
- experience
- employment_form
- work_format
- show_contacts
- response_letter_required
- found
- page
- pages
- per_page
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/search?text=product+manager&area=1&page=0&per_page=20 HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "items": [ { "id": "123456789", "name": "Product Manager", "published_at": "2026-09-20T10:15:00+0300", "created_at": "2026-09-18T09:00:00+0300", "archived": false, "alternate_url": "https://example.org/vacancy/123456789", "url": "https://example.org/api/jobs/123456789", "salary_range": {"from": 180000, "to": 250000, "currency": "RUR", "gross": true, "mode": "MONTH", "frequency": "MONTH"}, "area": {"id": "1", "name": "Москва", "url": "https://example.org/api/areas/1"}, "employer": {"id": "1337", "name": "Example Corp", "alternate_url": "https://example.org/employer/1337", "trusted": true, "open_vacancies": 42, "accredited_it_employer": true, "logo_urls": {"90": "https://cdn.example.org/logo90.png", "240": "https://cdn.example.org/logo240.png", "original": "https://cdn.example.org/logo.png"}}, "experience": {"id": "between3And6", "name": "От 3 до 6 лет"}, "employment_form": {"id": "FULL", "name": "Полная занятость"}, "work_format": [{"id": "HYBRID", "name": "Гибрид"}], "show_contacts": true, "response_letter_required": false, "accept_incomplete_resumes": true, "has_test": false } ], "found": 1284, "page": 0, "pages": 65, "per_page": 20, "alternate_url": "https://example.org/search/vacancy?text=product+manager&area=1" }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the search-results screen flow and its pagination parametersWire field names taken from the vacancy list and salary payloads
Fetch vacancy detail
GET
/v1/jobs/{job_id}opendataHydrates the vacancy card (description, key_skills, salary_range, employer, contacts, professional_roles) for the vacancy-detail screen and job deep links.
Auth: Bearer access_token for signed-in extras (relations, show_contacts, chat flags). User-Agent as above.
- id
- name
- description
- key_skills
- published_at
- created_at
- archived
- alternate_url
- apply_alternate_url
- negotiations_url
- salary_range
- area
- address
- employer
- experience
- employment_form
- work_format
- schedule
- working_hours
- work_schedule_by_days
- professional_roles
- response_letter_required
- accept_incomplete_resumes
- show_contacts
- contacts
- phones
- formatted
- responses_count
- allow_chat_with_manager
- relations
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/123456789 HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "id": "123456789", "name": "Product Manager", "description": "<p>Lead the candidate experience squad.</p>", "key_skills": [{"name": "product management"}, {"name": "SQL"}], "published_at": "2026-09-20T10:15:00+0300", "created_at": "2026-09-18T09:00:00+0300", "archived": false, "alternate_url": "https://example.org/vacancy/123456789", "apply_alternate_url": "https://example.org/applicant/vacancy_response?vacancyId=123456789", "negotiations_url": "https://example.org/api/applications?vacancy_id=123456789", "salary_range": {"from": 180000, "to": 250000, "currency": "RUR", "gross": true}, "area": {"id": "1", "name": "Москва"}, "address": {"city": "Москва", "street": "Тверская", "building": "1", "lat": 55.76, "lng": 37.61}, "employer": {"id": "1337", "name": "Example Corp", "trusted": true, "accredited_it_employer": true}, "experience": {"id": "between3And6", "name": "От 3 до 6 лет"}, "employment_form": {"id": "FULL", "name": "Полная занятость"}, "work_format": [{"id": "HYBRID", "name": "Гибрид"}], "schedule": {"id": "fullDay", "name": "Полный день"}, "working_hours": [{"id": "HOURS_8", "name": "8 часов"}], "work_schedule_by_days": [{"id": "FIVE_ON_TWO_OFF", "name": "5/2"}], "professional_roles": [{"id": "73", "name": "Менеджер продукта"}], "response_letter_required": false, "accept_incomplete_resumes": true, "accept_temporary": false, "internship": false, "show_contacts": true, "contacts": {"name": "Anna Petrova", "email": "[email protected]", "call_tracking_enabled": true, "phones": [{"country": "7", "city": "495", "number": "1234567", "formatted": "+7 (495) 123-45-67"}]}, "responses_count": 42, "allow_chat_with_manager": true, "relations": ["got_response"] }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the vacancy-detail screen and deep-link handlingField names taken from the full vacancy and contacts payloads
Fetch applicant resume
GET
/v1/cv/{cv_id}osintReturns the signed-in applicant's full resume (name, birth_date, contact, education, experience, salary, views) used by My resumes and the resume editor.
Auth: Bearer access_token required. The native resume screen asks for professional roles and credential extras via query flags.
- id
- last_name
- first_name
- middle_name
- title
- created_at
- updated_at
- birth_date
- age
- gender
- area
- salary
- contact
- education
- experience
- skill_set
- skills
- professional_roles
- status
- access
- total_views
- new_views
- views_url
- alternate_url
- can_publish_or_update
- next_publish_at
- progress
- creds
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/cv/abc12defghijklmnopqrstuvwx?include=roles,credentials HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "id": "abc12defghijklmnopqrstuvwx", "last_name": "Ivanov", "first_name": "Ivan", "middle_name": "Ivanovich", "title": "Product Manager", "created_at": "2024-03-01T12:00:00+0300", "updated_at": "2026-09-21T08:30:00+0300", "birth_date": "1992-04-12", "age": 34, "gender": {"id": "male", "name": "Мужской"}, "area": {"id": "1", "name": "Москва"}, "salary": {"amount": 220000, "currency": "RUR"}, "contact": [{"kind": "email", "value": "[email protected]", "preferred": true}, {"kind": "cell", "value": {"formatted": "+7 999 123-45-67"}}], "education": {"level": {"id": "higher", "name": "Высшее"}, "primary": [{"organization": "MGU", "name": "Economics", "year": 2014}]}, "experience": [{"company": "Example Corp", "position": "Product Manager", "start": "2020-01-01", "end": null}], "skill_set": ["SQL", "product management"], "skills": "Led marketplace growth.", "professional_roles": [{"id": "73", "name": "Менеджер продукта"}], "status": {"id": "published", "name": "Опубликовано"}, "access": {"type": {"id": "clients", "name": "Видно всем компаниям"}}, "total_views": 128, "new_views": 7, "views_url": "https://example.org/api/cv/abc12defghijklmnopqrstuvwx/viewers", "alternate_url": "https://example.org/resume/abc12defghijklmnopqrstuvwx", "can_publish_or_update": true, "next_publish_at": "2026-09-24T08:30:00+0300", "progress": {"percentage": 92}, "creds": {"email": "[email protected]"} }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the My resumes screen and the resume editor flowField names taken from the full resume payload, including views counters
List negotiations (applications)
GET
/v1/applicationsosintLists the applicant's vacancy responses (state, viewed_by_opponent, linked vacancy/resume, chat_id) for the responses / applications tab.
Auth: Bearer access_token required. User-Agent as above.
- items
- id
- state
- hidden
- read
- created_at
- updated_at
- url
- has_updates
- viewed_by_opponent
- messaging_status
- decline_allowed
- vacancy
- resume
- chat_id
- employer_responses_read_percent
- manager_inactive_minutes
- source
- employer_violates_rules
- tags
- found
- page
- pages
- per_page
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/applications?page=0&per_page=20 HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "items": [ { "id": "987654321", "state": {"id": "response", "name": "Отклик"}, "hidden": false, "read": true, "created_at": "2026-09-19T11:00:00+0300", "updated_at": "2026-09-21T09:15:00+0300", "url": "https://example.org/api/applications/987654321", "has_updates": true, "viewed_by_opponent": true, "messaging_status": "has_new", "decline_allowed": true, "vacancy": {"id": "123456789", "name": "Product Manager", "alternate_url": "https://example.org/vacancy/123456789"}, "resume": {"id": "abc12defghijklmnopqrstuvwx", "title": "Product Manager"}, "chat_id": "c-555", "employer_responses_read_percent": 80, "manager_inactive_minutes": 120, "source": "search", "employer_violates_rules": false, "tags": [] } ], "found": 12, "page": 0, "pages": 1, "per_page": 20 }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the responses tab flow and its per-item status payloadA matching POST variant creates an application from vacancy id, resume id and a cover message
List resume views
GET
/v1/cv/{cv_id}/viewersosintReturns who viewed the applicant's resume (employer id/name/logo, created_at, viewed flag) for the resume-views screen.
Auth: Bearer access_token required. User-Agent as above.
- items
- created_at
- viewed
- employer
- id
- name
- url
- alternate_url
- vacancies_url
- logo_urls
- resume
- title
- found
- page
- pages
- per_page
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/cv/abc12defghijklmnopqrstuvwx/viewers?page=0&per_page=20 HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "items": [ { "created_at": "2026-09-21T14:22:00+0300", "viewed": true, "employer": { "id": "1337", "name": "Example Corp", "url": "https://example.org/api/employers/1337", "alternate_url": "https://example.org/employer/1337", "vacancies_url": "https://example.org/api/jobs/search?employer_id=1337", "logo_urls": {"90": "https://cdn.example.org/logo90.png", "240": "https://cdn.example.org/logo240.png", "original": "https://cdn.example.org/logo.png"} } } ], "resume": {"id": "abc12defghijklmnopqrstuvwx", "title": "Product Manager", "url": "https://example.org/api/cv/abc12defghijklmnopqrstuvwx"}, "found": 128, "page": 0, "pages": 7, "per_page": 20 }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the who-viewed-my-resume screen and its employer payload
Fetch vacancy contact phones
GET
/v1/jobs/{job_id}/phoneosintReveals the vacancy recruiter phone (country/city/number/formatted, virtual_phone_state) used by the vacancy-contacts sheet after show_contacts.
Auth: Bearer access_token required. Shown after the applicant taps show contacts on the vacancy card.
- comment
- city
- number
- country
- formatted
- virtual_phone_state
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/123456789/phone HTTP/1.1 User-Agent: <package>/<version>, Device: <device>, Android OS: <os> (UUID: <uuid>) Authorization: Bearer <access_token>{ "comment": "HR desk, 10:00–18:00 MSK", "city": "495", "number": "1234567", "country": "7", "formatted": "+7 (495) 123-45-67", "virtual_phone_state": "enabled" }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Reconstructed from the vacancy contacts sheet shown after tapping show contacts
Data categories
- vacancies
- resumes
- applications
- contacts
- employers
- profiles
Where teams use this data
Vacancy market analytics
Comp-benchmarking pipelines aggregate vacancy search results — salary range, area, employer accreditation, work format — into pay-band maps per role and region.
Recruiter pipeline sync
ATS integrations mirror the negotiations list — state, read/unread, viewed-by-opponent, chat id — so recruiters work one pipeline instead of two inboxes.
Resume performance tracking
Job-seeker tools list which employers viewed a resume and when, correlating views with edits to show candidates which version actually gets attention.
Frequently asked questions
Which hh API calls power vacancy search?
The listing screen issues a paginated search request (text, area, page, per_page). Each hit carries id, name, salary_range (from/to/currency/gross), area, employer and published_at. Opening a card fetches the full vacancy detail with description, key_skills, contacts and professional_roles.
How does the app load an applicant resume?
A signed-in request for the applicant's CV returns last_name, first_name, birth_date, contact, education, experience, salary, skill_set, total_views and a views link. A separate mine-list variant enumerates the user's own resumes.
Where do applications and resume views come from?
The responses tab lists the applicant's applications with state, viewed_by_opponent, linked vacancy and resume, and a chat id. A separate resume-views feed returns employer id, name, logo and created_at, and recruiter phone numbers are revealed on demand from the vacancy card.
How is the hh API authenticated?
OAuth2 access tokens are minted during sign-in and attached as Authorization: Bearer. Requests also carry a generated User-Agent describing app version, device and Android OS. The same API serves the service's regional job-board sites by switching hosts.
Topics
- hh api
- headhunter vacancies api
- hh resume endpoint
- hh applications api
- salary_range
- first_name last_name
- resume views employer
- vacancy phone formatted
Need this app's data API integrated?
We deliver scoped integrations for any named app — from USD 500 with source-code handoff, or hosted access billed per call. Tell us the data you need.