{"openapi":"3.0.0","paths":{"/v1/key":{"get":{"description":"Пределы ключа и сколько потрачено за сегодняшние сутки по Москве. Этот запрос тоже идёт в счёт","operationId":"getKey","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1KeyDto"},"example":{"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}}}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Ключ и пределы","tags":["Ключ"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  \"https://api.jobok.ru/v1/key\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/key', {\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n  },\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.get(\n    \"https://api.jobok.ru/v1/key\",\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}},"/v1/scans":{"get":{"description":"Готовые сборы навыков, свежие сверху, не больше 50","operationId":"listScans","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/V1ScanListItemDto"}},"example":[{"id":"cmv1zfxir00041kx2cvn26e1g","queries":["devops инженер"],"status":"done","scanned":407,"finishedAt":"2026-10-10T05:59:29.578Z","skillCount":112,"salary":{"from":130500,"to":226200}}]}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Список сборов","tags":["Сборы навыков"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  \"https://api.jobok.ru/v1/scans\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/scans', {\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n  },\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.get(\n    \"https://api.jobok.ru/v1/scans\",\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}},"/v1/scans/{id}":{"get":{"description":"Навыки с долями и зарплатой, квартили зарплат, слова названий, регионы","operationId":"getScan","parameters":[{"name":"id","required":true,"in":"path","description":"id сбора из GET /v1/scans","schema":{"example":"cmv1zfxir00041kx2cvn26e1g","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ScanDto"},"example":{"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}]}}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"404":{"description":"Сбора нет или у него ещё нет результата","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Сбор целиком","tags":["Сборы навыков"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  \"https://api.jobok.ru/v1/scans/cmv1zfxir00041kx2cvn26e1g\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/scans/cmv1zfxir00041kx2cvn26e1g', {\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n  },\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.get(\n    \"https://api.jobok.ru/v1/scans/cmv1zfxir00041kx2cvn26e1g\",\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}},"/v1/skills":{"get":{"description":"Самые частые навыки по профессии — из подходящего готового сбора или из названного по scanId","operationId":"getSkills","parameters":[{"name":"profession","required":false,"in":"query","description":"Название профессии: сбор подбирается по словам названия — все слова одного должны быть в другом","schema":{"example":"devops","type":"string"}},{"name":"scanId","required":false,"in":"query","description":"Взять этот сбор (id из GET /v1/scans), а не подбирать по профессии","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1SkillsDto"},"example":{"scan":{"id":"cmv1zfxir00041kx2cvn26e1g","queries":["devops инженер"],"scanned":407,"finishedAt":"2026-10-10T05:59:29.578Z"},"skills":[{"name":"CI/CD","members":["CI/CD"],"share":0.1155}]}}}},"400":{"description":"Нет ни profession, ни scanId","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"404":{"description":"Подходящего сбора нет","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Навыки профессии","tags":["Сборы навыков"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  \"https://api.jobok.ru/v1/skills?profession=devops\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/skills?profession=devops', {\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n  },\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.get(\n    \"https://api.jobok.ru/v1/skills\",\n    params={\"profession\": \"devops\"},\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}},"/v1/resume/coverage":{"post":{"description":"Какие частые навыки профессии названы в тексте резюме, а каких не хватает","operationId":"checkResumeCoverage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1CoverageRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1CoverageDto"},"example":{"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}]}}}},"400":{"description":"Нет текста или нет ни profession, ни scanId","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"404":{"description":"Подходящего сбора нет","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Сверка с рынком","tags":["Сверка резюме"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"profession\":\"devops\",\"text\":\"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"}' \\\n  \"https://api.jobok.ru/v1/resume/coverage\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/resume/coverage', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"profession\": \"devops\",\n    \"text\": \"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"\n  }),\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.post(\n    \"https://api.jobok.ru/v1/resume/coverage\",\n    json={\"profession\": \"devops\", \"text\": \"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"},\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}},"/v1/vacancies/{id}/coverage":{"post":{"description":"Какие навыки вакансии hh.ru названы в тексте резюме, а каких не хватает. Вакансия, которую ещё не читали, берётся с hh.ru — у этого свой суточный предел (limits.vacancyFetchesPerDay в GET /v1/key); прочитанная отвечает из кэша без него","operationId":"checkVacancyCoverage","parameters":[{"name":"id","required":true,"in":"path","description":"Номер вакансии hh.ru — цифры из ссылки hh.ru/vacancy/…","schema":{"example":"123456789","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ResumeTextDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1VacancyCoverageDto"},"example":{"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"}]}}}},"400":{"description":"Нет текста или id — не номер вакансии","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"401":{"description":"Ключа нет, он удалён или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"404":{"description":"Такой вакансии на hh.ru нет","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"429":{"description":"Исчерпан предел — см. Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}},"502":{"description":"hh.ru не отдал страницу вакансии","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ErrorDto"}}}}},"security":[{"api-key":[]}],"summary":"Сверка с вакансией","tags":["Сверка резюме"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -H \"Authorization: Bearer $JOBOK_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\":\"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"}' \\\n  \"https://api.jobok.ru/v1/vacancies/123456789/coverage\""},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://api.jobok.ru/v1/vacancies/123456789/coverage', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.JOBOK_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"text\": \"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"\n  }),\n});\nconst data = await response.json();\nif (!response.ok) throw new Error(`${data.error.type}: ${data.error.message}`);\nconsole.log(data);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\n\nresponse = requests.post(\n    \"https://api.jobok.ru/v1/vacancies/123456789/coverage\",\n    json={\"text\": \"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible\"},\n    headers={\"Authorization\": f\"Bearer {os.environ['JOBOK_KEY']}\"},\n    timeout=30,\n)\ndata = response.json()\nif not response.ok:\n    raise RuntimeError(f\"{data['error']['type']}: {data['error']['message']}\")\nprint(data)"}]}}},"info":{"title":"Jobok API","description":"Данные рынка из сборов навыков hh.ru. Ключ — в разделе «API» кабинета","version":"1","contact":{}},"tags":[{"name":"Ключ","description":"Пределы ключа и сколько из них потрачено сегодня"},{"name":"Сборы навыков","description":"Готовые сборы навыков с hh.ru: что требуют работодатели по профессии и сколько платят"},{"name":"Сверка резюме","description":"Какие навыки названы в тексте резюме, а каких не хватает — по рынку профессии или по одной вакансии"}],"servers":[{"url":"https://api.jobok.ru"}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Ключ API: jbk_…"}},"schemas":{"ApiErrorType":{"type":"string","enum":["invalid_api_key","key_expired","rate_limit_exceeded","not_found","invalid_request","request_too_large","hh_unavailable","server_error"]},"V1ErrorBodyDto":{"type":"object","properties":{"type":{"description":"Стабильная строка — по ней ветвится программа","allOf":[{"$ref":"#/components/schemas/ApiErrorType"}]},"message":{"type":"string","description":"Текст для человека, может меняться"}},"required":["type","message"]},"V1ErrorDto":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/V1ErrorBodyDto"}},"required":["error"]},"V1LimitsDto":{"type":"object","properties":{"perMinute":{"type":"number","description":"Запросов в минуту на все ключи владельца","example":60},"perDay":{"type":"number","description":"Запросов в сутки по Москве на все ключи владельца","example":1000},"keyPerDay":{"type":"number","nullable":true,"description":"Свой суточный предел этого ключа; null — только общий","example":null},"vacancyFetchesPerDay":{"type":"number","description":"Вакансий в сутки, которые сверка может прочитать с hh.ru, на все ключи владельца; вакансии из кэша в счёт не идут","example":50}},"required":["perMinute","perDay","keyPerDay","vacancyFetchesPerDay"]},"V1UsageDto":{"type":"object","properties":{"total":{"type":"number","description":"Запросов за сегодня по всем ключам владельца","example":94},"key":{"type":"number","description":"Из них — этим ключом","example":1},"vacancyFetches":{"type":"number","description":"Вакансий прочитано с hh.ru по всем ключам владельца","example":7}},"required":["total","key","vacancyFetches"]},"V1KeyDto":{"type":"object","properties":{"name":{"type":"string","example":"Бот в Telegram"},"hint":{"type":"string","example":"jbk_AbCd…Wx12"},"createdAt":{"type":"string","example":"2026-10-11T19:03:06.623Z"},"expiresAt":{"type":"string","nullable":true,"description":"null — бессрочный","example":null},"limits":{"$ref":"#/components/schemas/V1LimitsDto"},"usedToday":{"description":"Счёт сегодняшних суток по Москве, включая этот запрос","allOf":[{"$ref":"#/components/schemas/V1UsageDto"}]}},"required":["name","hint","createdAt","expiresAt","limits","usedToday"]},"SkillScanStatus":{"type":"string","enum":["running","done","stopped","failed"]},"V1SalaryMediansDto":{"type":"object","properties":{"from":{"type":"number","nullable":true,"description":"Медиана названных нижних границ, ₽ в месяц на руки","example":130500},"to":{"type":"number","nullable":true,"description":"Медиана названных верхних границ, ₽ в месяц на руки","example":226200}},"required":["from","to"]},"V1ScanListItemDto":{"type":"object","properties":{"id":{"type":"string","example":"cmv1zfxir00041kx2cvn26e1g"},"queries":{"description":"Формулировки названия вакансии, по которым шёл сбор","example":["devops инженер"],"type":"array","items":{"type":"string"}},"status":{"description":"done — досчитан; stopped — остановлен вручную, посчитано то, что успели; running — идёт пересчёт, данные прошлого прогона","example":"done","allOf":[{"$ref":"#/components/schemas/SkillScanStatus"}]},"scanned":{"type":"number","description":"Сколько вакансий обойдено — база всех долей","example":407},"finishedAt":{"type":"string","nullable":true,"example":"2026-10-10T05:59:29.578Z"},"skillCount":{"type":"number","description":"Сколько групп навыков в сборе","example":112},"salary":{"nullable":true,"description":"null — зарплату не считали или её никто не указал","allOf":[{"$ref":"#/components/schemas/V1SalaryMediansDto"}]}},"required":["id","queries","status","scanned","finishedAt","skillCount","salary"]},"V1SalarySideDto":{"type":"object","properties":{"p25":{"type":"number","nullable":true,"example":80000},"p50":{"type":"number","nullable":true,"example":130500},"p75":{"type":"number","nullable":true,"example":200000},"count":{"type":"number","description":"По скольким вакансиям названа эта граница","example":68}},"required":["p25","p50","p75","count"]},"V1ScanSalaryDto":{"type":"object","properties":{"from":{"description":"Нижние границы вилок («от»), ₽ в месяц на руки","allOf":[{"$ref":"#/components/schemas/V1SalarySideDto"}]},"to":{"description":"Верхние границы вилок («до»), ₽ в месяц на руки","example":{"p25":123467,"p50":226200,"p75":280000,"count":58},"allOf":[{"$ref":"#/components/schemas/V1SalarySideDto"}]},"withSalary":{"type":"number","description":"У скольких вакансий зарплата пригодна к счёту","example":91},"ratesAt":{"type":"string","nullable":true,"description":"Дата курса ЦБ, по которому пересчитана валюта","example":"2026-10-10T00:00:00.000Z"}},"required":["from","to","withSalary","ratesAt"]},"V1ScanSkillDto":{"type":"object","properties":{"name":{"type":"string","example":"CI/CD"},"members":{"description":"Все написания навыка, от частого к редкому","example":["CI/CD"],"type":"array","items":{"type":"string"}},"count":{"type":"number","description":"Во скольких вакансиях встретился","example":47},"share":{"type":"number","description":"Доля от обойдённых вакансий, 0..1","example":0.1155},"salaryFrom":{"type":"number","nullable":true,"description":"Медиана «от» по вакансиям с этим навыком, ₽ в месяц","example":115250},"salaryTo":{"type":"number","nullable":true,"description":"Медиана «до» по вакансиям с этим навыком, ₽ в месяц","example":130250}},"required":["name","members","count","share","salaryFrom","salaryTo"]},"V1TitleWordDto":{"type":"object","properties":{"word":{"type":"string","description":"Слово или устойчивое сочетание из названий вакансий","example":"devops-инженер"},"count":{"type":"number","example":262},"employers":{"type":"number","description":"У скольких разных работодателей встретилось","example":204}},"required":["word","count","employers"]},"V1AreaDto":{"type":"object","properties":{"name":{"type":"string","example":"Москва"},"count":{"type":"number","example":213}},"required":["name","count"]},"V1ScanDto":{"type":"object","properties":{"id":{"type":"string","example":"cmv1zfxir00041kx2cvn26e1g"},"queries":{"example":["devops инженер"],"type":"array","items":{"type":"string"}},"status":{"description":"done — досчитан; stopped — остановлен вручную, посчитано то, что успели; running — идёт пересчёт, данные прошлого прогона","example":"done","allOf":[{"$ref":"#/components/schemas/SkillScanStatus"}]},"found":{"type":"number","description":"Сколько вакансий нашёл hh.ru","example":448},"scanned":{"type":"number","description":"Сколько обойдено — база всех долей","example":407},"limitHit":{"type":"boolean","description":"hh.ru отдаёт не больше 2000 вакансий на запрос — обойдена не вся выдача","example":false},"finishedAt":{"type":"string","nullable":true,"example":"2026-10-10T05:59:29.578Z"},"salary":{"nullable":true,"description":"null — зарплату не считали","allOf":[{"$ref":"#/components/schemas/V1ScanSalaryDto"}]},"skills":{"description":"Все группы навыков, от частых к редким","type":"array","items":{"$ref":"#/components/schemas/V1ScanSkillDto"}},"titleWords":{"type":"array","items":{"$ref":"#/components/schemas/V1TitleWordDto"}},"areas":{"description":"Регионы вакансий","type":"array","items":{"$ref":"#/components/schemas/V1AreaDto"}}},"required":["id","queries","status","found","scanned","limitHit","finishedAt","salary","skills","titleWords","areas"]},"V1SkillsScanDto":{"type":"object","properties":{"id":{"type":"string","example":"cmv1zfxir00041kx2cvn26e1g"},"queries":{"example":["devops инженер"],"type":"array","items":{"type":"string"}},"scanned":{"type":"number","description":"Сколько вакансий обойдено — база долей","example":407},"finishedAt":{"type":"string","nullable":true,"example":"2026-10-10T05:59:29.578Z"}},"required":["id","queries","scanned","finishedAt"]},"V1SkillDto":{"type":"object","properties":{"name":{"type":"string","example":"CI/CD"},"members":{"description":"Все написания — по ним навык ищут в тексте резюме","example":["CI/CD"],"type":"array","items":{"type":"string"}},"share":{"type":"number","description":"Доля от обойдённых вакансий, 0..1","example":0.1155}},"required":["name","members","share"]},"V1SkillsDto":{"type":"object","properties":{"scan":{"description":"Сбор, из которого взяты навыки","allOf":[{"$ref":"#/components/schemas/V1SkillsScanDto"}]},"skills":{"description":"Самые частые навыки, не больше 40","type":"array","items":{"$ref":"#/components/schemas/V1SkillDto"}}},"required":["scan","skills"]},"V1CoverageRequestDto":{"type":"object","properties":{"profession":{"type":"string","description":"Название профессии: сбор подбирается по словам названия — все слова одного должны быть в другом","example":"devops"},"scanId":{"type":"string","description":"Взять этот сбор (id из GET /v1/scans), а не подбирать по профессии"},"text":{"type":"string","description":"Текст резюме одной строкой: опыт, «О себе», навыки. Сервер его не хранит и не пишет в журнал","example":"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible"}},"required":["text"]},"V1CoverageDto":{"type":"object","properties":{"scan":{"description":"Сбор, с навыками которого сверялся текст","allOf":[{"$ref":"#/components/schemas/V1SkillsScanDto"}]},"covered":{"description":"Названы в тексте — любым написанием и отдельным словом: «Java» внутри «JavaScript» не считается","type":"array","items":{"$ref":"#/components/schemas/V1SkillDto"}},"missing":{"description":"Не названы, частые сверху","example":[{"name":"Linux","members":["Linux"],"share":0.1081}],"type":"array","items":{"$ref":"#/components/schemas/V1SkillDto"}}},"required":["scan","covered","missing"]},"V1ResumeTextDto":{"type":"object","properties":{"text":{"type":"string","description":"Текст резюме одной строкой: опыт, «О себе», навыки. Сервер его не хранит и не пишет в журнал","example":"Настраивал CI/CD в GitLab, инфраструктура на Terraform и Ansible"}},"required":["text"]},"V1VacancyRefDto":{"type":"object","properties":{"id":{"type":"string","example":"123456789"},"url":{"type":"string","example":"https://hh.ru/vacancy/123456789"}},"required":["id","url"]},"V1VacancySkillSource":{"type":"string","enum":["key_skills","description"]},"V1VacancySkillDto":{"type":"object","properties":{"name":{"type":"string","example":"Vue.js"},"members":{"description":"Написания навыка — по ним он ищется в тексте резюме: найденные в вакансии и известные по прошлым сборам","example":["Vue.js","Vue","VueJS"],"type":"array","items":{"type":"string"}},"source":{"description":"key_skills — в блоке «Ключевые навыки» вакансии; description — найден в описании по словарю прошлых сборов","allOf":[{"$ref":"#/components/schemas/V1VacancySkillSource"}]}},"required":["name","members","source"]},"V1VacancyCoverageDto":{"type":"object","properties":{"vacancy":{"$ref":"#/components/schemas/V1VacancyRefDto"},"covered":{"description":"Навыки вакансии, названные в тексте резюме","type":"array","items":{"$ref":"#/components/schemas/V1VacancySkillDto"}},"missing":{"description":"Не названы — сначала из блока «Ключевые навыки», потом из описания","example":[{"name":"JavaScript","members":["JavaScript"],"source":"key_skills"}],"type":"array","items":{"$ref":"#/components/schemas/V1VacancySkillDto"}}},"required":["vacancy","covered","missing"]}}},"x-rate-limits":{"perMinute":60,"perDay":1000,"vacancyFetchesPerDay":50,"headers":[{"name":"X-RateLimit-Limit-Requests","description":"суточный предел этого ключа"},{"name":"X-RateLimit-Remaining-Requests","description":"сколько запросов осталось на сегодня"},{"name":"X-RateLimit-Reset-Requests","description":"секунд до полуночи по Москве"},{"name":"Retry-After","description":"на отказе 429 — через сколько секунд повторить"}]},"x-error-types":[{"type":"invalid_api_key","status":401,"description":"Ключа нет в заголовке, он не распознан или удалён"},{"type":"key_expired","status":401,"description":"Срок ключа истёк"},{"type":"rate_limit_exceeded","status":429,"description":"Исчерпан предел — повторить через Retry-After секунд"},{"type":"not_found","status":404,"description":"Сбора нет, у него ещё нет результата или такого метода нет вовсе"},{"type":"invalid_request","status":400,"description":"Неверные параметры или тело запроса — не JSON"},{"type":"request_too_large","status":413,"description":"Тело запроса больше 100 КБ"},{"type":"hh_unavailable","status":502,"description":"hh.ru не отдал страницу вакансии — повторить позже"},{"type":"server_error","status":500,"description":"Сбой на нашей стороне"}],"x-mcp":{"path":"/v1/mcp","tools":[{"name":"list_scans","description":"Готовые сборы навыков с hh.ru, свежие сверху: формулировки поиска (профессия), сколько вакансий обойдено, медианы зарплат. id сбора — для get_scan и scanId"},{"name":"get_scan","description":"Сбор целиком: все навыки с долей вакансий и зарплатой, квартили зарплат, частые слова названий, регионы. Ответ большой — для частых навыков профессии хватит get_skills"},{"name":"get_skills","description":"Самые частые навыки по профессии (до 40) с долей вакансий, где их просят. Сбор подбирается по названию профессии; если не подходит — scanId из list_scans"},{"name":"check_resume_coverage","description":"Какие из частых навыков профессии названы в тексте резюме, а каких не хватает. Текст резюме не хранится"},{"name":"check_vacancy_coverage","description":"Какие навыки конкретной вакансии hh.ru названы в тексте резюме, а каких не хватает. Вакансия — ссылка или номер; непрочитанная берётся с hh.ru, у этого свой суточный предел (get_limits)"},{"name":"get_limits","description":"Пределы ключа и сколько потрачено сегодня"}],"prompts":[{"name":"resume_review","description":"Разбор резюме: каких навыков рынка или вакансии не хватает, что вписать и что убрать"}]}}