Инструменты программой: ключ доступа и API

Как обращаться к проверкам из своей программы: ключ, запрос, ответ и пределы.

Все проверки раздела «Инструменты» доступны не только со страницы, но и из вашей программы: тот же расчёт и тот же вид ответа. Здесь собрано всё, чтобы начать за десять минут.

Как получить ключ

  1. Войдите в кабинет инструментов по коду на почту.
  2. Ключ доступа входит в тариф «Профи». На бесплатном и «Базовом» уровне ключа нет — попытка его выпустить ответит TOOL_KEY_NOT_ALLOWED.
  3. В разделе «Ключи доступа» нажмите «Создать ключ» и дайте ему имя — по нему вы узнаете ключ в списке.
  4. Открытое значение ключа показывается один раз — в миг создания. Мы храним только его отпечаток, поэтому «показать ещё раз» не можем ни вам, ни себе. Скопируйте ключ сразу. Потеряли — отзовите старый и выпустите новый.

Ключ выглядит так: приставка tlk_ и 64 шестнадцатеричных знака. По приставке его видно в чужом журнале — не оставляйте ключ в открытом коде страницы и не кладите в хранилище кода.

Ключей на тарифе «Профи» можно держать пять. Отозванный перестаёт работать в тот же миг.

Как передать ключ

Ключ идёт заголовком Authorization со словом Bearer:

Authorization: Bearer tlk_ВАШ_КЛЮЧ

Другие способы не работают намеренно: Authorization: Basic …, пустой Bearer без значения или ключ без приставки tlk_ получат 401 TOOL_KEY_INVALID. Тихо работать гостем мы не станем — иначе вы упирались бы в гостевые пределы и читали это как случайные отказы.

Ключ работает только на том сайте, где он выдан. Тот же ключ на адресе другого сайта платформы отвечает 401 TOOL_KEY_INVALID — тем же кодом, что и выдуманный ключ.

Заголовка нет вовсе — это не ошибка: запрос проходит как гостевой, с гостевыми пределами.

Первый запрос

Одна проверка — один запрос POST. Адрес складывается из вида инструмента:

POST https://seo-gen.com.ua/api/public/tools/<kind>/run

Полный пример, который можно скопировать и запустить (подставьте свой ключ):

curl -X POST https://seo-gen.com.ua/api/public/tools/http-status-checker/run \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"target":"https://example.com/"}'

В теле запроса два поля: target — адрес, который проверяем, и необязательный options — настройки вида.

Из чего состоит ответ

Удачный ответ — 200 и два поля: data с результатом и limit с остатком объёма. В примере ниже раздел headers убран, чтобы не растягивать страницу — в живом ответе он есть.

{
  "data": {
    "kind": "http-status-checker",
    "target": "https://example.com/",
    "checkedAt": "2026-09-19T08:12:07.078Z",
    "cached": false,
    "verdict": "ok",
    "sections": [
      {
        "id": "summary",
        "rows": [
          { "status": 200, "final": "https://example.com/", "hops": 0, "time_ms": 95, "soft_404": "" }
        ],
        "columns": ["status", "final", "hops", "time_ms", "soft_404"]
      },
      { "id": "chain", "rows": [], "columns": ["step", "from", "to", "status", "scheme"] }
    ],
    "notes": []
  },
  "limit": { "remaining": null }
}
  • data.kind — вид инструмента — тот же, что в адресе
  • data.target — адрес, который проверили; null — у вида его нет
  • data.checkedAt — время проверки, ISO-8601 с часовым поясом
  • data.cachedtrue — ответ взят из нашего кеша (живёт 10 минут); время при этом остаётся временем самой проверки
  • data.verdict — одно слово итога — перечень ниже
  • data.sections — разделы результата: у каждого id, rows и columns — порядок колонок
  • data.notes — коды оговорок (не готовый текст): почему проверили не всё и что стоит знать
  • limit.remaining — сколько проверок осталось; null значит «предела нет»

Если раздел показан не целиком, у него есть capped с двумя числами: сколько показано и сколько найдено.

Слова итога

  • ok — проверили, беды не нашли
  • guess — определили приблизительно: ответ держится на одной слабой улике
  • partial — проверили частично — часть не состоялась по НАШЕЙ причине (наш срок, наш предел размера, нас придержали за темп). Числа «проверено N из M» стоят в сводке
  • warn — есть оговорки
  • unknown — определить не удалось: ответ сайта разобрать не вышло
  • fail — нашли поломку

Виды инструментов и что им передавать

Все виды ниже работают по ключу. Столбец «Настройки» — содержимое поля options: в круглых скобках тип и значение по умолчанию, в квадратных — перечень допустимых значений.

