Автозаполнение контрагентов по ИНН через DaData

Содержание
  1. Реквизиты руками из накладной
  2. ФНС / СПАРК / Контур.Фокус / DaData
  3. Как это работает в ScanFlow
  4. Что важно учесть
  5. FAQ
  6. Что дальше

Каждый раз, когда в потоке накладных появляется новый поставщик, у бухгалтера срабатывает один и тот же рефлекс: открыть карточку контрагента в 1С, начать набирать ИНН, потом КПП, наименование, адрес, БИК, расчётный счёт. Минута-две монотонной работы, в которой легко ошибиться — а ошибка тут же стопорит платёжку, поставка не закрыта, остатки разъезжаются.

В ScanFlow эта работа делается без человека: ИНН распознан с накладной, имя/адрес/КПП тянутся из DaData, и всё это кешируется в локальную таблицу suppliers. В статье разберём источники справочных данных по ИНН на российском рынке, почему мы выбрали DaData, что она возвращает и где подстелить соломки.

Реквизиты контрагента бьют руками из подписанной накладной

Сценарий типичный. Утром привезли товар от нового поставщика. Бухгалтер берёт ТОРГ-12 и начинает заводить контрагента в 1С. Это не одно поле — это полноценная карточка:

  • ИНН — 10 цифр для юрлица, 12 для ИП. Контрольное число в последнем разряде, но 1С его не проверяет сразу — ошибку поймаете уже на платёжке.
  • КПП — 9 цифр, у ИП пустой.
  • Полное наименование — буква в букву как в ЕГРЮЛ, потому что в платёжке оно сравнивается с тем, что у банка.
  • Юридический адрес — иногда читаемо напечатан в шапке накладной, иногда отсутствует, иногда указан фактический вместо юридического.
  • БИК и расчётный счёт — указаны не во всех ТОРГ-12, чаще придут отдельным письмом от менеджера.
  • ОКВЭД — формально не нужен для проводки, но в карточке клиента 1С обычно сохраняется.

Три минуты на контрагента, если повезло с источником, пять-семь — если ищем по сайту ФНС. Помножьте на 5-10 новых поставщиков в месяц у среднего ритейла или 50+ у крупного опта — за год набегают рабочие дни чистого набора цифр, не считая исправления ошибок.

А ошибки неизбежны. Опечатка в одной цифре ИНН не блокируется ни 1С, ни банком при создании черновика платёжки. Документ зависает, бухгалтер потом неделю разбирается, почему контрагент «есть и его как бы нет». И всё это — из-за того, что публично доступные в ЕГРЮЛ данные переписываются глазами с бумаги.

Что доступно: ФНС-выписка / СПАРК / Контур.Фокус / DaData

На российском рынке есть четыре легитимных способа получить справочные данные по ИНН. Они различаются по цене, объёму данных, наличию API и юридическому фокусу.

ФНС, бесплатная выписка из ЕГРЮЛ/ЕГРИП. Официальный, самый свежий источник. На egrul.nalog.ru по ИНН можно получить PDF-выписку со всеми реквизитами. Бесплатно. Минус один, критичный: нет публичного API. Парсить HTML — себе дороже: ФНС меняет вёрстку и режет ботов rate-limit'ом. Для автоматизации непригодно.

СПАРК-Интерфакс. Глубокая аналитическая платформа: ЕГРЮЛ + бухгалтерская отчётность + аффилированные лица + риски (банкротство, исполнительные производства, отзывы лицензий) + историческое связывание. REST API есть, документация хорошая. Цена — от $500/мес для маленького тарифа, крупные клиенты платят тысячи долларов в месяц. Имеет смысл для комплаенса, скоринга контрагентов, due diligence. Для «надо просто заполнить платёжку» — бронированный поезд против воробьёв.

Контур.Фокус. Тот же класс продукта, что СПАРК, но дешевле: 10-15 тыс. рублей в месяц за базовый тариф. REST API, покрытие тех же сценариев — карточка контрагента, риски, отчётность. Хороший выбор, если уже куплен Контур.Экстерн или Эльба и интеграция в одну экосистему даёт скидку. Но всё равно инструмент для compliance, не для «достань мне название и КПП».

DaData. Самый лёгкий из четырёх. Специализированный сервис справочной информации — адреса, ФИО, банки, организации. Никакой аналитики, рисков и связей. Зато: REST API из коробки, бесплатный лимит 10 000 запросов/сутки на разработчика, ответ за 100-300 мс, и в карточке организации ровно то, что нужно для платёжки — наименование, адрес, ОГРН, КПП, ОКВЭД, статус. Платные тарифы — от $5-10/мес за 100K запросов.

