Webhooks (Push Notifications) — Ozon Seller API
Overview
Ozon Seller API использует механизм push-уведомлений (webhooks) для отправки реальных событий на ваш сервер. Это позволяет вашей системе мгновенно реагировать на изменения в заказах, товарах, сообщениях и других сущностях маркетплейса.
Официальная документация: https://docs.ozon.ru/api/seller/en/#tag/push_intro
Важные термины
- Push-уведомление — HTTP-запрос, который Ozon отправляет на ваш URL при наступлении события
- MessageType — тип уведомления (константа, идентифицирующая событие)
- Payload — JSON-тело уведомления с данными события
Типы уведомлений (Message Types)
Ozon Seller API поддерживает 13 типов push-уведомлений:
1. TYPE_PING
Проверка соединения. Отправляется при первоначальном подключении и периодически для проверки доступности вашего сервера.
2. TYPE_NEW_POSTING
Новое отправление (заказ). Уведомление о создании нового заказа.
3. TYPE_POSTING_CANCELLED
Отмена отправления. Заказ был отменён.
4. TYPE_STATE_CHANGED
Изменение статуса отправления. Статус заказа изменился.
5. TYPE_CUTOFF_DATE_CHANGED
Изменение даты отгрузки. Дата, к которой нужно подготовить товар, изменилась.
6. TYPE_DELIVERY_DATE_CHANGED
Изменение даты доставки. Промежуток времени для доставки изменился.
7. TYPE_CREATE_OR_UPDATE_ITEM
Создание или обновление товара. Товар создан, обновлён или возникла ошибка при обработке.
8. TYPE_PRICE_INDEX_CHANGED
Изменение ценового индекса. Изменился ценовой индекс товара.
9. TYPE_STOCKS_CHANGED
Изменение остатков. Остатки товаров на складе изменились.
10. TYPE_NEW_MESSAGE
Новое сообщение в чате. Покупатель или служба поддержки отправили сообщение.
11. TYPE_UPDATE_MESSAGE
Изменение сообщения в чате. Сообщение было отредактировано.
12. TYPE_MESSAGE_READ
Прочитанное сообщение. Покупатель или служба поддержки прочитали ваше сообщение.
13. TYPE_CHAT_CLOSED
Чат закрыт. Чат с покупателем был закрыт.
Структуры payload для каждого типа
Общая структура для всех уведомлений
{
"message_type": "TYPE_..."
}
1. TYPE_PING — Проверка соединения
Запрос:
{
"message_type": "TYPE_PING",
"time": "2026-02-10T12:00:00Z"
}
Ожидаемый ответ:
{
"version": "1.0",
"name": "Ozon Seller API",
"time": "2026-02-10T12:00:00Z"
}
2. TYPE_NEW_POSTING — Новое отправление
{
"message_type": "TYPE_NEW_POSTING",
"posting_number": "12345678-0001",
"products": [
{
"sku": 123456,
"quantity": 2
}
],
"in_process_at": "2026-02-10T12:00:00Z",
"warehouse_id": 123456789,
"seller_id": 12345
}
Поля:
posting_number(string) — Номер отправленияproducts(array) — Массив товаров в отправленииsku(int64) — SKU товараquantity(int64) — Количество
in_process_at(datetime) — Дата и время начала обработки в UTCwarehouse_id(int64) — ID складаseller_id(int64) — ID продавца
3. TYPE_POSTING_CANCELLED — Отмена отправления
{
"message_type": "TYPE_POSTING_CANCELLED",
"posting_number": "12345678-0001",
"products": [
{
"sku": 123456,
"quantity": 2
}
],
"old_state": "awaiting_packaging",
"new_state": "posting_canceled",
"changed_state_date": "2026-02-10T12:00:00Z",
"reason": {
"id": 1,
"message": "Покупатель отменил заказ"
},
"warehouse_id": 123456789,
"seller_id": 12345
}
Дополнительные поля:
old_state(string) — Предыдущий статусnew_state(string) — Новый статус (обычноposting_canceled)changed_state_date(datetime) — Дата и время изменения статусаreason(object) — Причина отменыid(int64) — ID причиныmessage(string) — Описание причины
4. TYPE_STATE_CHANGED — Изменение статуса
{
"message_type": "TYPE_STATE_CHANGED",
"posting_number": "12345678-0001",
"new_state": "delivering",
"changed_state_date": "2026-02-10T12:00:00Z",
"warehouse_id": 123456789,
"seller_id": 12345
}
5. TYPE_CUTOFF_DATE_CHANGED — Изменение даты отгрузки
{
"message_type": "TYPE_CUTOFF_DATE_CHANGED",
"posting_number": "12345678-0001",
"new_cutoff_date": "2026-02-12T18:00:00Z",
"old_cutoff_date": "2026-02-11T18:00:00Z",
"warehouse_id": 123456789,
"seller_id": 12345
}
6. TYPE_DELIVERY_DATE_CHANGED — Изменение даты доставки
{
"message_type": "TYPE_DELIVERY_DATE_CHANGED",
"posting_number": "12345678-0001",
"new_delivery_date_begin": "2026-02-15T00:00:00Z",
"new_delivery_date_end": "2026-02-17T23:59:59Z",
"old_delivery_date_begin": "2026-02-14T00:00:00Z",
"old_delivery_date_end": "2026-02-16T23:59:59Z",
"warehouse_id": 123456789,
"seller_id": 12345
}
7. TYPE_CREATE_OR_UPDATE_ITEM — Создание/обновление товара
{
"message_type": "TYPE_CREATE_OR_UPDATE_ITEM",
"offer_id": "PRODUCT-123",
"product_id": 123456789,
"is_error": false,
"changed_at": "2026-02-10T12:00:00Z",
"seller_id": 12345
}
Поля:
offer_id(string) — Идентификатор товара в системе продавцаproduct_id(int64) — ID товара в Ozonis_error(boolean) —trueесли при создании/обновлении возникли ошибкиchanged_at(datetime) — Дата и время обновления
8. TYPE_PRICE_INDEX_CHANGED — Изменение ценового индекса
{
"message_type": "TYPE_PRICE_INDEX_CHANGED",
"updated_at": "2026-02-10T12:00:00Z",
"sku": 123456,
"product_id": 123456789,
"price_index": 1500,
"seller_id": 12345
}
Поля:
price_index(int64) — Новый ценовой индекс (в копейках)
9. TYPE_STOCKS_CHANGED — Изменение остатков
{
"message_type": "TYPE_STOCKS_CHANGED",
"items": [
{
"updated_at": "2026-02-10T12:00:00Z",
"sku": 123456,
"product_id": 123456789,
"stocks": [
{
"warehouse_id": 123456789,
"present": 100,
"reserved": 10
}
]
}
],
"seller_id": 12345
}
Поля:
items(array) — Массив товаров с изменившимися остаткамиupdated_at(datetime) — Дата и время обновленияsku(int64) — SKU товара (для FBS/rFBS)product_id(int64) — ID товараstocks(array) — Массив остатков по складамwarehouse_id(int64) — ID складаpresent(int64) — Общее количество товараreserved(int64) — Зарезервировано
10. TYPE_NEW_MESSAGE — Новое сообщение в чате
{
"message_type": "TYPE_NEW_MESSAGE",
"chat_id": "chat-12345",
"chat_type": "CUSTOMER",
"message_id": "msg-67890",
"created_at": "2026-02-10T12:00:00Z",
"user": {
"id": "user-999",
"type": "CUSTOMER"
},
"data": [
"Здравствуйте, когда будет отправка?"
],
"seller_id": 12345
}
Поля:
chat_id(string) — ID чатаchat_type(string) — Тип чата (CUSTOMER,SUPPORT)message_id(string) — ID сообщенияcreated_at(datetime) — Дата созданияuser(object) — Отправительid(string) — ID пользователяtype(string) — Тип (CUSTOMER,SUPPORT,SELLER)
data(array of strings) — Содержание сообщения в формате Markdown
11. TYPE_UPDATE_MESSAGE — Изменение сообщения
{
"message_type": "TYPE_UPDATE_MESSAGE",
"chat_id": "chat-12345",
"chat_type": "CUSTOMER",
"message_id": "msg-67890",
"created_at": "2026-02-10T12:00:00Z",
"updated_at": "2026-02-10T12:05:00Z",
"user": {
"id": "user-999",
"type": "CUSTOMER"
},
"data": [
"Здравствуйте, уточните когда будет отправка?"
],
"seller_id": 12345
}
Дополнительное поле:
updated_at(datetime) — Дата редактирования
12. TYPE_MESSAGE_READ — Прочитанное сообщение
{
"message_type": "TYPE_MESSAGE_READ",
"chat_id": "chat-12345",
"chat_type": "CUSTOMER",
"message_id": "msg-67890",
"created_at": "2026-02-10T12:00:00Z",
"user": {
"id": "user-999",
"type": "CUSTOMER"
},
"data": [
"Ваше сообщение"
],
"last_read_message_id": "msg-67890",
"seller_id": 12345
}
Дополнительное поле:
last_read_message_id(string) — ID последнего прочитанного сообщения
13. TYPE_CHAT_CLOSED — Чат закрыт
{
"message_type": "TYPE_CHAT_CLOSED",
"chat_id": "chat-12345",
"chat_type": "CUSTOMER",
"user": {
"id": "user-999",
"type": "SELLER"
},
"seller_id": 12345
}
Настройка webhook-сервера
Требования к серверу
- Доступность: Сервер должен быть доступен из интернета по HTTPS
- Порт: Любой порт (настраивается в личном кабинете Ozon)
- Отклик: Сервер должен отвечать HTTP 200 с телом
{"result": true} - Timeout: Обрабатывать запросы быстро (рекомендуется < 5 секунд)
Пример реализации на Go
package main
import (
"log"
"github.com/diphantxm/ozon-api-client/ozon/notifications"
)
func main() {
// Создаём сервер на порту 5000
port := 5000
server := notifications.NewNotificationServer(port)
// Регистрируем обработчики для каждого типа уведомлений
server.Register(notifications.NewPostingType, func(req interface{}) error {
notification := req.(*notifications.NewPosting)
log.Printf("Новое отправление: %s\n", notification.PostingNumber)
// Обработка нового заказа...
return nil
})
server.Register(notifications.PostingCancelledType, func(req interface{}) error {
notification := req.(*notifications.PostingCancelled)
log.Printf("Отправление %s отменено\n", notification.PostingNumber)
// Обработка отмены...
return nil
})
server.Register(notifications.StateChangedType, func(req interface{}) error {
notification := req.(*notifications.StateChanged)
log.Printf("Статус отправления %s изменен на %s\n",
notification.PostingNumber, notification.NewState)
// Обработка изменения статуса...
return nil
})
server.Register(notifications.NewMessageType, func(req interface{}) error {
notification := req.(*notifications.NewMessage)
log.Printf("Новое сообщение в чате %s: %v\n",
notification.ChatId, notification.Data)
// Обработка нового сообщения...
return nil
})
// Запускаем сервер
if err := server.Run(); err != nil {
log.Printf("Ошибка запуска сервера: %s", err)
}
}
Пример реализации на Python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/', methods=['POST'])
def handle_webhook():
data = request.json
message_type = data.get('message_type')
if message_type == 'TYPE_PING':
# Проверка соединения
return jsonify({
'version': '1.0',
'name': 'Ozon Seller API',
'time': datetime.utcnow().isoformat()
})
elif message_type == 'TYPE_NEW_POSTING':
posting_number = data.get('posting_number')
products = data.get('products', [])
# Обработка нового заказа
print(f"Новое отправление: {posting_number}")
for product in products:
print(f" SKU: {product['sku']}, Кол-во: {product['quantity']}")
elif message_type == 'TYPE_POSTING_CANCELLED':
posting_number = data.get('posting_number')
reason = data.get('reason', {}).get('message', 'Неизвестно')
print(f"Отправление {posting_number} отменено: {reason}")
elif message_type == 'TYPE_NEW_MESSAGE':
chat_id = data.get('chat_id')
message_data = data.get('data', [])
print(f"Новое сообщение в чате {chat_id}: {message_data}")
# ... обработка остальных типов ...
# Всегда возвращаем успешный ответ
return jsonify({'result': True})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, ssl_context='adhoc')
Процесс настройки webhook-интеграции
Шаг 1: Разверните webhook-сервер
- Разработайте и разверните сервер для приёма webhook-уведомлений
- Убедитесь, что сервер доступен из интернета по HTTPS
- Протестируйте обработку TYPE_PING запроса
Шаг 2: Зарегистрируйте webhook в личном кабинете
Официальная документация: https://docs.ozon.ru/api/seller/en/#tag/push_intro
Процесс регистрации:
- Войдите в личный кабинет продавца Ozon (seller.ozon.ru)
- Перейдите в раздел Настройки → API (или аналогичный раздел)
- Найдите подраздел Push-уведомления или Webhooks
- Укажите URL вашего webhook-сервера
- Выберите типы уведомлений, которые хотите получать
- Сохраните настройки
Важно: Точный путь настройки может отличаться. Рекомендуется обратиться к официальной документации Ozon или поддержке.
Шаг 3: Проверьте работу webhook
- Ozon отправит тестовый запрос
TYPE_PINGна ваш URL - Ваш сервер должен ответить корректной структурой с версией и временем
- После успешной проверки Ozon начнёт отправлять уведомления
Обработка ошибок
Структура ошибки
{
"error": {
"code": "400",
"message": "Ошибка валидации",
"details": "Поле 'posting_number' обязательно"
}
}
HTTP-коды ответов
- 200 OK — Уведомление успешно обработано
- 400 Bad Request — Неверный формат запроса или невалидные данные
- 500 Internal Server Error — Внутренняя ошибка вашего сервера
Важно: Даже если ваш сервер вернёт ошибку, Ozon может повторить отправку уведомления. Рекомендуется всегда возвращать 200 с
{"result": true}после успешной обработки, чтобы избежать повторов.
Рекомендации по реализации
1. Идемпотентность
Уведомления могут дублироваться. Обеспечьте идемпотентность обработки:
- Используйте
message_idилиposting_numberкак ключ идемпотентности - Храните обработанные уведомления в базе данных
- Перед обработкой проверяйте, не было ли уведомление уже обработано
2. Асинхронная обработка
Не выполняйте длительные операции синхронно:
- Сразу верните HTTP 200
- Поместите уведомление в очередь (RabbitMQ, Redis, Kafka)
- Обрабатывайте в фоновых воркерах
3. Логирование
Логируйте все входящие уведомления:
- Сохраняйте исходный JSON
- Записывайте время получения
- Фиксируйте результаты обработки
4. Мониторинг
Настройте мониторинг:
- Количество полученных уведомлений по типам
- Время обработки
- Ошибки и исключения
- Доступность webhook-сервера
5. Безопасность
Проверяйте входящие запросы:
- Используйте HTTPS
- Проверяйте IP-адреса источника (если Ozon предоставит список)
- Валидируйте структуру JSON
- Не доверяйте данным из уведомлений без проверки
Категории уведомлений по бизнес-процессам
Управление заказами
TYPE_NEW_POSTING— Новый заказTYPE_POSTING_CANCELLED— Отмена заказаTYPE_STATE_CHANGED— Изменение статусаTYPE_CUTOFF_DATE_CHANGED— Изменение даты отгрузкиTYPE_DELIVERY_DATE_CHANGED— Изменение даты доставки
Управление товарами
TYPE_CREATE_OR_UPDATE_ITEM— Создание/обновление товараTYPE_PRICE_INDEX_CHANGED— Изменение ценыTYPE_STOCKS_CHANGED— Изменение остатков
Коммуникации с клиентами
TYPE_NEW_MESSAGE— Новое сообщениеTYPE_UPDATE_MESSAGE— Редактирование сообщенияTYPE_MESSAGE_READ— Прочитанное сообщениеTYPE_CHAT_CLOSED— Закрытие чата
Служебные
TYPE_PING— Проверка соединения
Полезные ссылки
Официальная документация
- API Documentation (EN): https://docs.ozon.ru/api/seller/en/
- Push Notifications Intro: https://docs.ozon.ru/api/seller/en/#tag/push_intro
Клиентские библиотеки с поддержкой webhook
- Go (diPhantxm/ozon-api-client): https://github.com/diPhantxm/ozon-api-client
- Поддержка всех 13 типов уведомлений
- Встроенный REST-сервер для обработки webhook
- Laravel (muscobytes/laravel-ozon-seller-webhook): https://github.com/muscobytes/laravel-ozon-seller-webhook
- Конфигурация через Laravel config
- Обработка различных типов событий
Сообщество
- Telegram канал (EN): https://t.me/s/OzonEnSellerAPI
- GitHub Issues: Открывайте issues в репозиториях клиентских библиотек
Часто задаваемые вопросы (FAQ)
В: Ozon не отправляет уведомления на мой URL
О: Проверьте:
- Сервер доступен по HTTPS из интернета
- Корректно отвечаете на TYPE_PING (нужен JSON с version, name, time)
- Webhook зарегистрирован в личном кабинете Ozon
- Выбраны нужные типы уведомлений в настройках
В: Приходят дублирующиеся уведомления
О: Это нормально. Ozon может повторять отправку при:
- Таймауте ответа
- Ошибке (не 200)
- Неполном ответе
Реализуйте идемпотентность по message_id или posting_number.
В: Какой формат времени в уведомлениях?
О: Все даты в формате ISO 8601 UTC: 2026-02-10T12:00:00Z
В: Можно ли выбрать только определённые типы уведомлений?
О: Да, в личном кабинете Ozon вы можете выбрать, какие типы уведомлений получать на ваш URL.
В: Что делать если payload не соответствует документации?
О: Структуры payload могут меняться. Ozon обычно не предупреждает об изменениях. Рекомендации:
- Валидируйте JSON при получении
- Логируйте неизвестные поля
- Используйте клиентские библиотеки, которые обновляются сообществом
- Следите за обновлениями в Telegram-канале Ozon Seller API
Пример полной интеграции
Архитектура
Ozon Platform
↓ (Webhook HTTPS)
Nginx / Load Balancer
↓
Webhook Server (Go/Python/Node.js)
↓ (валидация, логирование)
Message Queue (RabbitMQ/Redis)
↓
Background Workers (обработка)
↓
Database (postgres/mysql)
Поток обработки
- Ozon отправляет POST на webhook URL
- Webhook сервер принимает JSON, парсит
message_type - Валидирует структуру, логирует в БД
- Отправляет
{"result": true}(HTTP 200) - Кладёт событие в очередь сообщений
- Фоновые воркеры обрабатывают события бизнес-логикой
- Результаты записываются в БД
Версия документации: 1.0 Дата обновления: 10 февраля 2026 г. Источник: GitHub diPhantxm/ozon-api-client, официальная документация Ozon