API v1

Документация RIZEL Search API

Загрузка каталога, ключи доступа, поиск и подсказки. Форматы данных, примеры запросов и обработка ошибок.

RIZEL Search принимает каталог в формате YML или JSON и возвращает результаты поиска через HTTPS API. Доступ к серверу и панели управления сайтом не нужен.

Схема подключения:

Схема подключения каталога и поискового API к RIZEL Search

Загрузите каталог товаров. Сервис обработает записи и построит поисковый индекс. При обновлении каталога поиск использует предыдущий индекс до публикации нового.

1. Что потребуется

Для подключения нужны:

  • URL магазина, например https://shop.example.com;
  • стабильные идентификаторы товаров и вариаций из вашей учётной системы;
  • способ выгрузки каталога: публичный YML-файл или JSON API;
  • backend, интеграционный модуль либо serverless-функцию, через которую проект будет обращаться к поиску;
  • активный тариф или пробный период RIZEL Search.

Ограничения по умолчанию:

  • не более 25 000 записей, включая товары и вариации;
  • до 1000 записей в одном JSON-пакете;
  • YML/XML-файл до 100 МБ;
  • поисковая строка до 256 символов;
  • размер страницы поисковой выдачи от 1 до 100.

Создание подключения

  1. Зарегистрируйтесь в кабинете RIZEL и откройте «Интеграции → Поиск».
  2. Нажмите «Подключить сайт». Кнопка доступна и в новом аккаунте без сайтов.
  3. Выберите самостоятельное подключение через API. Укажите основной HTTPS-адрес сайта без пути и параметров, например https://shop.ru, и его название.
  4. Выберите тариф. Пробный период длится 7 дней и запускается вами в кабинете после подготовки каталога.
  5. Нажмите «Добавить сайт и перейти к ключам». В открывшемся окне выберите «Импорт каталога», задайте название и выпустите ключ rzi_.... Затем выберите «Поиск» и выпустите ключ rzp_live_.... Скопируйте оба ключа до закрытия окна. Для загрузки YML через кабинет ключ импорта не требуется.
  6. Передайте первый полный каталог и дождитесь публикации индекса. В строке сайта нажмите «Запустить пробный период». Обращаться в поддержку для запуска не нужно. Ключи можно выпускать сразу, ещё до загрузки каталога.
  7. Проверьте результаты поиска по названию и артикулу, затем подключите поисковую форму на сайте.

Для Битрикс установите готовый модуль, вставьте оба ключа в его настройки, выберите каталог и запустите полную выгрузку. Для другой CMS используйте JSON API ниже или загрузите YML/XML в карточке сайта. Индексация выполняется в ночное окно; следите за статусом в таблице подключений. Получение ключа не включает поиск: нужны опубликованный индекс и действующий пробный или оплаченный период. Если ключ потерян, выпустите новый, замените его в приложении и отзовите старый в окне ключей. Пробный период предоставляется один раз для подключения. Отсчёт начинается при нажатии кнопки, а не при загрузке каталога. Если лёгкий поиск уже покрывается договором техподдержки, кнопка включит его по договору и сохранит пробный период.

2. Выбор способа загрузки каталога

YML: загрузка файла или по ссылке

Выберите YML, если ваша CMS, учётная система или интеграционный модуль уже умеет формировать товарную выгрузку. Для загрузки по ссылке нужен публичный HTTPS URL без логина и пароля, например:

text

https://shop.example.com/feeds/rizel-catalog.yml

В личном кабинете RIZEL:

  1. Создайте подключение поиска для своего сайта.
  2. Найдите блок «Обновить YML/XML-каталог» под списком подключений.
  3. Загрузите файл вручную либо укажите публичную HTTPS-ссылку.
  4. После первой проверки оставьте URL в настройках. Сервис будет периодически перечитывать его и строить новую полную версию индекса.

Для загрузки YML ключ импорта не нужен. Пример файла:

xml

<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="2026-10-14 12:00">
  <shop>
    <name>Example Shop</name>
    <company>Example Shop</company>
    <url>https://shop.example.com</url>
    <currencies>
      <currency id="RUB" rate="1"/>
    </currencies>
    <categories>
      <category id="10">Электроинструмент</category>
      <category id="11" parentId="10">Шлифовальные машины</category>
    </categories>
    <offers>
      <offer id="product-123" available="true">
        <name>Угловая шлифовальная машина Bosch GWS 18V-10</name>
        <url>https://shop.example.com/product/bosch-gws-18v-10/</url>
        <price>24990.00</price>
        <currencyId>RUB</currencyId>
        <categoryId>11</categoryId>
        <picture>https://shop.example.com/uploads/bosch-gws.jpg</picture>
        <vendor>Bosch</vendor>
        <vendorCode>06019J4002</vendorCode>
        <description>Аккумуляторная угловая шлифовальная машина.</description>
        <param name="Напряжение">18 В</param>
        <param name="Диаметр диска">125 мм</param>
      </offer>
    </offers>
  </shop>
