Поисковое API

Данные о сайтах и организациях из открытых источников. Всё через GET.

Как звать

Каждая операция доступна двумя способами. Это одна и та же работа — разница только в том, сколько ждать.

GET https://search.the-project.it/search/<op>?…        ждём результат, но не дольше 25 с
GET https://search.the-project.it/search/async/<op>?…  сразу номер работы
GET https://search.the-project.it/search/result/<id>   результат по номеру

Синхронный вызов не быстрее — он ждёт. Если работа не уложилась в 25 секунд, он вернёт тот же номер и адрес результата, а работа продолжится: ни отмены, ни повторного запуска не происходит. Поэтому долгие операции удобнее звать сразу асинхронно.

Доступ

API открытое. Ни ключа, ни регистрации, ни заголовков — просто откройте адрес.

Единственный предел: не больше 300 запросов в час с одного адреса и 2 одновременно идущих работ. Это не про доступ и не про наши расходы — государственные реестры отвечают капчей на серию частых запросов, и предел бережёт работоспособность для всех сразу.

Ответ

Форма одна у всех операций и у всех трёх способов вызова — разбирать ответ должен один и тот же код, какую бы ручку ни дёрнули.

{
  "id": "9f1c…",              номер работы
  "op": "company",
  "status": "done",            running | done | error — что с работой
  "found": true,               нашли ли то, что искали
  "reason": null,              почему не нашли; заполнен при found = false
  "sources": {                 кто из источников ответил, а кто нет
    "egrul": { "ok": true },
    "courts": { "ok": false, "reason": "картотека закрыта для автозапросов" }
  },
  "warnings": [],              оговорки, не отменяющие ответ
  "data": { … },               данные; своя форма у каждой операции
  "cost": {
    "rub": 0.0312,             сколько запрос стоил нам в деньгах
    "calls": [ … ],            платные вызовы: модель, поисковый API
    "free": { "egrul": 1 }     бесплатные обращения — их считаем, но не в рублях
  },
  "started_at": "…", "finished_at": "…"
}

Два поля, которые легко перепутать

status ≠ found
status: "done" значит, что работа прошла без сбоя. Нашли ли при этом что-нибудь — говорит found. Успешный запрос, не нашедший компанию, это done и found: false.
sources
Здесь живёт главное правило сервиса: не проверили ≠ проверили и не нашли. Пустой ответ реестра и молчащий реестр выглядят одинаково в data и по-разному здесь. Прежде чем считать, что чего-то нет, посмотрите, отвечал ли источник.

Отказы

кодкогда
400негодные параметры: разбираются до начала работы, деньги не тратятся
404нет такой операции или такой работы
429слишком часто с одного адреса либо уже идёт предельное число работ

Тело отказа: {"error":{"code":"inn_invalid","message":"…"}}. Разбирать нужно code — он не меняется, в отличие от текста.

Операции

Обход сайтаидёт долго

GET /search/crawl

Находит страницы сайта: по robots.txt, карте сайта и ссылкам.

параметрчто это
siteобязателендомен или адрес example.ru
limitсколько страниц вернуть, 1–300 100

В data: site, total, pages[] — адрес, заголовок, тип, число слов

curl "https://search.the-project.it/search/crawl?site=example.ru&limit=100"

Вопрос к сайтуидёт долго

GET /search/ask

Отвечает на произвольный вопрос по содержимому сайта: «занимается ли компания изготовлением печенья».

параметрчто это
siteобязателендомен example.ru
qобязателенвопрос, до 300 знаков делает ли компания печенье
pagesсколько страниц читать, 1–20 8

В data: answer (да | нет | не нашли), summary, quotes[] — цитата и адрес страницы, looked[] — что читали

