# Проверка товарных связок через ruBERT Адрес сервиса — https://rubert.platfomni.com. Метод `POST /v1/compare` сравнивает конкретный эталонный SKU с названием товара у партнёра. Без авторизации доступны [проверка готовности](https://rubert.platfomni.com/healthz), [формат запросов и ответов OpenAPI](https://rubert.platfomni.com/openapi.json) и [эта инструкция в Markdown](https://rubert.platfomni.com/docs.md). ## Первый запрос Поместите свой персональный ключ в переменную окружения `RUBERT_API_TOKEN` или секрет приложения. Передавайте его в заголовке `Authorization: Bearer …` по HTTPS. Отдельно указывать имя пользователя не нужно. В запросе ниже один эталон и одно партнёрское название. ```sh curl --fail-with-body --silent --show-error \ https://rubert.platfomni.com/v1/compare \ -H "Authorization: Bearer ${RUBERT_API_TOKEN:?задайте RUBERT_API_TOKEN}" \ -H 'Content-Type: application/json' \ --data-binary '{"pairs":[{"etalon_name":"Нурофен таблетки 200 мг №20","partner_name":"Нурофен таб. 200мг №20"}]}' ``` `etalon_name` и `partner_name` — обязательные исходные названия. В `etalon_brand` и `partner_brand` передайте фактические поля бренда или производителя каждой стороны, если они есть. При отсутствии значения поле можно опустить или передать `null`. Метод принимает 1–16 пар. Ответы идут в том же порядке. Для сопоставления с внутренними ID сохраните позиции массива у себя. ## Как использовать ответ Для примера с Нурофеном выше сервис вернул следующие поля. Здесь показана только часть ответа, а балл округлён. ```json { "model_version": "61031-5500-policy-b-plus-dose-v2-taste-v1", "results": [{ "input_status": "eligible", "decision": "review", "proposed_decision": "same_sku", "decision_reason": "accept_threshold_met", "scores": {"overall": 0.96409}, "predicted_reasons": [] }] } ``` Читайте `results[i].proposed_decision`. Значение `same_sku` означает, что модель предлагает совпадение. Значение `review` означает, что соответствие требует проверки. Сервис запущен в оценочном режиме. Поле `decision` всегда равно `review`. Запрос не меняет связку в каталоге. `scores.overall` — балл совпадения от 0 до 1. Порог равен 0,9575216 (округлённо). Если применимая проверка обнаружила конфликт, сервис также предлагает `review`. `predicted_reasons` содержит сработавшие проверки дозировки (`dosage`), фасовки (`pack_size`), формы (`release_form`) или объёма (`volume`). Учитывайте отдельную оценку только при `axes.<поле>.applicable=true`. Баллы не интерпретируются как вероятность ошибки в рабочем потоке. В API 1.1 поле `decision_reason` объясняет именно предложение `proposed_decision`. Поле `decision_explanation` содержит готовое пояснение на русском для оператора. Используйте код для логики приложения и текст для показа человеку. | `decision_reason` | Что означает | | --- | --- | | `below_accept_threshold` | Общий балл ниже порога совпадения. В пояснении приведены оба числа. | | `axis_conflict` | Сработала хотя бы одна проверка из `predicted_reasons`. | | `accept_threshold_met` | Балл достиг порога и проверки не отвели связку. | | `invalid_or_unsupported_input` | Сервис не смог оценить вход. Подробность в `input_reason`. | | `explicit_combined_dose_conflict` / `explicit_sibling_taste_conflict` | Обнаружено явное расхождение дозировки или вкуса. | Если обе строки равны «Парацетамол таблетки 500 мг 10 шт.» и оба производителя отсутствуют, сервис предлагает `review` с кодом `below_accept_threshold`. Общий балл 0,956592 ниже порога 0,957522. Пояснение также сообщает, что в снимке каталога у этого названия шесть активных SKU. Для выбора конкретной упаковки сверьте производителя или штрихкод. Сервис принимает текстовые поля, штрихкод можно проверить в карточке заказа. Совпадение названий само по себе не переводит пару в `same_sku`. Если `decision_reason` равен `explicit_combined_dose_conflict`, сравнение обнаружило двукратную разницу в явно записанных компонентах дозировки. Например, «Ко-Вамлосет 5+160+12,5 мг» и «Ко-Вамлосет 10+160+12,5 мг» направляются на проверку даже при высоком общем балле. Для такого ответа `predicted_reasons` может быть пустым. Перестановка компонентов и эквивалентные единицы сами по себе не вызывают срабатывания. Если `decision_reason` равен `explicit_sibling_taste_conflict`, партнёр явно указал другой вкус, который есть у соседнего SKU в той же группе. Например, эталон «Фервекс» с малиной и партнёрское название с лимоном получат `proposed_decision: review` даже при высоком балле. Правило действует для конкретных эталонов из проверенного списка. Если вкус отсутствует или не распознан, само по себе это не повод для отвода. Для каждого результата сначала проверьте `input_status`. Если он равен `ineligible`, оценка равна `null`, а причина находится в `input_reason`. Так обрабатываются, в частности, пустые после нормализации названия и пары длиннее 512 токенов. Названия не обрезаются. ## Пример на Python ```python import os import requests with requests.Session() as client: client.headers["Authorization"] = "Bearer " + os.environ["RUBERT_API_TOKEN"] pairs = [{"etalon_name": "Нурофен таблетки 200 мг №20", "partner_name": "Нурофен таб. 200мг №20"}] response = client.post("https://rubert.platfomni.com/v1/compare", json={"pairs": pairs}, timeout=(3, 10)) response.raise_for_status() for row in response.json()["results"]: print(row["proposed_decision"], row["decision_reason"], row["decision_explanation"]) ``` ## Ошибки и повторные запросы | HTTP | Что делать | | --- | --- | | 200 | Проверьте каждый элемент `results`, включая `input_status`. | | 401 | Проверьте ключ и заголовок авторизации. | | 413 | Уменьшите тело запроса. Предел — 128 КБ. | | 422 | Исправьте структуру JSON, поля или число пар (1–16). | | 502 / 503 / 504 | Сервис запускается или занят. Повторите с небольшой задержкой, учитывая `Retry-After`, если он есть. | При массовой проверке отправляйте пачки до 16 пар и переиспользуйте HTTPS-соединение. Результат запроса не имеет побочных эффектов. Заголовок `Server-Timing` показывает время вычисления на сервере в миллисекундах, без ожидания очереди и сетевого обмена. В замере 2 ноября 2026 года на 256 реальных связках медиана одиночного HTTPS-запроса составила 199 мс, 95-й перцентиль — 257 мс. Для пачки из 16 пар это 2,06 и 2,92 с за всю пачку, около 7,3 пары/с. Замер выполнен с одним клиентом и прогретым соединением. При одновременных запросах время ожидания может вырасти.