</yml_catalog>

Для вариаций можно использовать group_id. Значение group_id становится parent_id, а запись становится торговым предложением. Сначала передайте родительскую запись без group_id:

xml

<offer id="product-123" available="true">
  <name>Футболка RIZEL</name>
  <url>https://shop.example.com/product/rizel-shirt/</url>
  <price>2990</price>
  <currencyId>RUB</currencyId>
  <categoryId>20</categoryId>
  <vendorCode>RZ-SHIRT</vendorCode>
</offer>

<offer id="offer-456" group_id="product-123" available="true">
  <name>Футболка RIZEL, чёрная, размер L</name>
  <url>https://shop.example.com/product/rizel-shirt/?attribute_size=l</url>
  <price>2990</price>
  <currencyId>RUB</currencyId>
  <categoryId>20</categoryId>
  <vendorCode>RZ-SHIRT-BLACK-L</vendorCode>
  <param name="Цвет">Чёрный</param>
  <param name="Размер">L</param>
</offer>

JSON: передача каталога через API

Через JSON API каталог передаётся пакетами из серверной части сайта или учётной системы. Время отправки и состав пакетов определяет ваша интеграция.

Для поиска и загрузки каталога используются отдельные ключи:

КлючПримерНазначение
Ключ поискаrzp_live_...Поиск, подсказки, подписка и состояние подключения
Ключ импортаrzi_...Загрузка и публикация каталога

Ключ rzp_live_* нельзя использовать для изменения каталога. Ключ импорта вы выпускаете самостоятельно в окне ключей своего API-подключения. Полные значения ключей показываются один раз; храните их в переменных окружения или защищённом хранилище секретов вашего приложения.

Не размещайте ключи в JavaScript, HTML, репозитории Git или коде мобильного приложения.

3. Модель каталога JSON

Каталог состоит из записей двух типов:

  • product: самостоятельный товар или родитель вариаций;
  • offer: торговое предложение/вариация, связанная с товаром через parent_id.

Для обычного товара достаточно одной записи product. Для товара с вариантами передайте родительский product и отдельную запись offer для каждого варианта. Когда найден артикул варианта, API возвращает родительский товар и заполняет matched_offer_id идентификатором найденной вариации.

Поля записи

ПолеТипОбязательноОписание
external_idstringдаСтабильный ID в вашей системе. Не переиспользуйте его для другого товара.
record_typeproduct или offerдаТип записи.
namestringдаНазвание, до 500 символов. HTML удаляется.
parent_idstring или nullдля offerexternal_id родительского product.
skustring или nullрекомендуетсяАртикул, vendor code или модель, до 200 символов.
brandstring или nullрекомендуетсяОтображаемое название бренда, до 500 символов.
brand_idstring или nullнетСтабильный ID бренда в вашей системе, до 100 символов.
category_pathstring или string[]рекомендуетсяПолный путь категории. Массив будет объединён через /.
category_idstring или nullнетСтабильный ID конечной категории, до 100 символов.
descriptionstring или nullнетТекстовое описание, до 50 000 символов; HTML удаляется.
attributesobjectнетХарактеристики в формате ключ: значение.
pricenumber или nullнетНеотрицательная цена без символа валюты.
currencystring или nullнетКод валюты, например RUB, до 8 символов.
availablebooleanнетНаличие. По умолчанию true.
activebooleanнетУчаствует ли запись в индексе. По умолчанию true.
urlstring или nullрекомендуетсяАбсолютный HTTP(S) URL либо путь вида /product/item/.
source_versionintegerрекомендуетсяМонотонно растущая версия записи, обычно Unix time в миллисекундах.
deletebooleanтолько при удаленииЕсли true, запись удаляется при условии, что версия не старее сохранённой.

В текущей версии JSON-импорта изображения товара напрямую не загружаются. Если критично получать image_url в поисковой выдаче, используйте YML с тегом picture или согласуйте расширение JSON-импорта со специалистом RIZEL.