Резюме: «по ИНН получить реквизиты, чтобы заполнить карточку и платёжку» — DaData sweet spot. Если задача шире и включает проверку благонадёжности — берите СПАРК или Контур.Фокус, DaData кладите поверх как лёгкий быстрый кеш. У нас так и сделано: DaData основной источник, compliance оставляем клиенту (если ему это вообще нужно).

Как это работает в ScanFlow

Архитектура простая: распознали ИНН → проверили локальный кеш в таблице suppliers → если нет, дёрнули DaData → положили результат обратно в кеш → отдали в UI на подтверждение. Дальше — три блока с подробностями.

DaData API: что возвращает по ИНН

Endpoint один и простой: POST https://suggestions.dadata.ru/suggestions/api/4_1/rs/findById/party. Авторизация — заголовком Authorization: Token <ваш ключ>, тело запроса — {"query": "<ИНН>"}. Ответ — массив suggestions, где каждый элемент содержит структуру data с реквизитами организации.

// POST /suggestions/api/4_1/rs/findById/party
// body: {"query": "7707083893"}
{
  "suggestions": [{
    "value": "ПАО СБЕРБАНК",
    "data": {
      "inn": "7707083893",
      "kpp": "773601001",
      "ogrn": "1027700132195",
      "name": {
        "full": "Публичное акционерное общество \"Сбербанк России\"",
        "short": "ПАО Сбербанк"
      },
      "address": { "value": "117997, Москва, ул. Вавилова, д. 19" },
      "okved": "64.19",
      "state": { "status": "ACTIVE" },
      "type": "LEGAL"
    }
  }]
}

В коде нас интересуют четыре поля: name.full (или value как fallback) — для отображения в UI и в платёжке, kpp — для шапки контрагента, address.value — юридический адрес, и сам inn — для подтверждения, что DaData вернула того, о ком спросили. Текущая обёртка в репозитории — src/sber/dadata.ts, lookupPartyByInn(inn) — возвращает компактный объект { name, inn, kpp, address } или null, если ИНН не найден.

Случай «пустой suggestions» бывает редко. Чаще всего это значит, что ИНН на накладной распознался с ошибкой — цифра уехала, и итоговое значение не соответствует ни одной организации в ЕГРЮЛ. Реже — ИНН давно ликвидированного юрлица. В обоих случаях UI показывает «контрагент не найден» и даёт оператору заполнить карточку вручную.

Локальная таблица suppliers (PK=ИНН) — почему кешируем

Первый раз в жизни ScanFlow увидел поставщика — да, сходил в DaData. Но к пятой накладной от того же поставщика дёргать внешний API уже бессмысленно: имя/адрес/КПП меняются редко, а в реквизитах появляются вещи, которых DaData не знает в принципе — расчётный счёт получателя в банке, БИК, корсчёт, плюс ручные правки оператора (опечатка в адресе, более удобное сокращение в коротком имени, дополнительные заметки в поле notes). Поэтому у нас локальный кеш — таблица suppliers в MariaDB.

CREATE TABLE suppliers (
  inn               VARCHAR(12) PRIMARY KEY,
  name              VARCHAR(512) NOT NULL,
  kpp               VARCHAR(9),
  account           VARCHAR(20),
  bank_bic          VARCHAR(9) NOT NULL,
  bank_corr_account VARCHAR(20),
  bank_name         VARCHAR(255),
  address           TEXT,
  verified          TINYINT DEFAULT 0,
  source            VARCHAR(32),       -- 'dadata' | 'manual' | 'invoice'
  notes             TEXT,
  created_at        TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at        TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  last_used_at      TIMESTAMP NULL
);

Ключевые детали схемы. Первичный ключ — ИНН, а не суррогатный id: ИНН по природе своей уникален, и так репозиторий получает UPSERT бесплатно (supplierRepo.upsert делает findByInn → create/update в одну транзакцию). Поле source позволяет понять, откуда пришли данные: автоматически из DaData, вручную ввёл оператор или вытащили эвристикой из текста накладной. last_used_at — для сортировки по релевантности в списках и для возможной чистки давно не используемых записей.

Auto-create работает так: при первой отправке накладной в Сбер пользователю показывается модалка подтверждения реквизитов. В этой модалке поля prefill-ятся данными, которые мы достали из накладной (имя + ИНН + КПП + адрес — что распозналось). Если ИНН ещё не в локальном кеше, делается опциональный DaData-lookup (если в окружении задан DADATA_API_KEY), и результаты дозаполняются в форму. Оператор может всё поправить — модалка дружелюбная, поля редактируемые. После подтверждения карточка уезжает в suppliers с source='manual' или source='dadata' в зависимости от того, что было основным источником.

