Jobok API
Создать ключ

Начало

  • Обзор
  • Авторизация
  • Пределы
  • Ошибки

Ключ

  • GETКлюч и пределы

Сборы навыков

  • GETСписок сборов
  • GETСбор целиком
  • GETНавыки профессии

Сверка резюме

  • POSTСверка с рынком
  • POSTСверка с вакансией

ИИ-ассистенты

  • MCP

Jobok API

Данные рынка из сборов навыков hh.ru. Ключ — в разделе «API» кабинета

  1. Создайте ключ в разделе «API» кабинета — он показывается один раз.
  2. Передавайте его в каждом запросе. Начните с метода «Ключ и пределы» — он покажет пределы ключа.
  3. ИИ-ассистенту подключите MCP или отдайте эту документацию: кнопка «Скопировать Markdown» вверху, файл — /v1/docs.md.

Спека OpenAPI для генераторов клиентов — /v1/openapi.json

Авторизация

Ключ передаётся в каждом запросе заголовком:

Authorization: Bearer jbk_…

Адрес API — https://api.jobok.ru. Ключ открывает только ручки /v1: войти с ним в кабинет нельзя. Вызывать API — с сервера, из скрипта или бота: из браузера на чужом сайте не выйдет, CORS открыт только сайту Jobok, а ключ в браузере увидел бы любой посетитель.

Пределы

Не больше 60 запросов в минуту и 1000 в сутки — на все ключи владельца вместе. Сутки — по Москве. У ключа может быть свой суточный предел, меньше общего. Сверка с вакансией, которую ещё не читали, берёт её с hh.ru — таких не больше 50 в сутки; прочитанные отвечают из кэша без этого предела. Каждый ответ несёт заголовки:

X-RateLimit-Limit-Requestsсуточный предел этого ключа
X-RateLimit-Remaining-Requestsсколько запросов осталось на сегодня
X-RateLimit-Reset-Requestsсекунд до полуночи по Москве
Retry-Afterна отказе 429 — через сколько секунд повторить

Ошибки

Отказ всегда в одной форме. Ветвиться — по type: текст в message для человека и может меняться.

{ "error": { "type": "not_found", "message": "…" } }
typeСтатусКогда
invalid_api_key401Ключа нет в заголовке, он не распознан или удалён
key_expired401Срок ключа истёк
rate_limit_exceeded429Исчерпан предел — повторить через Retry-After секунд
not_found404Сбора нет, у него ещё нет результата или такого метода нет вовсе
invalid_request400Неверные параметры или тело запроса — не JSON
request_too_large413Тело запроса больше 100 КБ
hh_unavailable502hh.ru не отдал страницу вакансии — повторить позже
server_error500Сбой на нашей стороне

Ключ

Пределы ключа и сколько из них потрачено сегодня

Ключ и пределы

GET/v1/key

Пределы ключа и сколько потрачено за сегодняшние сутки по Москве. Этот запрос тоже идёт в счёт

Ответ 200

  • namestring
  • hintstring
  • createdAtstring
  • expiresAtstring | null

    null — бессрочный

  • limitsobject
    Вложенные поля: 4
    • perMinutenumber

      Запросов в минуту на все ключи владельца

    • perDaynumber

      Запросов в сутки по Москве на все ключи владельца

    • keyPerDaynumber | null

      Свой суточный предел этого ключа; null — только общий

    • vacancyFetchesPerDaynumber

      Вакансий в сутки, которые сверка может прочитать с hh.ru, на все ключи владельца; вакансии из кэша в счёт не идут

  • usedTodayobject

    Счёт сегодняшних суток по Москве, включая этот запрос

    Вложенные поля: 3
    • totalnumber

      Запросов за сегодня по всем ключам владельца

    • keynumber

      Из них — этим ключом

    • vacancyFetchesnumber

      Вакансий прочитано с hh.ru по всем ключам владельца

Отказы

401Ключа нет, он удалён или истёк
429Исчерпан предел — см. Retry-After
curl -H "Authorization: Bearer $JOBOK_KEY" \
  "https://api.jobok.ru/v1/key"

Ответ 200

{
  "name": "Бот в Telegram",
  "hint": "jbk_AbCd…Wx12",
  "createdAt": "2026-10-11T19:03:06.623Z",
  "expiresAt": null,
  "limits": {
    "perMinute": 60,
    "perDay": 1000,
    "keyPerDay": null,
    "vacancyFetchesPerDay": 50
  },
  "usedToday": {
    "total": 94,
    "key": 1,
    "vacancyFetches": 7
  }
}

Сборы навыков