Пример обычного товара

json

{
  "external_id": "product-123",
  "record_type": "product",
  "name": "Угловая шлифовальная машина Bosch GWS 18V-10",
  "parent_id": null,
  "sku": "06019J4002",
  "brand": "Bosch",
  "brand_id": "bosch",
  "category_path": ["Электроинструмент", "Шлифовальные машины"],
  "category_id": "11",
  "description": "Аккумуляторная угловая шлифовальная машина 18 В.",
  "attributes": {
    "Напряжение": "18 В",
    "Диаметр диска": "125 мм",
    "Тип двигателя": "Бесщёточный"
  },
  "price": 24990,
  "currency": "RUB",
  "available": true,
  "active": true,
  "url": "https://shop.example.com/product/bosch-gws-18v-10/",
  "source_version": 1791968400000
}

Пример товара с вариациями

Родитель:

json

{
  "external_id": "product-200",
  "record_type": "product",
  "name": "Футболка RIZEL",
  "sku": "RZ-SHIRT",
  "brand": "RIZEL",
  "category_path": ["Одежда", "Футболки"],
  "category_id": "20",
  "description": "Хлопковая футболка, несколько цветов и размеров.",
  "available": true,
  "active": true,
  "url": "https://shop.example.com/product/rizel-shirt/",
  "source_version": 1791968400000
}

Вариация:

json

{
  "external_id": "offer-456",
  "record_type": "offer",
  "parent_id": "product-200",
  "name": "Футболка RIZEL, чёрная, размер L",
  "sku": "RZ-SHIRT-BLACK-L",
  "brand": "RIZEL",
  "category_path": ["Одежда", "Футболки"],
  "category_id": "20",
  "attributes": {
    "Цвет": "Чёрный",
    "Размер": "L"
  },
  "price": 2990,
  "currency": "RUB",
  "available": true,
  "active": true,
  "url": "https://shop.example.com/product/rizel-shirt/?attribute_size=l",
  "source_version": 1791968400000
}

Правила идентификаторов:

  • ID должны быть строками и оставаться неизменными между выгрузками;
  • ID товара и предложения могут быть числовыми строками, но префиксы вроде product- и offer- упрощают диагностику;
  • parent_id вариации должен в точности совпадать с external_id родителя;
  • уникальность определяется парой record_type + external_id;
  • изменение source_version должно увеличивать число; старые версии не перезаписывают более новые данные.

4. Первая полная загрузка JSON

Для полной загрузки:

  1. Создать уникальный snapshot_id, начинающийся с full-.
  2. Передать все товары и вариации пакетами до 1000 записей.
  3. Вызвать /v1/catalog/snapshots/complete после успешной передачи всех пакетов.

Префикс full- обязателен для полной синхронизации. После успешной публикации сервис удалит из внутреннего каталога записи, которых нет в новом snapshot. Если хотя бы один пакет не загрузился, не вызывайте snapshots/complete: исправьте ошибку и повторите пакет с тем же idempotency_key.

Шаг 1. Идентификатор выгрузки

Snapshot объединяет пакеты одной выгрузки. Задайте ему уникальный идентификатор:

bash

SNAPSHOT_ID="full-catalog-$(date -u +%Y%m%dT%H%M%SZ)"

Все пакеты одной выгрузки должны иметь одинаковый snapshot_id.

Шаг 2. Передача пакетов

bash

curl --fail-with-body -X POST "https://rizel.ru/v1/catalog/batches" \
  -H "Authorization: Bearer rzi_ВАШ_КЛЮЧ_ИМПОРТА" \
  -H "Content-Type: application/json" \
  -d '{
    "snapshot_id": "full-catalog-20261014T090000Z",
    "idempotency_key": "full-catalog-20261014T090000Z-batch-0001",
    "records": [
      {
        "external_id": "product-123",
        "record_type": "product",
        "name": "Угловая шлифовальная машина Bosch GWS 18V-10",
        "sku": "06019J4002",
        "brand": "Bosch",
        "category_path": ["Электроинструмент", "Шлифовальные машины"],
        "price": 24990,
        "currency": "RUB",
        "available": true,
        "active": true,
        "url": "https://shop.example.com/product/bosch-gws-18v-10/",
        "source_version": 1791968400000
      }
    ]
  }'

У каждого пакета должен быть собственный idempotency_key, например ...-batch-0001, ...-batch-0002. При повторе запроса с тем же ключом API вернёт прежний результат и replayed: true.

Успешный ответ:

json