Отдельная страница /#/suppliers даёт CRUD по этой же таблице — список с поиском по имени/ИНН, форма редактирования, кнопка «обновить из DaData». Полезно, например, после переезда поставщика на новый юридический адрес — оператор открывает карточку, жмёт «обновить», DaData отдаёт свежие данные, оператор сохраняет.

Сравнение DaData / СПАРК / Контур.Фокус по 4 параметрам

Чтобы у выбора DaData была опорная база, разложим четыре сервиса по четырём параметрам.

1. Цена. DaData — бесплатно до 10K запросов/сутки, дальше от $5-10 в месяц. ФНС — бесплатно. Контур.Фокус — 10-15 тысяч рублей в месяц. СПАРК — от $500 в месяц для маленького тарифа, в реальности крупные клиенты платят кратно больше. DaData выигрывает за счёт того, что для нашего use-case бесплатного лимита хватает с большим запасом.

2. Скорость ответа. DaData возвращает ответ за 100-300 мс. СПАРК и Контур.Фокус — 500-1000 мс, плюс у них API устроены сложнее: иногда чтобы получить карточку, нужно сначала сделать поиск, потом запросить детали. ФНС — нет API, секунды на запрос страницы выписки. DaData выигрывает по скорости.

3. Полнота данных. Тут DaData проигрывает СПАРК и Контур.Фокус, и это очевидно — она вообще не аналитический сервис. У СПАРК/Контура есть финансовая отчётность, история собственников, риски, исполнительные производства, лицензии, госконтракты. У DaData — справочная карточка из ЕГРЮЛ плюс ОКВЭД и статус, и всё. Если задача про compliance — DaData мало, нужен СПАРК или Контур. Если задача про реквизиты для платёжки — данных DaData ровно столько, сколько надо.

4. Удобство интеграции. DaData — один endpoint, один тип запроса, один заголовок авторизации. Контракт стабильный (4_1 версия живёт годами без breaking changes). У СПАРК и Контура API богаче, но и сложнее: больше методов, больше состояний, больше edge-кейсов. ФНС — интеграции в традиционном смысле нет.

В итоге для задачи «вытащить реквизиты по ИНН для автоматического заполнения карточки контрагента и платёжки» DaData выигрывает по трём из четырёх параметров. Проигрывает только по полноте данных — но эта полнота нам не нужна в данной точке пайплайна. Если у конкретного клиента есть собственный СПАРК-доступ и он хочет дополнительно прогонять контрагентов через risk-проверку — это отдельный архитектурный слой, который к ScanFlow подключается как опциональный middleware.

Что важно учесть

Два аспекта DaData, которые легко не заметить на стадии прототипа и потом удивляться продакшен-багам.

DaData не проверяет, действующий ли контрагент

В ответе есть поле data.state.status с возможными значениями: ACTIVE (организация действует), LIQUIDATING (в процессе ликвидации), LIQUIDATED (ликвидирована), BANKRUPT (признана банкротом), REORGANIZING (реорганизуется). Информация сама по себе ценная, но интерпретация — на стороне клиента. DaData ничего не блокирует и ничего не запрещает: она вам данные отдаст по любому ИНН, который физически существовал в ЕГРЮЛ когда-либо.

В ScanFlow мы статус сохраняем (в поле notes или отдельным флагом — в зависимости от версии миграции) и показываем в UI рядом с именем поставщика. Но не блокируем создание карточки или платёжки. Логика тут такая: «ликвидируется» не значит «нельзя ему сегодня отгрузить заказ». Поставщик может полгода находиться в процессе ликвидации, продолжая отгружать товар, и нам через ScanFlow всё это нужно нормально провести. Решение «работать ли с организацией в стадии ликвидации» — это бизнес-решение, а не техническое.

DaData — это reference data, а не compliance. Распространённая ошибка — использовать DaData в качестве «проверки благонадёжности контрагента». Не делайте так. У DaData нет данных о судебных делах, исполнительных производствах, отзыве лицензий, аффилированных лицах, госконтрактах, бенефициарах. Если ваш бизнес-процесс требует KYC, due diligence, антимонопольных проверок — берите СПАРК-Интерфакс, Контур.Фокус, Чек-Индекс или специализированные сервисы. DaData отвечает на вопрос «как зовут этого ИНН и где он зарегистрирован», а не «безопасно ли с ним работать».

Лимит 10 000 запросов/сутки на бесплатном тарифе

Free tier DaData — 10 000 запросов в сутки на один API-ключ. Для типичного потока ScanFlow (среднее SMB-предприятие, 20-50 накладных в день, из них половина — повторные поставщики) это с очень большим запасом: реальное потребление редко превышает 20-30 запросов за день. Но есть один сценарий, в котором лимит можно выработать — batch-импорт исторических данных.

