Коротко. Ozon API — это не один запрос «создать товар». Рабочая интеграция строится как пайплайн: категории и типы → атрибуты → валидация → импорт товара → проверка статуса → медиа → цены → остатки → аналитика → повторная оптимизация. Если пропустить статус импорта, лимиты, обязательные атрибуты или защиту цен, интеграция быстро превращается в генератор ошибок. Та же логика, что и в материале про автоматизацию Wildberries через API.
Почему ручное ведение Ozon ломается на масштабе
Пока в каталоге 20 товаров, карточки, цены и остатки можно обновлять руками. Когда товаров 500, 5 000 или 50 000, ручной процесс перестаёт работать:
- менеджеры ошибаются в артикулах и ценах;
- остатки в ERP и на Ozon расходятся;
- карточки не проходят модерацию из-за атрибутов;
- категории меняются, обязательные характеристики становятся неактуальными;
- цены улетают в карантин или не применяются;
- фото и rich-контент живут отдельно от товарной базы;
- невозможно быстро обновить карточки под сезон, акцию или новую поставку;
- отчёты по SEO и запросам не связаны с контентом карточки.
Решение: API-интеграция как товарный конвейер
Правильная интеграция — это не один большой сценарий, а несколько независимых workflow. Каждый отделяется, потому что у него своя логика отказов и своя частота запуска.
| Workflow | Что делает | Почему отдельно |
|---|---|---|
| Справочники | категории, типы, атрибуты, значения справочников | схема категорий меняется |
| Импорт товаров | создаёт и обновляет карточки | импорт асинхронный, нужен статус |
| Медиа | изображения и rich-контент | отдельные требования и ошибки |
| Цены | цены, старые цены, минимальные цены, НДС | нужен контроль маржи и карантина |
| Остатки | обновляет остатки по складам | обновление на витрине не мгновенное |
| Аналитика | запросы, продажи, видимость, цены, остатки | данные нужны для SEO и ассортимента |
| Мониторинг | ловит 429, validation errors, skipped, failed | без логов интеграция неуправляема |
Что реально автоматизировать через Ozon Seller API
| Направление | Можно автоматизировать | Основные методы |
|---|---|---|
| Категории и типы | дерево категорий, типы товаров | /v1/description-category/tree |
| Атрибуты | обязательные и доп. характеристики | /v1/description-category/attribute |
| Значения атрибутов | справочники значений | /attribute/values, /values/search |
| Создание и обновление товара | импорт товарной карточки | /v3/product/import |
| Проверка импорта | статус загрузки товара | /v1/product/import/info |
| Список товаров | выгрузка товаров магазина | /v3/product/list |
| Информация по товарам | данные по offer_id, product_id, sku | /v3/product/info/list |
| Атрибуты товара | заполненные характеристики | /v4/product/info/attributes |
| Изображения | загрузка и получение фото | /v1/product/pictures/import |
| Цены | обновление и получение цен | /v1/product/import/prices, /v5/product/info/prices |
| Остатки | обновление остатков | /v2/products/stocks |
| FBS/FBO | заказы, отправления, склады, поставки | posting, warehouse, supply-order |
| Аналитика | поисковые запросы, остатки, продажи | /v1/analytics/product-queries, /v1/search-queries/top |
| Коммуникации | отзывы, вопросы, чаты | review, question, chat API |
Ключевые сущности Ozon: offer_id, product_id, sku, category, type_id
Перед автоматизацией нужно договориться, что именно хранится в вашей базе.
| Поле | Что значит | Где использовать |
|---|---|---|
offer_id | ваш артикул продавца | главный ключ синхронизации со своей ERP/PIM |
product_id | ID товара в Ozon | получение информации, статусов и части операций |
sku | SKU товара на Ozon | заказы, аналитика, остатки |
description_category_id | категория описания товара | импорт и получение атрибутов |
type_id | тип товара внутри категории | влияет на набор атрибутов, хранить в базе |
attribute_id | ID характеристики | нужен для payload товара |
dictionary_value_id | ID значения справочника | для справочных характеристик |
offer_id должен быть стабильным и уникальным. Не используйте в нём случайные названия, пробелы, временные префиксы и артикулы поставщика, которые могут измениться.Production-схема интеграции
Линейный конвейер с единственной развилкой — на проверке статуса импорта: товар идёт дальше только после imported.
- Источник: ERP / PIM / Google Sheets / 1С → нормализация данных.
- Справочники Ozon:
/description-category/tree,/attribute,/attribute/values. - Валидация товара по справочникам и обязательным атрибутам.
- Импорт:
/v3/product/import→ получаемtask_id. - Проверка статуса:
/v1/product/import/info.imported→ дальше;failed/skipped→ лог ошибок поoffer_id. - Медиа:
/v1/product/pictures/import. - Цены:
/v1/product/import/prices. - Остатки:
/v2/products/stocks. - Проверка карточки:
/v3/product/info/list. - Аналитика и SEO → рекомендации по контенту → возврат к нормализации.
Пайплайн создания товара через API
Шаг 1. Получить категории и типы
Сначала получаем дерево категорий и типов — без этого нельзя корректно собрать payload товара.
POST https://api-seller.ozon.ru/v1/description-category/tree
Client-Id: {{OZON_CLIENT_ID}}
Api-Key: {{OZON_API_KEY}}
Content-Type: application/json
{
"language": "RU"
}
Что сохранить:
{
"description_category_id": 17028922,
"category_name": "Одежда",
"type_id": 97311,
"type_name": "Футболка"
}
Шаг 2. Получить атрибуты категории и типа
POST https://api-seller.ozon.ru/v1/description-category/attribute
{
"description_category_id": 17028922,
"type_id": 97311,
"language": "RU"
}
В ответе нужно смотреть: обязательность атрибута; тип значения; наличие справочника; можно ли передавать несколько значений; используется ли в фильтрах; ограничения по длине и формату.
Шаг 3. Получить справочные значения
Для атрибутов со справочниками нельзя писать «как хочется» — нужно передавать значение из справочника.
POST https://api-seller.ozon.ru/v1/description-category/attribute/values
{
"description_category_id": 17028922,
"type_id": 97311,
"attribute_id": 85,
"language": "RU",
"limit": 1000
}
Шаг 4. Собрать и провалидировать карточку
До отправки в Ozon проверяем:
offer_idзаполнен и уникален;- указаны
description_category_idиtype_id; - заполнены обязательные атрибуты;
- значения справочников переданы через корректные ID;
- габариты и вес не равны нулю;
- изображения доступны по URL;
- цена не нарушает внутренние правила маржи;
- НДС и валюта заданы корректно;
- товар не превышает лимиты по созданию/обновлению.
Шаг 5. Импортировать товар
POST https://api-seller.ozon.ru/v3/product/import
{
"items": [
{
"offer_id": "TSHIRT-BASIC-BLACK-M",
"name": "Футболка базовая хлопковая черная",
"description_category_id": 17028922,
"type_id": 97311,
"barcode": "4601234567890",
"price": "1290",
"old_price": "1990",
"min_price": "990",
"currency_code": "RUB",
"vat": "0.2",
"height": 2,
"width": 30,
"depth": 25,
"dimension_unit": "cm",
"weight": 250,
"weight_unit": "g",
"images": [
"https://example.com/images/tshirt-black-1.jpg",
"https://example.com/images/tshirt-black-2.jpg"
],
"attributes": [
{
"id": 85,
"values": [
{
"dictionary_value_id": 12345,
"value": "Черный"
}
]
},
{
"id": 8229,
"values": [
{
"value": "100% хлопок"
}
]
}
]
}
]
}
attribute_id, dictionary_value_id, обязательные поля, габариты и значения зависят от категории и типа товара.Шаг 6. Проверить статус импорта
Импорт асинхронный. Нельзя считать карточку созданной только потому, что метод импорта вернул task_id.
POST https://api-seller.ozon.ru/v1/product/import/info
{
"task_id": 123456789
}
В интеграции нужно обрабатывать минимум такие состояния:
sent_to_import
checking_import_status
imported
skipped
failed
validation_error
Если статус неуспешный, ошибку нужно сохранить рядом с offer_id, исходным payload и временем запроса.
JSON-примеры запросов
Получить список товаров
POST https://api-seller.ozon.ru/v3/product/list
{
"filter": {
"visibility": "ALL"
},
"last_id": "",
"limit": 100
}
Получить информацию по товарам
POST https://api-seller.ozon.ru/v3/product/info/list
{
"offer_id": [
"TSHIRT-BASIC-BLACK-M",
"TSHIRT-BASIC-WHITE-M"
]
}
Получить заполненные атрибуты товара
POST https://api-seller.ozon.ru/v4/product/info/attributes
{
"filter": {
"offer_id": ["TSHIRT-BASIC-BLACK-M"],
"visibility": "ALL"
},
"limit": 100,
"last_id": ""
}
Обновить цены
POST https://api-seller.ozon.ru/v1/product/import/prices
{
"prices": [
{
"offer_id": "TSHIRT-BASIC-BLACK-M",
"price": "1290",
"old_price": "1990",
"min_price": "990",
"currency_code": "RUB",
"vat": "0.2"
}
]
}
Обновить остатки
POST https://api-seller.ozon.ru/v2/products/stocks
{
"stocks": [
{
"offer_id": "TSHIRT-BASIC-BLACK-M",
"stock": 25,
"warehouse_id": 123456789
}
]
}
Цены: как обновлять и не попасть в ценовые ошибки
Цены лучше не отправлять напрямую из ERP в Ozon. Между ERP и API нужен валидатор.
Минимальная защита перед отправкой цены
const price = Number(item.price);
const oldPrice = Number(item.old_price || 0);
const minPrice = Number(item.min_price || 0);
const cost = Number(item.cost || 0);
const minMargin = 0.18;
if (!price || price <= 0) {
throw new Error(`Некорректная цена: ${item.offer_id}`);
}
if (cost > 0 && (price - cost) / price < minMargin) {
throw new Error(`Маржа ниже ${minMargin * 100}%: ${item.offer_id}`);
}
if (oldPrice > 0 && oldPrice < price) {
throw new Error(`old_price меньше price: ${item.offer_id}`);
}
if (minPrice > 0 && minPrice > price) {
throw new Error(`min_price больше price: ${item.offer_id}`);
}
return item;
Что логировать по ценам
Остатки: почему нужен отдельный workflow
Остатки — один из самых частых источников конфликтов. Их нельзя обновлять тем же процессом, который создаёт карточку.
- ERP/WMS остатки → нормализация по
offer_id. - Проверка
warehouse_id. - Резерв под заказы вычитается из доступного остатка.
- Отправка
/v2/products/stocks→ статусsync_pending. - Повторная проверка через 20–30 минут → синхронизировано.
Что учитывать:
- остаток должен быть привязан к складу;
warehouse_idдолжен быть актуальным;- после обновления на витрине может быть задержка;
- остатки из ERP нужно очищать от резервов, брака и внутренних перемещений;
- нельзя обновлять остатки товара, который ещё не прошёл импорт.
Медиа и rich-контент
Изображения и rich-контент лучше вынести отдельно — у них своя логика отказов.
Почему не стоит грузить всё сразу
- фото могут быть недоступны по URL;
- изображения могут не пройти требования Ozon;
- rich-контент имеет отдельный формат;
- повторная отправка медиа не должна ломать товарную карточку;
- медиа-команда часто работает отдельно от товарной базы.
Пример загрузки изображений
POST https://api-seller.ozon.ru/v1/product/pictures/import
{
"pictures": [
{
"offer_id": "TSHIRT-BASIC-BLACK-M",
"images": [
"https://example.com/images/tshirt-black-1.jpg",
"https://example.com/images/tshirt-black-2.jpg",
"https://example.com/images/tshirt-black-3.jpg"
]
}
]
}
n8n workflow: импорт товара в Ozon
Ниже — минимальный workflow для n8n. Он показывает логику, а не заменяет полноценную PIM-систему. Что делает: запускается вручную → берёт тестовый товар → нормализует payload → отправляет /v3/product/import → ждёт 30 секунд → проверяет /v1/product/import/info.
Перед импортом укажите переменные окружения:
OZON_CLIENT_ID=ваш_client_id
OZON_API_KEY=ваш_api_key
{
"name": "Ozon API - Product Import MVP",
"nodes": [
{
"parameters": {},
"id": "ManualTrigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "return [{ json: { offer_id: 'TSHIRT-BASIC-BLACK-M', name: 'Футболка базовая хлопковая черная', description_category_id: 17028922, type_id: 97311, barcode: '4601234567890', price: '1290', old_price: '1990', min_price: '990', currency_code: 'RUB', vat: '0.2', height: 2, width: 30, depth: 25, dimension_unit: 'cm', weight: 250, weight_unit: 'g', images: ['https://example.com/images/tshirt-black-1.jpg'], attributes: [{ id: 85, values: [{ dictionary_value_id: 12345, value: 'Черный' }] }, { id: 8229, values: [{ value: '100% хлопок' }] }] } }];"
},
"id": "TestProduct",
"name": "Test Product",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"jsCode": "const item = $json;\n\nconst required = ['offer_id', 'name', 'description_category_id', 'type_id', 'price'];\nfor (const field of required) {\n if (!item[field]) {\n throw new Error(`Missing required field: ${field}`);\n }\n}\n\nconst price = Number(item.price);\nconst minPrice = Number(item.min_price || 0);\nif (!price || price <= 0) throw new Error(`Invalid price for ${item.offer_id}`);\nif (minPrice > 0 && minPrice > price) throw new Error(`min_price > price for ${item.offer_id}`);\n\nreturn [{\n json: {\n items: [item]\n }\n}];"
},
"id": "NormalizePayload",
"name": "Normalize Payload",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://api-seller.ozon.ru/v3/product/import",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Client-Id",
"value": "={{$env.OZON_CLIENT_ID}}"
},
{
"name": "Api-Key",
"value": "={{$env.OZON_API_KEY}}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{$json}}",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"id": "ImportProduct",
"name": "Import Product",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
940,
300
]
},
{
"parameters": {
"amount": 30,
"unit": "seconds"
},
"id": "WaitImport",
"name": "Wait 30 sec",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
1180,
300
]
},
{
"parameters": {
"jsCode": "const body = $node['Import Product'].json.body || $node['Import Product'].json;\nconst taskId = body?.result?.task_id || body?.task_id;\nif (!taskId) {\n throw new Error('Ozon import task_id not found in response');\n}\nreturn [{ json: { task_id: taskId } }];"
},
"id": "ExtractTaskId",
"name": "Extract task_id",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1400,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://api-seller.ozon.ru/v1/product/import/info",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Client-Id",
"value": "={{$env.OZON_CLIENT_ID}}"
},
{
"name": "Api-Key",
"value": "={{$env.OZON_API_KEY}}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{$json}}"
},
"id": "CheckImportStatus",
"name": "Check Import Status",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1620,
300
]
}
],
"connections": {
"Manual Trigger": {
"main": [
[
{
"node": "Test Product",
"type": "main",
"index": 0
}
]
]
},
"Test Product": {
"main": [
[
{
"node": "Normalize Payload",
"type": "main",
"index": 0
}
]
]
},
"Normalize Payload": {
"main": [
[
{
"node": "Import Product",
"type": "main",
"index": 0
}
]
]
},
"Import Product": {
"main": [
[
{
"node": "Wait 30 sec",
"type": "main",
"index": 0
}
]
]
},
"Wait 30 sec": {
"main": [
[
{
"node": "Extract task_id",
"type": "main",
"index": 0
}
]
]
},
"Extract task_id": {
"main": [
[
{
"node": "Check Import Status",
"type": "main",
"index": 0
}
]
]
}
}
}
Что обязательно доработать перед production
- заменить тестовый товар на источник данных: Google Sheets, ERP, PIM, 1С;
- добавить получение категорий и атрибутов;
- добавить таблицу соответствия ваших полей и Ozon attributes;
- добавить базу логов по
offer_id; - добавить повторные проверки статуса импорта;
- добавить обработку 429 и backoff;
- разделить контент, цены и остатки на разные workflow;
- добавить алерты в Telegram/Slack при ошибках.
Ошибки, лимиты и защита от поломок
1. Общий rate limit
Для Ozon Seller API важно ограничивать скорость запросов на уровне кабинета. Не запускайте 5 параллельных workflow без общего rate limiter.
очередь задач → глобальный лимитер → API-запрос → лог ответа → retry при 429/5xx
2. Асинхронный импорт
/v3/product/import возвращает задачу импорта. Итоговый статус нужно проверять через /v1/product/import/info.
Ошибочный подход:
Отправили /v3/product/import → сразу ставим цену и остатки
Правильный подход:
Отправили /v3/product/import → получили task_id → проверили import/info → только потом медиа/цены/остатки
3. Устаревшие методы
Ozon регулярно обновляет Seller API. В интеграции должен быть процесс проверки changelog. Что хранить:
{
"api_method": "/v3/product/import",
"workflow": "ozon-product-import",
"last_checked_docs_at": "2026-06-13",
"owner": "integration-team"
}
4. Ошибки атрибутов
Самые частые причины:
- неверный
description_category_idилиtype_id; - отсутствует обязательный атрибут;
- передано текстовое значение вместо справочного ID;
- значение не входит в справочник;
- изменились требования категории;
- старый товар обновляется по новой схеме.
5. Ошибки цен
Проверять до отправки: цена больше нуля; не ниже себестоимости и минимальной маржи; old_price не меньше price; min_price не больше price; валюта соответствует кабинету; НДС корректен; резкое снижение цены подтверждено правилом.
6. Ошибки остатков
Проверять до отправки: товар уже импортирован; warehouse_id существует; остаток не отрицательный; учтены резервы; остаток не перетирается устаревшей выгрузкой; есть контроль задержки обновления на витрине.
SEO и аналитика Ozon
Автоматизация Ozon не должна заканчиваться созданием карточки. Дальше нужно регулярно смотреть, как товар находится и продаётся — это та же работа, что и SEO карточек товаров и SEO-аналитика.
Что собирать
API-контур для SEO
/v1/analytics/product-queries
/v1/analytics/product-queries/details
/v1/search-queries/top
/v1/search-queries/text
/v3/product/info/list
/v4/product/info/attributes
Как использовать данные
- Получить запросы, по которым товар уже показывается.
- Разделить запросы на коммерческие, информационные, брендовые, мусорные.
- Сравнить запросы с названием, атрибутами и описанием.
- Найти запросы с показами, но без продаж.
- Найти запросы с продажами, но слабой позицией.
- Обновить контент и характеристики (хороший SEO-текст в описании).
- Проверить эффект через 7–14 дней.
Чек-лист запуска интеграции
Перед первым импортом
- Получены
Client-IdиApi-Key. - Ключи не хранятся в workflow открытым текстом.
- Есть таблица соответствия ваших категорий и Ozon
description_category_id/type_id. - Загружены атрибуты категорий и справочные значения.
- Есть валидатор обязательных атрибутов.
- Есть стабильный
offer_idи журнал ошибок по нему.
Перед массовым обновлением
- Проверены лимиты API, включён rate limiter.
- Есть retry/backoff для 429 и 5xx.
- Есть dry-run режим и diff изменений.
- Сохраняется исходный payload.
- Есть rollback для цен и алерты при массовых ошибках.
Перед автоматизацией цен
- Задана минимальная маржа, проверяется себестоимость.
- Проверяются
old_priceиmin_price. - Отслеживается карантин цен.
- Есть лог всех ценовых изменений.
Перед автоматизацией остатков
- Проверены склады и
warehouse_id. - Учитываются резервы.
- Остатки не отправляются для неимпортированных товаров.
- Есть задержка и повторная проверка, защита от устаревших выгрузок.
FAQ
Можно ли через Ozon API массово создавать товары?
Да. Для создания и обновления товаров используется /v3/product/import. Но перед импортом нужно получить категории, типы и атрибуты, а после отправки — проверить статус через /v1/product/import/info.
Можно ли обновлять цены отдельно от карточки?
Да. Цены обновляются отдельным методом /v1/product/import/prices. Это лучше выносить в отдельный workflow с проверкой маржи, минимальной цены, старой цены и НДС.
Можно ли обновлять остатки через API?
Да. Для обновления остатков используется отдельный контур, например /v2/products/stocks. Остатки нужно синхронизировать со складами и учитывать задержку обновления на витрине.
Почему товар не появился после импорта?
Потому что импорт асинхронный. Ответ метода импорта ещё не означает, что карточка создана. Нужно проверить задачу через /v1/product/import/info и разобрать ошибки по атрибутам, категории, изображениям или данным товара.
Можно ли сделать интеграцию Ozon в n8n?
Да. n8n подходит для MVP и средних сценариев: импорт товаров, обновление цен, остатков, алерты, синхронизация с Google Sheets, ERP или CRM. Для больших каталогов лучше добавить базу данных, очередь и отдельный rate-limit worker.
Нужно ли следить за изменениями API?
Да. Ozon регулярно обновляет методы, переносит beta-методы в основной раздел и отключает устаревшие версии. Для production-интеграции нужен changelog-мониторинг.
Источники
- Ozon Help: Working with API — docs.ozon.ru/api/intro
- Ozon Help: API Documentation — docs.ozon.ru/api
- Ozon for Dev: автоимпорт и обновление товаров в Seller API — dev.ozon.ru/start/294
- Ozon for Dev: изменение дерева категорий — dev.ozon.ru/start/261
- Ozon for Dev: использование поля type_id — dev.ozon.ru/start/334
- Ozon for Dev: новые лимиты в Seller API — dev.ozon.ru/news/584
- Ozon Help: Stock Management — fulfillment/stock
- Ozon Help: Price Management — prices/price-control
- Ozon Help: Price Quarantine — prices/price-quarantine
- Ozon Help: Search Queries — analytics/search-queries