curl "https://search.the-project.it/search/ask?site=example.ru&q=%D0%B4%D0%B5%D0%BB%D0%B0%D0%B5%D1%82%20%D0%BB%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%BF%D0%B0%D0%BD%D0%B8%D1%8F%20%D0%BF%D0%B5%D1%87%D0%B5%D0%BD%D1%8C%D0%B5&pages=8"
Единственная платная операция: вызывает модель. Ответ «да» или «нет» выдаётся только с цитатой, найденной в тексте страницы дословно; невыдуманную проверку не прошедшая цитата отбрасывается, а утверждение снимается до «не нашли».

Что известно о сайте

GET /search/site-info

Реквизиты и контакты со страниц плюс whois: на кого оформлен домен.

параметрчто это
siteобязателендомен example.ru

В data: requisites — inn[], ogrn[], emails[], phones[], names[]; whois; blocked

curl "https://search.the-project.it/search/site-info?site=example.ru"

Подбор организацийидёт долго

GET /search/companies

Ищет компании по признакам реестра МСП и отчётности из ГИР БО, считает оценку надёжности.

параметрчто это
okvedкод отрасли, можно началом 86.23
regionкод региона 77
npTypeUL (юрлица) или IP (предприниматели) UL
regToработает не позже, чем с года 2020
minRevenueвыручка от, в рублях 50000000
minEmployeesработников не меньше 10
minScoreоценка не ниже, 0–100 70
profitableтолько прибыльные: true true
growingтолько с растущей выручкой: true
noRedFlagsбез критических признаков: true
hasFinanceтолько с опубликованной отчётностью: true
limitсколько компаний вернуть 20

В data: rows[] — компания, оценка, коэффициенты, признаки; total, coverageNote

curl "https://search.the-project.it/search/companies?okved=86.23&region=77&npType=UL"
Без региона отбор идёт по всей России. Для широких отраслей это сотни тысяч компаний: просмотреть их целиком нельзя, и список будет срезом по алфавиту — об этом придёт warning.

Оценка компании по ИНН

GET /search/company

Собирает карточку по государственным реестрам: ЕГРЮЛ, выписка, МСП, ГИР БО, «Прозрачный бизнес», Федресурс. Считает надёжность и вилку штрафов.

параметрчто это
innобязателенИНН: 10 цифр у юрлица, 12 у ИП 7731016390

В data: identity, card, finance, tax, fedresurs, trust, fines, courts

curl "https://search.the-project.it/search/company?inn=7731016390"
Суды и приставы не проверяются: картотека арбитражных дел и банк данных ФССП закрыты для автоматических запросов. Об этом приходит warning — «дел нет» из этого не следует.

Привязка сайта к организации

GET /search/identify

Находит реквизиты на страницах сайта и сверяет их с реестром.

параметрчто это
siteобязателендомен example.ru

В data: найденная организация и чем подтверждена связка

curl "https://search.the-project.it/search/identify?site=example.ru"
Совпадение по названию привязкой не считается: подтверждением служит только ИНН или ОГРН, напечатанный на самом сайте.

Поиск сайта организации

GET /search/website

Ищет сайт компании по ИНН через официальный поисковый API.

параметрчто это
innобязателенИНН 7731016390
nameназвание, если известно — иначе возьмём из ЕГРЮЛ
regionрегион для уточнения запроса

В data: host, url, proof — чем подтверждён адрес (ИНН, ОГРН или название)

curl "https://search.the-project.it/search/website?inn=7731016390"
Требует ключа Яндекс XML или Google CSE. Без него операция отвечает «поиск не настроен» — это не то же самое, что «сайта нет». Справочники вроде rusprofile и 2ГИС отбрасываются: сайтом компании они не являются.

Чего API не делает

Не обходит капчу и антибот-стены. Если сайт закрыт защитой от автоматических обращений, операция вернёт found: false и назовёт защиту в sources.site.reason — Cloudflare, DDoS-Guard, Qrator, Imperva, reCAPTCHA. Это ответ, с которым можно работать; «страниц нет» в таком случае было бы выводом о сайте, которого мы не делали.

Не проверяет суды и исполнительные производства: картотека арбитражных дел и банк данных ФССП закрыты для автоматических запросов. Об этом приходит warning, и «дел нет» из молчания не следует.