Готовые сборы навыков с hh.ru: что требуют работодатели по профессии и сколько платят

Список сборов

GET/v1/scans

Готовые сборы навыков, свежие сверху, не больше 50

Ответ 200 — массив объектов

  • idstring
  • queriesstring[]

    Формулировки названия вакансии, по которым шёл сбор

  • status"running" | "done" | "stopped" | "failed"

    done — досчитан; stopped — остановлен вручную, посчитано то, что успели; running — идёт пересчёт, данные прошлого прогона

  • scannednumber

    Сколько вакансий обойдено — база всех долей

  • finishedAtstring | null
  • skillCountnumber

    Сколько групп навыков в сборе

  • salaryobject | null

    null — зарплату не считали или её никто не указал

    Вложенные поля: 2
    • fromnumber | null

      Медиана названных нижних границ, ₽ в месяц на руки

    • tonumber | null

      Медиана названных верхних границ, ₽ в месяц на руки

Отказы

401Ключа нет, он удалён или истёк
429Исчерпан предел — см. Retry-After
curl -H "Authorization: Bearer $JOBOK_KEY" \
  "https://api.jobok.ru/v1/scans"

Ответ 200

[
  {
    "id": "cmv1zfxir00041kx2cvn26e1g",
    "queries": [
      "devops инженер"
    ],
    "status": "done",
    "scanned": 407,
    "finishedAt": "2026-10-10T05:59:29.578Z",
    "skillCount": 112,
    "salary": {
      "from": 130500,
      "to": 226200
    }
  }
]

Сбор целиком

GET/v1/scans/{id}

Навыки с долями и зарплатой, квартили зарплат, слова названий, регионы

Параметры

  • idstringв путиобязательно

    id сбора из GET /v1/scans

Ответ 200

  • idstring
  • queriesstring[]
  • status"running" | "done" | "stopped" | "failed"

    done — досчитан; stopped — остановлен вручную, посчитано то, что успели; running — идёт пересчёт, данные прошлого прогона

  • foundnumber

    Сколько вакансий нашёл hh.ru

  • scannednumber

    Сколько обойдено — база всех долей

  • limitHitboolean

    hh.ru отдаёт не больше 2000 вакансий на запрос — обойдена не вся выдача

  • finishedAtstring | null
  • salaryobject | null

    null — зарплату не считали

    Вложенные поля: 4
    • fromobject

      Нижние границы вилок («от»), ₽ в месяц на руки

      Вложенные поля: 4
      • p25number | null
      • p50number | null
      • p75number | null
      • countnumber

        По скольким вакансиям названа эта граница

    • toobject

      Верхние границы вилок («до»), ₽ в месяц на руки

      Вложенные поля: 4
      • p25number | null
      • p50number | null
      • p75number | null
      • countnumber

        По скольким вакансиям названа эта граница

    • withSalarynumber

      У скольких вакансий зарплата пригодна к счёту

    • ratesAtstring | null

      Дата курса ЦБ, по которому пересчитана валюта

  • skillsobject[]

    Все группы навыков, от частых к редким

    Вложенные поля: 6
    • namestring
    • membersstring[]

      Все написания навыка, от частого к редкому

    • countnumber

      Во скольких вакансиях встретился

    • sharenumber

      Доля от обойдённых вакансий, 0..1

    • salaryFromnumber | null

      Медиана «от» по вакансиям с этим навыком, ₽ в месяц

    • salaryTonumber | null

      Медиана «до» по вакансиям с этим навыком, ₽ в месяц

  • titleWordsobject[]
    Вложенные поля: 3
    • wordstring

      Слово или устойчивое сочетание из названий вакансий

    • countnumber
    • employersnumber

      У скольких разных работодателей встретилось

  • areasobject[]

    Регионы вакансий

    Вложенные поля: 2
    • namestring
    • countnumber

Отказы

401Ключа нет, он удалён или истёк
404Сбора нет или у него ещё нет результата
429Исчерпан предел — см. Retry-After
curl -H "Authorization: Bearer $JOBOK_KEY" \
  "https://api.jobok.ru/v1/scans/cmv1zfxir00041kx2cvn26e1g"

Ответ 200