{
  "accepted": 1,
  "rejected": 0,
  "errors": [],
  "request_id": "c30d6d92-c9e9-46cc-98aa-b3b253dd19ad"
}

Даже при HTTP 200 часть записей может быть отклонена. Перед завершением snapshot проверьте ответ каждого пакета:

  • rejected равно 0;
  • массив errors пуст;
  • accepted равен количеству отправленных записей.

Если часть записей отклонена, исправьте данные и отправьте весь каталог в новом snapshot. Завершение неполной выгрузки удалит из нового индекса пропущенные товары.

Шаг 3. Завершение и постановка в очередь

bash

curl --fail-with-body -X POST "https://rizel.ru/v1/catalog/snapshots/complete" \
  -H "Authorization: Bearer rzi_ВАШ_КЛЮЧ_ИМПОРТА" \
  -H "Content-Type: application/json" \
  -d '{
    "snapshot_id": "full-catalog-20261014T090000Z",
    "idempotency_key": "full-catalog-20261014T090000Z-complete"
  }'

Ответ HTTP 202:

json

{
  "job_id": 381,
  "status": "queued",
  "request_id": "5f96912d-51ef-45fd-b0df-b46fd82b7892"
}

queued означает, что каталог принят, но индекс ещё не опубликован. Построение может выполняться в установленное сервисом окно индексации. Не отправляйте новый полный snapshot, пока предыдущий не обработан.

Запрос состояния подключения:

bash

curl --fail-with-body "https://rizel.ru/v1/connection/status" \
  -H "Authorization: Bearer rzi_ВАШ_КЛЮЧ_ИМПОРТА"

Пример ответа:

json

{
  "store_id": 17,
  "domain": "shop.example.com",
  "plan": "medium",
  "status": "active",
  "access": {
    "allowed": true,
    "source": "paid",
    "ends_at": "2027-01-14T00:00:00.000Z"
  },
  "index_ready": true,
  "request_id": "72fae802-cbb0-4401-a347-fb79233e675f"
}

Для проверки конкретной выгрузки используйте номер задания из ответа завершения:

bash

curl --fail-with-body "https://rizel.ru/v1/catalog/jobs/381" \
  -H "Authorization: Bearer rzi_ВАШ_КЛЮЧ_ИМПОРТА"

Ответ: {"job_id":381,"status":"queued"}. queued означает очередь, running означает обработку, done подтверждает публикацию индекса этого задания, failed означает ошибку (подробности доступны в кабинете). interrupted и staged не являются подтверждением публикации. Проверяйте статус не чаще раза в 15 секунд. Метод доступен только с ключом импорта и возвращает только задания его подключения.

После done выполните контрольные поиски по артикулу, названию и категории. При повторной выгрузке index_ready может быть true из-за предыдущего индекса, поэтому для подтверждения обновления нужен статус конкретного задания.

5. Обновление и удаление товаров

Для регулярного обновления передавайте полный каталог:

  1. Создавать новый full-... snapshot.
  2. Передавать все актуальные активные товары и вариации.
  3. Проверять ответы каждого пакета.
  4. Завершать snapshot.

Товар, отсутствующий в новом полном snapshot, будет удалён из внутреннего каталога после успешной публикации нового индекса.

Для удаления отдельного товара передайте запись:

json

{
  "external_id": "product-123",
  "record_type": "product",
  "name": "deleted",
  "delete": true,
  "source_version": 1792054800000
}

Поле name обязательно и при удалении. У товара с вариантами удалите родительский product и каждую запись offer отдельно. При полной выгрузке достаточно исключить эти записи из каталога.

6. Серверная интеграция

Где хранить ключи

Храните адрес API и ключи в переменных окружения backend-приложения:

dotenv

RIZEL_SEARCH_URL=https://rizel.ru
RIZEL_SEARCH_KEY=rzp_live_ВАШ_КЛЮЧ_ПОИСКА
RIZEL_IMPORT_KEY=rzi_ВАШ_КЛЮЧ_ИМПОРТА

Не добавляйте эти значения в клиентский JavaScript, HTML, мобильное приложение, публичный репозиторий или ответы собственного API. Если ключ оказался раскрыт, отзовите его и выпустите новый.

Подготовка записей

Сопоставьте поля вашей базы с полями из раздела 3. В примере ниже используются поля исходной системы id, title, article и updated_at_ms. Замените их своими.

php

