Последнее обновление: 26 августа 2026
Получение API-ключа
Войдите под учётной записью мерчанта, откройте Настройки → Интеграции, выберите вкладку API-ключи и создайте ключ. Скопируйте его сразу: полный ключ показывается только один раз. Отозвать ключи можно на той же странице.
Базовый URL и аутентификация
https://a.ivo.md/v1/merchant-api
Передавайте ключ в каждом запросе одним из заголовков:
X-API-Key: <ВАШ_API_КЛЮЧ>
Authorization: Bearer <ВАШ_API_КЛЮЧ>
Всегда отправляйте Accept: application/json и Content-Type: application/json, кроме загрузки файлов. Без заголовка Accept ошибки аутентификации возвращаются HTML-страницей, а не JSON.
Структура ответа
| Случай | HTTP | Тело |
|---|---|---|
| Успех | 200 | Поля эндпоинта плюс "status": "success". |
| Обработанная ошибка | 202, 403, 404, 409, 422, 500 | "status": "error", машиночитаемое message (код ошибки) и дополнительные поля контекста. |
| Ошибка аутентификации | 403 | Возникает до запуска контроллера, поэтому поля status нет — только {"message": "api_key_invalid"}. Коды: api_key_missing, api_key_invalid, merchant_not_found, integration_disabled. |
| Превышен лимит | 429 | 120 запросов в минуту с одного IP-адреса. В каждом ответе есть X-RateLimit-Limit и X-RateLimit-Remaining. |
Важно: в ответе 200 поле status верхнего уровня всегда равно строке success — оно лишь подтверждает, что запрос принят, и ничего больше. Эндпоинты, у которых есть незавершённая работа, сообщают о ней в собственном поле: sync_status у эндпоинтов синхронизации и import_status у эндпоинтов импорта.
Ответ 202 — это структура ошибки, чьё message объясняет, почему результат ещё не готов: queued, processing или pending_approval.
Проверка подключения
GET /check
Проверяет API-ключ и возвращает данные мерчанта. Это первый эндпоинт, который стоит вызвать при настройке интеграции.
Вход: ничего, кроме заголовка с API-ключом.
{
"merchant_id": "<ID_МЕРЧАНТА>",
"merchant_name": "My Shop",
"status": "success"
}
| Поле ответа | Тип | Значение |
|---|---|---|
merchant_id | string | Идентификатор мерчанта в IVO, которому принадлежит ключ. Сохраните его: он никогда не меняется и определяет учётную запись в обращениях в поддержку. |
merchant_name | string | Отображаемое название мерчанта в IVO. |
status | string | Всегда success. Подтверждает, что ключ действителен и не отозван; это не статус учётной записи мерчанта. |
Торговые точки
Каждое предложение принадлежит торговой точке (магазин, склад или пункт выдачи). Используйте ID точки из этих эндпоинтов как merchant_point_id. Если в аккаунте ровно одна точка, синхронизация выбирает её автоматически и поле можно не передавать.
GET /merchant-points
Возвращает все точки аутентифицированного мерчанта.
{
"points": [
{
"_id": "<ID_ТОЧКИ>",
"name": "Главный магазин",
"contact_person": "Ion Popescu",
"email": "[email protected]",
"phone": "+37360000000",
"street_id": "<ID_УЛИЦЫ>",
"number": "12",
"city_id": "<ID_ГОРОДА>",
"state_id": "<ID_РАЙОНА>",
"country": "MD",
"zip_code": "MD-2001",
"status": "approved",
"is_active": true
}
],
"status": "success"
}
| Поле ответа | Тип | Значение |
|---|---|---|
points[]._id | string | ID точки. Именно это значение передаётся как merchant_point_id. |
points[].name | string | Название точки. Его можно передавать как merchant_point вместо ID; совпадение точное, без учёта регистра. |
points[].contact_person, email, phone | string | С кем связываются курьер и поддержка IVO по этой точке. |
points[].street_id, number, block, entrance, floor, apartment, intercom, zip_code, city_id, state_id, country | string | Адрес забора товара. Идентификаторы местоположения — собственные ID улиц, городов и районов IVO. |
points[].status | string | pending (ждёт одобрения IVO), approved или rejected. Предложения в точке без статуса approved не видны на сайте. |
points[].is_active | boolean | Собственный переключатель мерчанта. Предложения в неактивной точке не видны. |
points[].rejection_reason | string, null | Причина отказа IVO, когда status равен rejected. |
POST /merchant-points/store
Создаёт точку. Она всегда создаётся со status: pending и is_active: true и остаётся невидимой для покупателей, пока IVO её не одобрит.
| Поле запроса | Тип | Значение |
|---|---|---|
name | string | Как точка называется в вашей системе и в панели мерчанта. |
contact_person | string | Человек, которого курьер спрашивает при заборе товара. |
email, phone | string | Контактные данные точки. |
street_id, city_id, state_id | string | Идентификаторы местоположения IVO для адреса. |
number, block, entrance, floor, apartment, intercom | string | Остальная часть адреса, чтобы курьер попал к нужной двери. |
zip_code, country | string | Почтовый индекс и код страны. |
Любое поле вне этого списка игнорируется. Ответ: {"point": { … }, "status": "success"}, где point — созданная запись вместе с новым _id.
POST /merchant-points/update/{id}
Обновляет точку, принадлежащую мерчанту. {id} — ID точки. Принимает все поля создания плюс is_active (boolean — установите false, чтобы снять с продажи весь остаток точки, ничего не удаляя). Возвращает обновлённую точку. Неизвестный ID: point_not_found (404).
POST /merchant-points/delete/{id}
Удаляет точку, принадлежащую мерчанту. Возвращает {"deleted": true, "status": "success"}. Запись удаляется логически, поэтому история сохраняется, но точку больше нельзя использовать для предложений.
Обновление существующего предложения
POST /product-offer/update
Обновляет цену или остаток уже существующего предложения без запуска импорта товаров. Это самый быстрый и дешёвый эндпоинт — используйте его для регулярного обновления цен и остатков.
{
"merchant_internal_id": "PRODUCT-123",
"merchant_point_id": "<ID_ТОЧКИ>",
"price": 1999,
"currency": "MDL",
"availability": 5,
"availability_on_order": 0
}
| Поле запроса | Тип | Значение |
|---|---|---|
offer_id | string | ID предложения в IVO. Передайте это поле или merchant_internal_id. Предложение должно принадлежать вашей учётной записи. |
merchant_internal_id | string | Ваш собственный идентификатор товара (SKU), переданный при создании предложения. Поиск ведётся только внутри вашей учётной записи. |
merchant_point_id | string | Используется только вместе с merchant_internal_id: сужает поиск до одной точки. Обязателен, если один и тот же SKU есть в нескольких точках, иначе запрос завершится с merchant_internal_id_not_unique. |
price | number | Новая цена продажи в валюте currency. Предложение с ценой 0 или пустой ценой никогда не показывается на сайте. |
currency | string | Код ISO 4217. Принимаются: MDL (по умолчанию), EUR, USD, RON, UAH, RUB, GBP. Цены в другой валюте пересчитываются для показа по сохранённому курсу IVO. |
availability | integer | Единицы, физически имеющиеся в этой точке и готовые к немедленной отгрузке. |
availability_on_order | integer | Единицы, которые вы можете поставить под заказ (склад поставщика). Товар остаётся доступным к покупке при availability равном 0, но с более длительным сроком доставки. |
Обязательно хотя бы одно из полей availability, availability_on_order, price или currency; передача только идентификатора завершается ошибкой no_fields_to_update. Опущенные поля сохраняют текущее значение. Каждое изменение записывается в историю цен и остатков предложения.
{
"offer": {
"id": "<ID_ПРЕДЛОЖЕНИЯ>",
"merchant_internal_id": "PRODUCT-123",
"product_id": "<ID_ТОВАРА>",
"merchant_point_id": "<ID_ТОЧКИ>",
"condition": "new",
"quality": null,
"price": 1999,
"currency": "MDL",
"availability": 5,
"availability_on_order": 0
},
"status": "success"
}
| Поле ответа | Тип | Значение |
|---|---|---|
offer.id | string | ID предложения. Используйте его как offer_id, чтобы в следующих вызовах не искать по SKU. |
offer.merchant_internal_id | string, null | Ваш SKU в том виде, в каком он сохранён у предложения. |
offer.product_id | string | Товар IVO (вариант), к которому привязано предложение. |
offer.merchant_point_id | string | Точка, в которой лежит остаток предложения. |
offer.condition | string | new, used или refurbished. |
offer.quality | string, null | Произвольная пометка состояния, которая различает несколько не новых предложений одного товара. |
offer.price, offer.currency, offer.availability, offer.availability_on_order | number / string / integer | Сохранённые значения после обновления. |
Ошибки: missing_identifier (422) — не передан ни offer_id, ни merchant_internal_id; no_fields_to_update (422); offer_not_found (404) — предложения нет или оно принадлежит другому мерчанту; merchant_internal_id_not_unique (409) — SKU соответствует нескольким предложениям, в теле есть count. Передайте merchant_point_id, чтобы устранить неоднозначность.
Информация о товаре и предложении
GET /product/{id}/info
В качестве {id} используйте ID предложения, а не ID товара. Предложение должно принадлежать аутентифицированному мерчанту.
{
"product": {
"id": "<ID_ТОВАРА_ПРЕДЛОЖЕНИЯ>",
"root_product_id": "<ID_ОСНОВНОГО_ТОВАРА>",
"type": "variant",
"status": "active",
"name": {"ro": "Nume", "en": "Name", "ru": "Название"},
"slug": {"ro": "nume", "en": "name", "ru": "nazvanie"},
"url": "https://ivo.md/nume/p",
"urls": {"ro": "https://ivo.md/nume/p", "en": "https://ivo.md/en/name/p", "ru": "https://ivo.md/ru/nazvanie/p"}
},
"offer": {
"id": "<ID_ПРЕДЛОЖЕНИЯ>",
"price": 1999,
"currency": "MDL",
"availability": 5,
"availability_on_order": 0
},
"history": [
{
"price": 2099,
"currency": "MDL",
"availability": 3,
"availability_on_order": 0,
"changed_at": "2026-08-20T11:04:35+03:00",
"source": "merchant_api"
}
],
"status": "success"
}
| Поле ответа | Тип | Значение |
|---|---|---|
product.id | string | Товар, к которому привязано предложение. У товара с вариантами это вариант, а не родительский товар. |
product.root_product_id | string | Основной (родительский) товар. Несколько вариантов делят его между собой, и публичная страница принадлежит именно ему. |
product.type | string | main или variant. |
product.status | string | Каталожный статус товара предложения, например active или draft. |
product.name | object | Каталожное название по языкам (ro, en, ru). Его пишет IVO, поэтому оно может отличаться от отправленного вами. |
product.slug | object | Сегмент URL для каждого языка. |
product.url | string | Публичный URL на румынском — самая короткая ссылка, которую можно дать покупателю. |
product.urls | object | Публичный URL для каждого языка. |
offer.id, offer.price, offer.currency, offer.availability, offer.availability_on_order | — | Текущие значения предложения в том виде, в каком IVO хранит их сейчас. |
history[] | array | До 100 изменений цены и остатка, начиная с самых свежих. В каждой записи есть price, currency, availability, availability_on_order, changed_at (ISO 8601) и source — какая система внесла изменение (merchant_api, api_sync и так далее). |
Ошибки: offer_not_found (404); product_not_accessible (403) — предложение принадлежит другому мерчанту; product_not_found (404); pending_approval (202) — основной товар ещё не опубликован, в теле есть product_id и product_status; product_slug_missing (422).
POST /product/info-by-sku
Тот же подробный ответ, но найденный по вашему SKU, а не по ID из IVO. Используйте его, если не храните идентификаторы IVO у себя.
{
"import_name": "daily-sync",
"merchant_internal_id": "PRODUCT-123"
}
| Поле запроса | Тип | Значение |
|---|---|---|
merchant_internal_id | string, обязательно | Ваш SKU. Поиск идёт по импортированным строкам вашей учётной записи. |
import_name | string, обязательно | Проверяется как обязательное, но поиск по нему не фильтруется: SKU ищется по всем вашим импортам. Передавайте то же имя, что и в /product/sync. |
При успехе тело совпадает с GET /product/{id}/info. Пока товар ещё проходит обработку, ответом будет структура ошибки:
| message | HTTP | Значение |
|---|---|---|
not_imported | 404 | Ни одна импортированная строка не содержит этот SKU. Сначала отправьте товар через /product/sync. |
queued | 202 | Строка ждёт обработки. Повторите запрос позже. |
processing | 202 | Строка обрабатывается прямо сейчас. Повторите запрос позже. |
pending_approval | 202 | Товар существует, но ещё не опубликован. С вашей стороны делать нечего. |
| код ошибки строки | 500 | Обработка не удалась. В теле есть import_row_id, import_id, ai_product_id, ai_error и error. |
| статус предложения строки | 404 | Строка завершилась, но предложение не создано (например, unauthorized_category). |
offer_deleted | 404 | Строка указывает на предложение, которого больше нет. |
Создание или синхронизация одного товара
POST /product/sync
Создаёт товар или обновляет существующее предложение. Повторное использование одного и того же import_name вместе со стабильным merchant_internal_id обновляет ту же строку, а не создаёт дубликаты, поэтому эндпоинт можно вызывать многократно для одного каталога.
{
"mode": "async",
"import_name": "daily-sync",
"merchant_internal_id": "PRODUCT-123",
"name": "Example Phone 256 GB Black",
"price": 1999,
"currency": "MDL",
"availability": 5,
"availability_on_order": 0,
"merchant_point_id": "<ID_ТОЧКИ>",
"brand": "Example",
"ean": "5940000000000",
"description": "Описание товара",
"images": ["https://example.com/product.jpg"]
}
| Поле запроса | Тип | Значение |
|---|---|---|
price | number, обязательно | Цена продажи, больше 0 (минимум 0.01). Должна быть обычным числом — 1999 или 1999.00, но не "1 999,00". |
name | string, обязательно без product_id | Полное название товара. IVO сопоставляет его с каталогом и создаёт по нему товар, поэтому указывайте бренд, модель и отличительные характеристики (объём памяти, цвет). Слишком расплывчатое название отклоняется с ошибкой строки too_generic. |
product_id | string | ID существующего товара IVO. Полностью обходит сопоставление с каталогом и записывает только предложение — самый быстрый путь, если товар уже известен. Если у этого товара уже есть варианты, нужно передать и offer_product_id. |
offer_product_id | string | Вариант товара product_id, к которому привязывается предложение. Обязателен, когда у основного товара есть варианты: IVO никогда не угадывает, какой вариант у вас в наличии. |
merchant_internal_id | string | Ваш стабильный идентификатор товара (SKU). Это ключ, связывающий ваш каталог с IVO при каждом следующем вызове. Настоятельно рекомендуется: без него строки сопоставляются по хешу всего запроса. |
legacy_merchant_internal_id / legacy_merchant_internal_ids | string / array | Идентификаторы, под которыми товар отправлялся раньше. Используйте их при смене схемы SKU, чтобы переиспользовать существующие строку и предложение вместо создания дубликата товара. |
import_name | string | Имя списка импорта, к которому относится товар, и ключ, по которому вы запрашиваете статус. Оно приводится к slug: пробелы и знаки препинания превращаются в _ или удаляются, длина обрезается до 64 символов ("My Daily Sync" → my_daily_sync). Пустое значение становится default. Используйте одно стабильное имя на источник. |
merchant_point_id / merchant_point | string | ID точки или её точное название. Если в аккаунте одна точка, она выбирается автоматически. |
availability | integer или string | Немедленный остаток. Текст разбирается мягко: "10 шт" → 10, "2-3" → 3, "in stock"/"da" → 1, "out of stock" и всё нераспознанное → 0. Если не передать ни availability, ни availability_on_order, немедленный остаток по умолчанию равен 1. |
availability_on_order | integer или string | Остаток, доступный под заказ; разбирается так же. |
currency | string | Код ISO 4217, по умолчанию MDL. |
condition | string | new (по умолчанию), used или refurbished. Предложение new существует одно на товар и точку; не новых предложений может быть несколько. |
quality | string | Произвольная пометка, различающая несколько не новых предложений одного товара в одной точке. |
brand | string | Название бренда. Помогает сопоставлению и используется, когда товар нужно создать. |
ean, asin, jan | string | Глобальные штрихкоды и идентификаторы товара. Самый сильный сигнал для сопоставления — передавайте их, если они есть. |
description | string | Описание товара, используется при сопоставлении и как исходный материал для нового товара. |
images (или image) | array или string | URL изображений, первое — главное. IVO скачивает их; они должны быть общедоступны. |
weight, volume | number | Вес отправления (граммы) и объём, используются при расчёте доставки. |
item_group_id, item_group_title, variant_option, variant_options | string / object | Подсказки группировки вариантов: товары с одинаковым item_group_id считаются вариантами одного родителя, а значения опций указывают, чем они отличаются (цвет, размер). |
force_reprocess | boolean | true перезапускает строку с нуля, отбрасывая прежние результаты сопоставления. Используйте для исправления неверно сопоставленной строки — не при каждой синхронизации, так как заново выполняется весь конвейер сопоставления. |
mode | string | async (по умолчанию) возвращает ответ сразу. sync удерживает соединение до завершения строки в пределах серверного лимита (по умолчанию 300 секунд) и всё равно отвечает, если работа продолжается. |
Любое другое поле сохраняется вместе со строкой, но учитывается только если его имя совпадает с колонкой импорта.
Ответы
Все три — HTTP 200 со "status": "success". О том, что произошло, говорит набор присутствующих полей.
| Возвращённые поля | Что произошло |
|---|---|
sync_status: "completed", offer_id, offer_product_id, message: "Offer saved (AI bypassed)" | Вы передали product_id: предложение записано напрямую, без сопоставления и без этапа одобрения. |
sync_status: "completed", offer_id, offer_product_id, import_id, row_id и matched_by, если использовался прежний идентификатор | Найдено и сразу обновлено существующее предложение с этим merchant_internal_id. Это обычный ответ для товара, уже имеющегося в каталоге. |
sync_status: "processing", import_id, message: "Product creation started" | Новый — или существенно переименованный — товар попал в поток импорта и одобрения. Результат запрашивайте через /product-import/status или /product/info-by-sku. |
| Поле ответа | Тип | Значение |
|---|---|---|
sync_status | string | completed — предложение существует, ничего не ожидает обработки. processing — товар поставлен в очередь, и результат нужно запросить позже. Ветвите логику именно по этому полю, а не по status. |
offer_id | string | Созданное или обновлённое предложение. Сохраните его: последующие обновления цены и остатка сведутся к одному быстрому вызову. |
offer_product_id | string | Товар IVO (вариант), к которому привязано предложение. |
import_id | string | Список импорта, в который занесён товар, — тот, что назван в import_name. |
row_id | string | Строка импорта для этого товара. |
matched_by | string | merchant_internal_id или legacy_merchant_internal_id, если предложение найдено по одному из переданных вами прежних идентификаторов. |
row_status | string | Только в mode: sync, когда ожидание истекло: состояние строки на тот момент. |
Ошибки: invalid_product_id (422), product_not_found (404), offer_product_not_found (404), offer_product_invalid (422) — вариант не принадлежит указанному основному товару, missing_offer_product_id (422), missing_merchant_point (422) — на пути с product_id не удалось определить точку, invalid_price (422), unauthorized_category (403) — у вашей учётной записи нет разрешения продавать в этой категории, integration_not_found / integration_disabled (403) — import_name называет удалённую или отключённую интеграцию, и processing_failed (422) в mode: sync вместе с error и import_id.
Синхронизация нескольких товаров
POST /product/sync-multiple
От 1 до 100 товаров в запросе. Каждый элемент products принимает ровно те же поля, что и /product/sync, плюс перечисленные ниже. Именно на этом эндпоинте строится полная синхронизация каталога.
{
"mode": "async",
"import_name": "daily-sync",
"image_base_url": "https://shop.example.com/images",
"products": [
{
"merchant_internal_id": "PRODUCT-123",
"name": "Example Phone 256 GB Black",
"price": 1999,
"availability_by_point": {
"<ID_ТОЧКИ_1>": 5,
"<ID_ТОЧКИ_2>": 2
}
}
]
}
| Поле пакета | Тип | Значение |
|---|---|---|
products | array, обязательно | От 1 до 100 объектов товаров. Больший каталог разбивайте на последовательные запросы с одним и тем же import_name. |
import_name | string | Те же правила, что и в /product/sync, и тот же список: при совпадении имени оба эндпоинта работают с одним импортом. |
mode | string | async (по умолчанию) или sync. |
image_base_url | string (URL) | Префикс, добавляемый к относительным путям изображений, чтобы фид мог отправлять /catalog/x.jpg. Сохраняется в импорте и переиспользуется при повторных попытках. |
image_split_spaces | boolean | Считать пробелы внутри значения изображения разделителями между несколькими путями. |
image_split_commas | boolean | Считать запятые внутри значения изображения разделителями между несколькими путями. |
integration_run_id | string, до 64 | Помечает все строки одного полного прогона каталога. Позволяет IVO измерять прогресс относительно реального итога прогона, а не размера одного пакета, и даёт новому прогону отбросить остатки, оставшиеся от прежней конфигурации. |
| Дополнительное поле товара | Тип | Значение |
|---|---|---|
availability_by_point | object | Остаток по точкам: {"<ID_ТОЧКИ>": 5}. Передавайте полную картину по этому SKU в одном элементе — она заменяет предыдущий снимок. Тогда товар попадает в одну строку импорта, а не в отдельную строку на каждую точку. |
availability_only | boolean | true делает элемент чистым обновлением остатка: обязательны только merchant_internal_id и availability, а name и price — нет. Неизвестные идентификаторы пропускаются, а не создают товары: это поток обновлений, а не источник товаров. |
force_reprocess | boolean | Пропускает быстрый путь существующего предложения и перезапускает сопоставление строки. |
Ответ: sync_status (completed, если все товары уже были актуальны, и processing, если строки поставлены в очередь) и import_id, а также message, если работа поставлена в очередь. По каждому товару ничего не возвращается — читайте отдельные результаты через /product-import/status или /product/info-by-sku. Запрос, не прошедший валидацию, отклоняется целиком с validation_failed (422), с указанием index проблемного товара и его errors; также возможны invalid_product_payload (422) и products_required (422).
Загрузка файла товаров
POST /product-import/upload-and-import
Отправляет весь каталог одним запросом — так же, как при загрузке из панели мерчанта. Используйте multipart/form-data.
| Поле запроса | Тип | Значение |
|---|---|---|
file | файл, обязательно | Файл каталога. Допустимые расширения: XLSX, XLS, CSV, TSV, ODS, JSON и XML. |
mode | string | async (по умолчанию) отвечает сразу после постановки файла в очередь. sync ждёт завершения импорта, по умолчанию до 300 секунд. |
import_name | string | Необязательное имя, под которым сохраняется загрузка; приводится к slug, как и везде. Передавайте его, если собираетесь опрашивать импорт: GET /product-import/status тогда находит его по этому имени. Без него импорт сохраняет имя загруженного файла, и опрашивать нужно по import_id (или по этому же имени файла). |
columns | array | Сопоставление колонок: по одной записи на каждую колонку файла, по порядку. Используйте канонические имена: name, description, brand, ean, asin, jan, weight, volume, image, availability, availability_on_order, price, price_and_currency, currency, merchant_internal_id и ignore для пропускаемых колонок. Сопоставьте несколько колонок с image, чтобы импортировать несколько изображений. Если columns не передан, IVO определяет сопоставление по строке заголовков. |
| Поле ответа | Тип | Значение |
|---|---|---|
import_id | string | Созданный импорт. Сохраните его: именно с ним вы обращаетесь к эндпоинту статуса. |
import_name | string | Имя, под которым сохранён импорт, — ваш import_name после приведения к slug или имя загруженного файла. Опрашивайте ровно этим значением. |
import_status | string | Реальное состояние импорта: pending, ready_to_process, processing, completed, completed_with_errors или error. |
message | string | Import started successfully или примечание о том, что работа ещё идёт, в режиме mode: sync. |
import | object | Только в mode: sync, когда импорт достиг конечного состояния: полная запись импорта. |
Для регулярной синхронизации лучше использовать /product/sync-multiple: он обновляет те же строки на месте, сообщает результат по каждому товару и не требует файла.
Проверка статуса импорта
GET /product-import/status
Сообщает о ходе любого созданного вами импорта — через /product/sync, /product/sync-multiple или /product-import/upload-and-import — и о результате по одному товару из него.
GET /product-import/status?import_name=daily-sync&merchant_internal_id=PRODUCT-123
GET /product-import/status?import_id=<ID_ИМПОРТА>
| Поле запроса | Тип | Значение |
|---|---|---|
import_id | string | Импорт, о котором нужен отчёт, — в том виде, в каком его вернул любой вызов синхронизации или загрузки. Передайте это поле или import_name; если нет ни одного, запрос завершится с missing_identifier (422). |
import_name | string | Имя списка импорта. Ищется и в приведённом к slug виде (так его сохраняет синхронизация), и ровно как написано (так его сохраняет загрузка), поэтому выданное вам имя всегда находит импорт. Должно принадлежать вашей учётной записи мерчанта. |
merchant_internal_id | string | Строку какого товара показать. Можно опустить, только если импорт содержит ровно одну строку; в импорте с несколькими строками пропуск приводит к ошибке merchant_internal_id_required (422). |
{
"import_id": "<ID_ИМПОРТА>",
"import_name": "daily-sync",
"import_status": "processing",
"error_type": null,
"processed_rows": 87,
"total_rows": 120,
"row_count": 120,
"row": {
"id": "<ID_СТРОКИ>",
"row_number": 12,
"status": "completed",
"error": null,
"merchant_internal_id": "PRODUCT-123",
"ai_product_id": "<ID_AI_ТОВАРА>",
"offer_product_id": "<ID_ВАРИАНТА>",
"product_id": "<ID_ТОВАРА>",
"offer_id": "<ID_ПРЕДЛОЖЕНИЯ>",
"product": {
"id": "<ID_ВАРИАНТА>",
"root_product_id": "<ID_ОСНОВНОГО_ТОВАРА>",
"type": "variant",
"root_type": "main",
"status": "active",
"name": {"ro": "Nume", "en": "Name", "ru": "Название"},
"slug": {"ro": "nume", "en": "name", "ru": "nazvanie"},
"url": "https://ivo.md/nume/p",
"urls": {"ro": "https://ivo.md/nume/p"},
"has_public_url": true
},
"started_at": "2026-08-26T09:12:00+03:00",
"ended_at": "2026-08-26T09:12:41+03:00"
},
"status": "success"
}
| Поле ответа | Тип | Значение |
|---|---|---|
import_id | string | Импорт, которому соответствует запрос. |
import_name | string | Имя, под которым он сохранён. |
import_status | string | Состояние всего импорта: pending, ready_to_process, processing, completed, completed_with_errors или error. Это состояние импорта — поле status верхнего уровня лишь говорит, что сам запрос выполнен. |
processed_rows / total_rows | integer | Прогресс всего импорта: строки, дошедшие до completed или error, из ожидаемого итога. Равные значения означают, что импорт завершён. |
row_count | integer | Сколько строк сейчас содержит импорт. |
error_type | string, null | Заполняется, когда сбой произошёл в самом импорте (например, нечитаемый файл), а не в отдельной строке. |
row.status | string | Состояние выбранного товара: ready (в очереди), processing, completed или error. Именно это поле опрашивают по конкретному SKU. |
row.error | string, null | Причина сбоя строки в виде машиночитаемого кода — см. коды уровня строки ниже. |
row.merchant_internal_id | string, null | Ваш SKU в том виде, в каком он сохранён в строке. |
row.ai_product_id | string, null | Промежуточная запись, созданная при построении товара. Полезна только для обращений в поддержку. |
row.product_id / row.offer_product_id | string, null | Найденный товар и вариант, к которому привязывается предложение. |
row.offer_id | string, null | Полученное предложение. Как только оно появилось, дальнейшие обновления можно делать через /product-offer/update. |
row.product | object, null | Публичные данные товара: name и slug по языкам, url и urls, каталожный status и has_public_url — false, пока у товара ещё нет публичной страницы. |
row.started_at / row.ended_at | datetime, null | Когда обработка этой строки началась и завершилась. |
status | string | Всегда success — сообщает об успехе самого запроса. Состояние импорта — это import_status. |
Ошибки: missing_identifier (422) — не передан ни import_id, ни import_name, import_not_found (404), import_row_not_found (404), merchant_internal_id_required (422).
Когда предложение становится видимым
Успешный вызов ещё не означает опубликованный товар. Предложение появляется на ivo.md только при выполнении всех условий:
- учётная запись мерчанта активна;
- её торговая точка имеет статус
approvedиis_active; - товар прошёл одобрение IVO и имеет публичную страницу;
priceзадана и больше нуля;availabilityилиavailability_on_orderбольше нуля.
Если синхронизированный товар не появился, проверьте эти пять условий по порядку, прежде чем обращаться в поддержку.
Частые коды ошибок
| Код | HTTP | Значение |
|---|---|---|
api_key_missing | 403 | Нет ни заголовка X-API-Key, ни Authorization: Bearer. |
api_key_invalid | 403 | Неизвестный или отозванный ключ. |
merchant_not_found | 403 | Ключ действителен, но его учётной записи мерчанта больше нет. |
integration_disabled / integration_not_found | 403 | import_name называет интеграцию, которую мерчант отключил или удалил. |
unauthorized_category | 403 | У вашей учётной записи нет разрешения продавать в этой категории. |
product_not_accessible | 403 | Предложение принадлежит другому мерчанту. |
offer_not_found, product_not_found, offer_product_not_found, point_not_found, import_not_found, import_row_not_found, not_imported, offer_deleted | 404 | Указанной записи не существует или она не принадлежит вашей учётной записи. |
merchant_internal_id_not_unique | 409 | SKU соответствует нескольким предложениям. Добавьте merchant_point_id. |
missing_identifier, no_fields_to_update, invalid_price, invalid_product_id, missing_merchant_point, missing_offer_product_id, offer_product_invalid, merchant_internal_id_required, products_required, invalid_product_payload, validation_failed, product_slug_missing, processing_failed | 422 | Запрос неполный или противоречивый. validation_failed содержит index и errors. |
queued, processing, pending_approval | 202 | Это не ошибка: результат ещё не готов. Повторите запрос позже. |
Ошибки уровня строки появляются в row.error, а не в HTTP-статусе: too_generic (название не определяет конкретный товар), missing_name_value, missing_category, unauthorized_category, variant_not_found, duplicate, no_availability и missing_merchant_point.