{
  "id": "cmv1zfxir00041kx2cvn26e1g",
  "queries": [
    "devops инженер"
  ],
  "status": "done",
  "found": 448,
  "scanned": 407,
  "limitHit": false,
  "finishedAt": "2026-10-10T05:59:29.578Z",
  "salary": {
    "from": {
      "p25": 80000,
      "p50": 130500,
      "p75": 200000,
      "count": 68
    },
    "to": {
      "p25": 123467,
      "p50": 226200,
      "p75": 280000,
      "count": 58
    },
    "withSalary": 91,
    "ratesAt": "2026-10-10T00:00:00.000Z"
  },
  "skills": [
    {
      "name": "CI/CD",
      "members": [
        "CI/CD"
      ],
      "count": 47,
      "share": 0.1155,
      "salaryFrom": 115250,
      "salaryTo": 130250
    }
  ],
  "titleWords": [
    {
      "word": "devops-инженер",
      "count": 262,
      "employers": 204
    }
  ],
  "areas": [
    {
      "name": "Москва",
      "count": 213
    }
  ]
}

Навыки профессии

GET/v1/skills

Самые частые навыки по профессии — из подходящего готового сбора или из названного по scanId

Параметры

  • professionstringв запросе

    Название профессии: сбор подбирается по словам названия — все слова одного должны быть в другом

  • scanIdstringв запросе

    Взять этот сбор (id из GET /v1/scans), а не подбирать по профессии

Ответ 200

  • scanobject

    Сбор, из которого взяты навыки

    Вложенные поля: 4
    • idstring
    • queriesstring[]
    • scannednumber

      Сколько вакансий обойдено — база долей

    • finishedAtstring | null
  • skillsobject[]

    Самые частые навыки, не больше 40

    Вложенные поля: 3
    • namestring
    • membersstring[]

      Все написания — по ним навык ищут в тексте резюме

    • sharenumber

      Доля от обойдённых вакансий, 0..1

Отказы

400Нет ни profession, ни scanId
401Ключа нет, он удалён или истёк
404Подходящего сбора нет
429Исчерпан предел — см. Retry-After
curl -H "Authorization: Bearer $JOBOK_KEY" \
  "https://api.jobok.ru/v1/skills?profession=devops"

Ответ 200

{
  "scan": {
    "id": "cmv1zfxir00041kx2cvn26e1g",
    "queries": [
      "devops инженер"
    ],
    "scanned": 407,
    "finishedAt": "2026-10-10T05:59:29.578Z"
  },
  "skills": [
    {
      "name": "CI/CD",
      "members": [
        "CI/CD"
      ],
      "share": 0.1155
    }
  ]
}

Сверка резюме

Какие навыки названы в тексте резюме, а каких не хватает — по рынку профессии или по одной вакансии

Сверка с рынком

POST/v1/resume/coverage

Какие частые навыки профессии названы в тексте резюме, а каких не хватает

Тело запроса, JSON

  • professionstring

    Название профессии: сбор подбирается по словам названия — все слова одного должны быть в другом

  • scanIdstring

    Взять этот сбор (id из GET /v1/scans), а не подбирать по профессии

  • textstringобязательно

    Текст резюме одной строкой: опыт, «О себе», навыки. Сервер его не хранит и не пишет в журнал

Ответ 200

  • scanobject

    Сбор, с навыками которого сверялся текст

    Вложенные поля: 4
    • idstring
    • queriesstring[]
    • scannednumber

      Сколько вакансий обойдено — база долей

    • finishedAtstring | null
  • coveredobject[]

    Названы в тексте — любым написанием и отдельным словом: «Java» внутри «JavaScript» не считается

    Вложенные поля: 3
    • namestring
    • membersstring[]

      Все написания — по ним навык ищут в тексте резюме

    • sharenumber

      Доля от обойдённых вакансий, 0..1

  • missingobject[]

    Не названы, частые сверху

    Вложенные поля: 3
    • namestring
    • membersstring[]

      Все написания — по ним навык ищут в тексте резюме

    • sharenumber

      Доля от обойдённых вакансий, 0..1

Отказы

400Нет текста или нет ни profession, ни scanId
401Ключа нет, он удалён или истёк
404Подходящего сбора нет
429Исчерпан предел — см. Retry-After
curl -H "Authorization: Bearer $JOBOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profession":"devops","text":"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible"}' \
  "https://api.jobok.ru/v1/resume/coverage"

Ответ 200

{
  "scan": {
    "id": "cmv1zfxir00041kx2cvn26e1g",
    "queries": [
      "devops инженер"
    ],
    "scanned": 407,
    "finishedAt": "2026-10-10T05:59:29.578Z"
  },
  "covered": [
    {
      "name": "CI/CD",
      "members": [
        "CI/CD"
      ],
      "share": 0.1155
    }
  ],
  "missing": [
    {
      "name": "Linux",
      "members": [
        "Linux"
      ],
      "share": 0.1081
    }
  ]
}