Сценарий такой: клиент только что подключился, у него в учётной системе есть архив на пару тысяч накладных, и он хочет одной операцией прогнать их через ScanFlow. В этот момент пайплайн распознаёт сотни ранее невиданных ИНН подряд, и каждый из них стучится в DaData. Если в очереди тысяча уникальных ИНН — мы съели десятую часть дневного лимита одним заходом.

Решение здесь двухуровневое. Во-первых, локальный кеш suppliers — это и есть наша основная защита: повторные ИНН лимит не тратят, потому что вообще не идут в API. Во-вторых, если очень нужно прогнать большой архив — есть платные тарифы DaData, начинаются от $5-10 в месяц за 100K запросов и масштабируются дальше. Для разового prewarm-импорта проще взять платный пакет на один месяц.

💡

Прогрейте кеш заранее. Если у вас уже есть список основных поставщиков (например, выгрузка из 1С или просто XLSX-файл с ИНН) — закиньте его в ScanFlow одним batch'ем во время онбординга. DaData один раз заполнит карточки, они лягут в локальные suppliers, и дальше при распознавании накладных вы будете попадать в кеш почти всегда. Это второй по значимости источник экономии трафика после правильного выбора модели — и единственный, который полностью под вашим контролем.

Хороший кеш — это второй по значимости рычаг экономии в обработке потока документов. Первый — выбор модели OCR, второй — локальное хранилище справочников. Третий и дальше — оптимизации, эффект которых уже сильно меньше.

FAQ

А если ИНН ИП?

У индивидуального предпринимателя ИНН на 12 цифр (вместо 10 у юрлица), и DaData возвращает структурно другой ответ. В data.name.short будет ФИО предпринимателя одной строкой — «Иванов Иван Иванович», а в data.fio — структурированный объект с раздельными полями surname, name, patronymic. Поле data.type будет INDIVIDUAL (для юрлица — LEGAL). КПП у ИП пустой — это нормально и так и должно быть. Если случайно записать туда любые цифры, банк при создании платёжки вернёт ошибку валидации реквизитов. Платёжное поручение для ИП работает так же, как для юрлица — единственная разница, что вместо «ООО Ромашка» в поле получателя будет ФИО.

Можно ли использовать DaData для проверки контрагента (compliance)?

Нет. DaData — это reference data, не compliance-сервис. Информации о судебных делах, исполнительных производствах, банкротных процедурах, бенефициарах, аффилированных лицах, госконтрактах, лицензиях, проверках регуляторов — у DaData нет. Для KYC, due diligence, антимонопольных и санкционных проверок нужны специализированные продукты: СПАРК-Интерфакс, Контур.Фокус, Чек-Индекс, FIRA, x-COMPLIANCE. У них и базы шире, и юридический фокус другой, и часто есть прямые интеграции с государственными источниками рисков. DaData отлично закрывает свою нишу — «справочная информация для автозаполнения форм», — но за её пределы выходить не нужно.

Что если у DaData нет нашего поставщика?

Бывает редко — база DaData синхронизируется с ЕГРЮЛ/ЕГРИП и покрывает практически 100% действующих и исторических организаций. Если случилось «не нашли» — почти всегда это значит, что ИНН распознан с накладной с ошибкой. Проверьте контрольное число (есть стандартный алгоритм для 10- и 12-значных ИНН), сверьте с печатью на накладной, и если действительно очепятка — поправьте руками. Если ИНН правильный, но DaData всё равно не находит — это либо очень свежий ИНН, который ещё не успел индексироваться (бывает в первые часы после регистрации), либо организация ликвидирована давно и выкинута из реестра. В обоих случаях UI ScanFlow показывает «контрагент не найден» и даёт оператору заполнить карточку вручную; результат сохраняется в suppliers с source='manual'.

Что дальше

Мы разобрали, как ScanFlow автоматически заполняет реквизиты контрагента по ИНН с накладной, какие источники справочных данных есть на рынке, и почему DaData — это разумный выбор для задачи «заполнить платёжку без compliance-проверок». Локальный кеш suppliers бережёт API-лимит, дешёво ловит большинство повторных запросов и позволяет ручные правки поверх данных DaData.

Чтобы посмотреть, где этот кеш используется дальше по пайплайну:

Хотите попробовать на своих поставщиках — зарегистрируйтесь, первые пять распознаваний бесплатно. Загрузите 2-3 накладные от разных контрагентов, и посмотрите, как заполняется карточка из DaData и что попадает в локальный suppliers.