function toRizelProduct(array $source): array
{
    return [
        'external_id' => 'product-' . $source['id'],
        'record_type' => 'product',
        'name' => $source['title'],
        'parent_id' => null,
        'sku' => $source['article'] ?? null,
        'brand' => $source['brand'] ?? null,
        'category_path' => $source['category_path'] ?? [],
        'description' => strip_tags($source['description'] ?? ''),
        'attributes' => $source['properties'] ?? [],
        'price' => isset($source['price']) ? (float)$source['price'] : null,
        'currency' => $source['currency'] ?? 'RUB',
        'available' => (bool)($source['available'] ?? true),
        'active' => (bool)($source['active'] ?? true),
        'url' => $source['url'] ?? null,
        'source_version' => (int)$source['updated_at_ms'],
    ];
}

Для варианта товара создайте отдельную запись offer; её parent_id должен совпадать с external_id родительской записи product.

HTTP-запросы на PHP

Для примера требуется PHP с расширением cURL:

php

function rizelPost(string $path, array $payload, string $key): array
{
    $baseUrl = rtrim((string)getenv('RIZEL_SEARCH_URL'), '/');
    $curl = curl_init($baseUrl . $path);
    curl_setopt_array($curl, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $key,
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode(
            $payload,
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR
        ),
    ]);

    $raw = curl_exec($curl);
    if ($raw === false) {
        throw new RuntimeException(curl_error($curl));
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $body = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
    if ($status < 200 || $status >= 300) {
        throw new RuntimeException($body['error']['message'] ?? "RIZEL API HTTP {$status}");
    }
    return $body;
}

Получайте каталог из своей базы постранично, преобразуйте записи и отправляйте их пакетами по 200–1000 элементов. Для каждого пакета проверяйте rejected, errors и accepted; завершайте snapshot только после успешной загрузки всех пакетов. Не собирайте большой каталог целиком в памяти.

Полную синхронизацию запускайте фоновой задачей или системным cron, а не внутри пользовательского HTTP-запроса. Записывайте snapshot_id, номера пакетов, job_id и request_id в журнал интеграции. Не запускайте две полные выгрузки одновременно; используйте блокировку, доступную в вашей инфраструктуре.

7. Подключение поиска к сайту

Ключ поиска должен использоваться только backend-частью проекта. Браузер или мобильное приложение обращается к вашему backend, а тот добавляет секретный ключ и отправляет запрос в RIZEL. Так ключ не попадает к конечному пользователю.

Пример серверного запроса PHP:

php

function rizel_search(string $query, int $page = 1): array
{
    return rizelPost('/v1/search', [
        'q' => $query,
        'page' => max(1, $page),
        'page_size' => 20,
        'filters' => ['available' => true],
    ], (string)getenv('RIZEL_SEARCH_KEY'));
}

Прямой запрос для проверки:

bash

curl --fail-with-body -X POST "https://rizel.ru/v1/search" \
  -H "Authorization: Bearer rzp_live_ВАШ_КЛЮЧ_ПОИСКА" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "Bosch GWS 18",
    "page": 1,
    "page_size": 20,
    "filters": {
      "available": true,
      "brand": "Bosch",
      "price_min": 1000,
      "price_max": 50000
    }
  }'

Доступные фильтры:

ФильтрТипОписание
availablebooleanПоказывать доступные или недоступные позиции.
brandstringТочное значение бренда из каталога.
categorystringТочное значение category_path.
price_minnumberМинимальная цена включительно.
price_maxnumberМаксимальная цена включительно.

Основные поля ответа:

json

{
  "items": [
    {
      "external_id": "product-123",
      "matched_offer_id": null,
      "record_type": "product",
      "name": "Угловая шлифовальная машина Bosch GWS 18V-10",
      "sku": "06019J4002",
      "brand": "Bosch",
      "category": "Электроинструмент / Шлифовальные машины",
      "price": 24990,
      "currency": "RUB",
      "available": true,
      "url": "https://shop.example.com/product/bosch-gws-18v-10/",
      "position": 1
    }
  ],
  "found": 1,
  "page": 1,
  "page_size": 20,
  "index_version": 52,
  "mode": "exact",
  "query_variants": ["Bosch GWS 18"],
  "corrected_query": null,
  "request_id": "a307377c-a66a-40d6-a954-c508118a43f1"
}

Для найденной вариации external_id, название и URL относятся к родительскому товару, а matched_offer_id содержит ID вариации. Это позволяет открыть обычную карточку товара и при необходимости выбрать найденную вариацию.

8. Поисковые подсказки

bash