Сверка с вакансией

POST/v1/vacancies/{id}/coverage

Какие навыки вакансии hh.ru названы в тексте резюме, а каких не хватает. Вакансия, которую ещё не читали, берётся с hh.ru — у этого свой суточный предел (limits.vacancyFetchesPerDay в GET /v1/key); прочитанная отвечает из кэша без него

Параметры

  • idstringв путиобязательно

    Номер вакансии hh.ru — цифры из ссылки hh.ru/vacancy/…

Тело запроса, JSON

  • textstringобязательно

    Текст резюме одной строкой: опыт, «О себе», навыки. Сервер его не хранит и не пишет в журнал

Ответ 200

  • vacancyobject
    Вложенные поля: 2
    • idstring
    • urlstring
  • coveredobject[]

    Навыки вакансии, названные в тексте резюме

    Вложенные поля: 3
    • namestring
    • membersstring[]

      Написания навыка — по ним он ищется в тексте резюме: найденные в вакансии и известные по прошлым сборам

    • source"key_skills" | "description"

      key_skills — в блоке «Ключевые навыки» вакансии; description — найден в описании по словарю прошлых сборов

  • missingobject[]

    Не названы — сначала из блока «Ключевые навыки», потом из описания

    Вложенные поля: 3
    • namestring
    • membersstring[]

      Написания навыка — по ним он ищется в тексте резюме: найденные в вакансии и известные по прошлым сборам

    • source"key_skills" | "description"

      key_skills — в блоке «Ключевые навыки» вакансии; description — найден в описании по словарю прошлых сборов

Отказы

400Нет текста или id — не номер вакансии
401Ключа нет, он удалён или истёк
404Такой вакансии на hh.ru нет
429Исчерпан предел — см. Retry-After
502hh.ru не отдал страницу вакансии
curl -H "Authorization: Bearer $JOBOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible"}' \
  "https://api.jobok.ru/v1/vacancies/123456789/coverage"

Ответ 200

{
  "vacancy": {
    "id": "123456789",
    "url": "https://hh.ru/vacancy/123456789"
  },
  "covered": [
    {
      "name": "Vue.js",
      "members": [
        "Vue.js",
        "Vue",
        "VueJS"
      ],
      "source": "key_skills"
    }
  ],
  "missing": [
    {
      "name": "JavaScript",
      "members": [
        "JavaScript"
      ],
      "source": "key_skills"
    }
  ]
}

MCP — для ИИ-ассистентов

Те же методы — инструментами MCP: ассистент сам решает, когда спросить навыки профессии или сверить резюме. Сервер без сессий, по Streamable HTTP; ключ тот же, в заголовке Authorization.

https://api.jobok.ru/v1/mcp

Claude Code

claude mcp add --transport http jobok https://api.jobok.ru/v1/mcp \
  --header "Authorization: Bearer $JOBOK_KEY"

Cursor и другие клиенты с файлом mcpServers

{
  "mcpServers": {
    "jobok": {
      "url": "https://api.jobok.ru/v1/mcp",
      "headers": {
        "Authorization": "Bearer jbk_…"
      }
    }
  }
}

Yandex AI Studio: в MCP Hub — внешний MCP-сервер, адрес выше, ключ — как Bearer-токен.

ИнструментЧто делает
list_scansГотовые сборы навыков с hh.ru, свежие сверху: формулировки поиска (профессия), сколько вакансий обойдено, медианы зарплат. id сбора — для get_scan и scanId
get_scanСбор целиком: все навыки с долей вакансий и зарплатой, квартили зарплат, частые слова названий, регионы. Ответ большой — для частых навыков профессии хватит get_skills
get_skillsСамые частые навыки по профессии (до 40) с долей вакансий, где их просят. Сбор подбирается по названию профессии; если не подходит — scanId из list_scans
check_resume_coverageКакие из частых навыков профессии названы в тексте резюме, а каких не хватает. Текст резюме не хранится
check_vacancy_coverageКакие навыки конкретной вакансии hh.ru названы в тексте резюме, а каких не хватает. Вакансия — ссылка или номер; непрочитанная берётся с hh.ru, у этого свой суточный предел (get_limits)
get_limitsПределы ключа и сколько потрачено сегодня

Промпты — готовые заготовки разговора: в Claude Code они видны командами, например /mcp__jobok__resume_review.

ПромптЧто делает
resume_reviewРазбор резюме: каких навыков рынка или вакансии не хватает, что вписать и что убрать

Каждое сообщение MCP идёт в счёт пределов: подключение — два запроса, список инструментов и каждый вызов — по одному.