Вид (kind)НазваниеАдресНастройки (options)Разделы ответа
auditАудит сайтаобязателенuser_agent (select, "*") [*|Googlebot|Bingbot|YandexBot|GPTBot|ClaudeBot|PerplexityBot|Google-Extended]summary, issues, robots_issues, sitemap_issues, hreflang_issues, sources, conflicts, plan, chain, checks, directives, meta, headings
seo-checkerSEO-анализ страницыобязателенcheck_links (boolean, true)summary, issues, indexability, meta, headings, content, images, links
cms-detectorCMS Detector / Определить CMS сайтаобязателенcms, signals, tech
indexability-checkerПроверка индексируемостиобязателенuser_agent (select, "*") [*|Googlebot|Bingbot|YandexBot|GPTBot|ClaudeBot|PerplexityBot|Google-Extended]; check_targets (boolean, true)verdict, conflicts, sources, targets, plan
http-status-checkerПроверка кодов ответа HTTPобязателенcheck_domain_variants (boolean, false)summary, chain, variants, headers
redirect-checkerПроверка редиректовобязателенcheck_domain_variants (boolean, false)summary, chain, variants, headers
robots-checkerПроверка robots.txtобязателенuser_agent (select, "*") [*|Googlebot|Bingbot|YandexBot|GPTBot|ClaudeBot|PerplexityBot|Google-Extended]; paths (list); custom_file (textarea)verdict, paths, ai_bots, issues, file, health
sitemap-checkerПроверка sitemap.xmlобязателенcheck_urls (boolean, true); sample_size (number, 20)summary, robots, issues, tree, sample, urls, searched
robots-meta-checkerПроверка meta robotsобязателенuser_agent (select, "*") [*|Googlebot|Bingbot|YandexBot|GPTBot|ClaudeBot|PerplexityBot|Google-Extended]; with_robots_txt (boolean, true)verdict, issues, sources, directives
canonical-checkerПроверка canonicalобязателенcheck_target (boolean, true)summary, checks, chain
link-extractorИзвлечение ссылок со страницыобязателенcheck_status (boolean, true); unique_only (boolean, false)summary, links, domains, special
link-attributesПроверка nofollow / sponsored / ugcобязателенmy_domain (domain); check_status (boolean, true)page_block, summary, links, mine
anchor-analysisАнализ анкоров ссылокобязателенcommercial_words (textarea)types, anchors, words, conflicts
meta-extractorИзвлечение метатеговобязателенsummary, tags, cards, code
hreflang-checkerПроверка hreflangобязателенcheck_return (boolean, true)summary, alternates, reciprocal, issues
headings-extractorИзвлечение заголовков H1–H6не нуженhtml (textarea)tiles, outline
pagespeed-checkerPageSpeed / Core Web Vitals Checkerобязателенstrategy (select, "mobile") [mobile|desktop]summary, vitals, field, opportunities
broken-linksПроверка «битых» ссылокобязателенmode (select, "page") [page|site]; max_pages (number, 100); check_status (boolean, true); urls (textarea)summary, broken, redirects, skipped
internal-linksПроверка внутренних ссылокобязателенmode (select, "page") [page|site]; max_pages (number, 100); check_status (boolean, true); subdomains_internal (boolean, false); urls (textarea)summary, links, dead_ends, orphans
external-linksПроверка внешних ссылокобязателенmode (select, "page") [page|site]; max_pages (number, 100); check_status (boolean, true); subdomains_internal (boolean, false); urls (textarea)summary, links, skipped
sitemap-generatorГенератор sitemap.xmlне нуженurls (textarea); alternates (boolean, true); locales (text, "uk, ru, en"); lastmod (date); changefreq (select) [|always|hourly|daily|weekly|monthly|yearly|never]; priority (number)numbers, xml, notes, next
json-ld-validatorПроверка JSON-LDне нуженcode (textarea)summary, blocks, issues
hreflang-generatorГенератор hreflangне нуженversions (rows); x_default (select); format (select, "html") [html|xml|http]; site_country (country, "UA"); comments (boolean); heads (textarea)numbers, code, checks, map

Списки адресов и файлы

Список адресов и обход сайта идут в очередь: запрос отвечает сразу, а результат забирается по ссылке.

curl -X POST https://seo-gen.com.ua/api/public/tools/http-status-checker/batch \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"list":"https://example.com/\nhttps://example.com/nope\nне адрес"}'

В ответе 202: номер задания, ссылка на него, сколько адресов принято и перечень отклонённых строк сразу — с номером строки и причиной.

{
  "data": {
    "id": "537f4024-0537-4abc-b564-56dc55569538",
    "url": "/api/public/tools/jobs/537f4024-0537-4abc-b564-56dc55569538",
    "accepted": 2,
    "rejected": [ { "code": "TARGET_INVALID", "line": 3, "value": "не адрес" } ],
    "status": "queued"
  },
  "limit": { "remaining": 4997 }
}

Список можно прислать и файлом — multipart/form-data, поле file; подходят CSV, XLSX и TXT до 5 МБ:

curl -X POST https://seo-gen.com.ua/api/public/tools/http-status-checker/batch \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ" \
  -F "file=@spisok.csv"

Ход и результат — той же ссылкой. Поле job.status проходит queuedrunningdone, а job.done и job.total показывают продвижение:

curl https://seo-gen.com.ua/api/public/tools/jobs/537f4024-0537-4abc-b564-56dc55569538 \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ"

Готовый результат выгружается файлом — таблицей или JSON:

curl -OJ https://seo-gen.com.ua/api/public/tools/jobs/537f4024-0537-4abc-b564-56dc55569538/export.csv \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ"
curl -OJ https://seo-gen.com.ua/api/public/tools/jobs/537f4024-0537-4abc-b564-56dc55569538/export.json \
  -H "Authorization: Bearer tlk_ВАШ_КЛЮЧ"

Обход сайта — тот же маршрут, но вместо списка один адрес и options.mode = "site". Сколько страниц обойти, говорит тариф.

Что считается расходом

  • Одна проверка POST …/run — одна единица месячного объёма тарифа и одно обращение по ключу.
  • Список из N адресов — N единиц объёма: каждый адрес это отдельный поход к чужому сайту.
  • Обход сайта — одна единица в миг постановки в очередь; сколько страниц он пройдёт, ограничивает тариф.
  • Ответ из кеша (cached: true) объём всё равно тратит: объём считает обращения, а не походы.
  • Отказ по пределу (QUOTA_EXCEEDED, API_QUOTA_EXCEEDED) приходит ДО работы: считать чужой сайт и потом говорить «не положено» мы не станем.
  • Просмотр хода задания и выгрузка результата объём не тратят.

Отказы

Отказ — это всегда тело с двумя полями: code машинным словом и error подписью на языке запроса (язык берём из заголовка Accept-Language). Тот же код дублируется заголовком X-CMS-Error-Code.

КодHTTPЧто значит
TOOL_KEY_INVALID401Ключ не подошёл: не тот, отозванный, с другого сайта или переданный не тем способом.
TOOL_KEY_NOT_ALLOWED403Ключ есть, но тариф его больше не позволяет — подписку понизили или она кончилась.
TOOL_KIND_UNKNOWN400Такого вида инструмента нет.
TOOL_NOT_IMPLEMENTED501Вид объявлен, но он ещё в разработке.
TARGET_INVALID422Адрес не передали или он не похож на адрес.
TARGET_NOT_ALLOWED400Адрес не ведёт в открытый интернет: внутренняя или служебная сеть. За такими мы не ходим.
TARGET_UNREACHABLE502Домен не существует или не отвечает. Это ответ О ЧУЖОМ САЙТЕ, а не наша поломка.
TARGET_TIMEOUT504Сайт не ответил за 10 секунд.
TARGET_TOO_BIG413Страница больше 5 МБ — дальше мы не читаем.
TARGET_TOO_MANY_REDIRECTS502Цепочка переадресаций длиннее пяти шагов.
OUR_BUDGET504Вышел НАШ срок на весь прогон. Это не поломка сайта.
QUOTA_EXCEEDED429Месячный объём тарифа исчерпан. Счёт начнётся заново в следующем месяце.
API_QUOTA_EXCEEDED429Исчерпан месячный объём обращений именно ПО КЛЮЧУ — он меньше объёма проверок.
RATE_LIMIT_EXCEEDED429Часовой предел гостя. У ключа на оплаченном тарифе его нет — там считает месячный объём.
BATCH_TOO_LARGE422В списке больше адресов, чем позволяет тариф. Объём за это не списан.
BATCH_BUSY429Уже идут два задания сайта — дождитесь конца одного из них.
FILE_UNREADABLE422Файл прочитать не удалось. Подходят CSV, XLSX и TXT.
JOB_NOT_FOUND404Задания нет: истёк его срок (семь дней) или оно с другого сайта.

Пределы и вежливость к чужим сайтам

Пределы тарифа «Профи»: 30 000 проверок в месяц, 5 000 обращений по ключу в месяц, 5 000 адресов в одном списке, обход до 50 000 страниц, пять ключей, история 365 дней. Сколько осталось — в поле limit.remaining каждого ответа.

Пределы вежливости к ЧУЖОМУ сайту не снимает ни один тариф — они не про того, кто платит, а про того, кого проверяют:

  • не больше двух одновременных запросов к одному хосту и пауза 500 мс между ними;
  • чужую страницу ждём 10 секунд, читаем первые 5 МБ, идём не больше чем по пяти переадресациям;
  • на всю одиночную проверку отведено 18 секунд: не успели — ответ приходит честно частичным (partial), а не оборванным;
  • представляемся именем SeoGenCMS-Tools — по нему нас можно закрыть в своём robots.txt;
  • одновременных заданий на сайт — два.

Проверяйте чужие сайты с той же мерой, с какой хотели бы, чтобы проверяли ваш.