curl --fail-with-body -X POST "https://rizel.ru/v1/search/suggestions" \
  -H "Authorization: Bearer rzp_live_ВАШ_КЛЮЧ_ПОИСКА" \
  -H "Content-Type: application/json" \
  -d '{"q":"шлифовальная маш","limit":8}'

Запрос должен содержать от 2 до 256 символов. Подсказки используют тот же опубликованный каталог, что и основной поиск, и могут возвращать товары, бренды, категории и поисковые фразы.

Отправляйте запрос подсказок через 200–300 мс после последнего нажатия клавиши (debounce). Если пользователь продолжил ввод, отмените предыдущий запрос.

9. Подписка и лимиты

bash

curl --fail-with-body "https://rizel.ru/v1/subscription" \
  -H "Authorization: Bearer rzp_live_ВАШ_КЛЮЧ_ПОИСКА"

Ответ содержит выбранный тариф, источник доступа, даты периода и расход лимита:

json

{
  "plan": "medium",
  "access": {
    "allowed": true,
    "source": "paid",
    "starts_at": "2026-10-14T00:00:00.000Z",
    "ends_at": "2027-01-14T00:00:00.000Z"
  },
  "usage": {
    "period": "2026-10-01",
    "requests": 1842,
    "model_calls": 217,
    "request_limit": 50000
  },
  "request_id": "2b67db77-405e-489a-9b4f-8b125a982c43"
}

После окончания оплаченного периода ключ сохраняется, но поиск возвращает HTTP 403. После регистрации следующего оплаченного периода тот же ключ снова начинает работать; перевыпускать его не требуется.

Лимиты по умолчанию:

  • burst до 10 запросов;
  • восстановление примерно 5 запросов в секунду;
  • до 50 000 основных поисковых запросов в месяц на подключение.

10. Ошибки и повторные запросы

Единый формат ошибки:

json

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Слишком много запросов",
    "request_id": "5a24c154-a90d-48cc-8e56-74c13cc9ba89",
    "retryable": true
  }
}
HTTPКодЧто делать
400INVALID_QUERY, INVALID_BATCH, INVALID_SNAPSHOTИсправить запрос; автоматически без изменений не повторять.
401INVALID_KEYПроверить тип ключа, пробелы и отзыв ключа.
403SEARCH_UNPAID, TRIAL_EXPIRED, SEARCH_BLOCKEDПроверить подписку или обратиться в поддержку.
409EMPTY_SNAPSHOT, CATALOG_LIMITПроверить snapshot и объём каталога.
429RATE_LIMITEDПовторить с exponential backoff и случайной задержкой.
503INDEX_NOT_READY, SERVICE_UNAVAILABLEПовторять только при retryable: true.

Для ответов 429 и retryable 503 используйте задержки примерно 1, 2, 4, 8 секунд с небольшим случайным отклонением. Сохраняйте request_id из ошибки: он нужен поддержке для поиска запроса в журналах.

11. Контрольный список запуска

  • Подключение сайта создано в кабинете RIZEL.
  • Выбран способ загрузки: YML или JSON API.
  • Ключи находятся только на backend и не попадают в браузер.
  • У каждого товара стабильный external_id.
  • У вариаций заполнен parent_id, совпадающий с ID родителя.
  • Артикулы находятся в sku, а не только в названии или описании.
  • Категория передаётся полным путём.
  • Цена передаётся числом, валюта указана в отдельном поле.
  • Все batch-ответы имеют rejected: 0.
  • snapshots/complete вызывается только после всех пакетов.
  • Первый индекс получил index_ready: true.
  • Проверены точный артикул, часть названия, категория и запрос в неверной раскладке.
  • Проверены подсказки и переходы на реальные URL товаров.
  • Настроена регулярная полная выгрузка без параллельных запусков.
  • Настроены журналирование request_id и повторы временных ошибок.

12. Адреса API

  • интерактивная OpenAPI-документация: https://rizel.ru/search-api-docs/;
  • JSON-схема OpenAPI: https://rizel.ru/v1/openapi.json;
  • загрузка пакета: POST https://rizel.ru/v1/catalog/batches;
  • завершение snapshot: POST https://rizel.ru/v1/catalog/snapshots/complete;
  • поиск: POST https://rizel.ru/v1/search;
  • подсказки: POST https://rizel.ru/v1/search/suggestions;
  • состояние: GET https://rizel.ru/v1/connection/status;
  • подписка и расход лимита: GET https://rizel.ru/v1/subscription.