Ручне оновлення залишків на маркетплейсах — джерело постійних проблем. Продавець виставляє 10 одиниць, а на складі залишилося 3. Замовлення оформлюється, але не відвантажується — маркетплейс штрафує, рейтинг картки падає. Співробітники витрачають години на звірку цифр, але людський фактор неминучий: забули оновити, помилилися в кількості, не врахували резерв. Наш досвід — 5+ років і 50+ успішних проектів з інтеграції облікових систем з маркетплейсами. Порівняно з ручним оновленням, автоматичний бот скорочує час управління стоком у 10 разів і знижує кількість скасованих замовлень на 70%. Типова економія на штрафах — рассчитывается индивидуально.
Чому автоматизація вигідніша за ручне оновлення?
Ручне введення через особистий кабінет забирає 1–2 години щодня для магазину з 5000 позицій. Помилка в одній цифрі призводить до каскаду проблем: скасування замовлень, негативний рейтинг, втрата позицій у видачі. Наш бот обробляє зміни за секунди, виключаючи помилки. Він бере дані безпосередньо з облікової системи — жодних описок. У результаті рейтинг карток зростає, а кількість скасованих замовлень знижується на 70%.
Кейс з практики: Для клієнта з каталогом 15 000 SKU ручне оновлення займало 4 години щодня. Після впровадження бота час скоротився до 10 хвилин, а кількість скасованих замовлень впала на 70%. Штрафи за невірний сток були виключені повністю. Порівняно з використанням універсальних ERP-модулів, наш бот дає більш гнучке налаштування буфера та алептів.
Згідно з офіційною документацією Ozon API, PUT /v2/products/stocks дозволяє оновлювати до 100 товарів за запит.
Як ми інтегруємося з джерелами даних?
Джерел декілька, їх потрібно агрегувати. Основне — ваша складська система (1С, МійСклад, Odoo). Додатково підключаємо постачальників (через імпорт) і зчитуємо резерв маркетплейсів. Також враховуємо віртуальний резерв з власного сайту — відкриті кошики.
| Облікова система | Метод інтеграції | Складність |
|---|---|---|
| 1С | HTTP-сервіс (REST) або вебхук | Середня |
| МійСклад | REST API | Низька |
| Odoo | XML-RPC / JSON-RPC | Середня |
Схема даних будується на таблицях stock_levels, marketplace_stocks та stock_sync_log. Перша зберігає загальні залишки та резерв, друга — актуальні для кожного маркетплейсу, третя — історію синхронізацій для дебагу.
CREATE TABLE stock_levels (
id BIGSERIAL PRIMARY KEY,
product_id BIGINT REFERENCES products(id),
warehouse_id INT REFERENCES warehouses(id),
quantity INT NOT NULL DEFAULT 0,
reserved INT NOT NULL DEFAULT 0,
available INT GENERATED ALWAYS AS (quantity - reserved) STORED,
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE marketplace_stocks (
id BIGSERIAL PRIMARY KEY,
product_id BIGINT REFERENCES products(id),
marketplace VARCHAR(50) NOT NULL,
warehouse_code VARCHAR(100),
synced_quantity INT,
last_synced_at TIMESTAMP,
sync_status VARCHAR(20) DEFAULT 'ok',
error_message TEXT,
UNIQUE(product_id, marketplace, warehouse_code)
);
CREATE TABLE stock_sync_log (
id BIGSERIAL PRIMARY KEY,
product_id BIGINT,
marketplace VARCHAR(50),
old_qty INT,
new_qty INT,
source VARCHAR(50),
synced_at TIMESTAMP DEFAULT NOW()
);
Інтеграція з Ozon API
Оновлення залишків виконується через ендпоінт PUT /v2/products/stocks. Ми надсилаємо батчі по 100 товарів, щоб не перевищити ліміт.
class OzonStockSyncer
{
public function syncStocks(array $items): SyncResult
{
$result = new SyncResult();
$batches = array_chunk($items, 100);
foreach ($batches as $batch) {
$payload = array_map(fn($item) => [
'offer_id' => $item['sku'],
'stock' => $item['qty'],
'warehouse_id' => $item['warehouse_id'],
], $batch);
$response = Http::withHeaders([
'Client-Id' => $this->clientId,
'Api-Key' => $this->apiKey,
])->post('https://api-seller.ozon.ru/v2/products/stocks', [
'stocks' => $payload,
]);
if (!$response->successful()) {
$result->errors[] = $response->json('message', 'Unknown error');
continue;
}
foreach ($response->json('result', []) as $item) {
if ($item['updated']) {
$result->updated++;
} else {
$result->errors[] = "SKU {$item['offer_id']}: " . ($item['errors'][0]['message'] ?? 'error');
}
}
}
return $result;
}
}
Інтеграція з Wildberries
Wildberries використовує PUT-запит до /api/v3/warehouses/{warehouseId}/stocks. Код аналогічний, але з урахуванням особливостей — токен у заголовку, мапінг через barcode.
class WildberriesStockSyncer
{
public function syncStocks(array $items, int $warehouseId): SyncResult
{
$payload = array_map(fn($item) => [
'sku' => $item['wb_barcode'],
'amount' => max(0, $item['qty']),
], $items);
$response = Http::withToken($this->apiKey)
->put("https://marketplace-api.wildberries.ru/api/v3/warehouses/{$warehouseId}/stocks", [
'stocks' => $payload,
]);
if (!$response->successful()) {
throw new WildberriesApiException($response->json('title', 'API Error'));
}
return new SyncResult(updated: count($items));
}
}
Як налаштувати буферний сток та алепти?
Часто потрібно тримати буфер — не вивантажувати весь залишок на маркетплейс, щоб резервувати для інших каналів. Ми реалізуємо гнучку логіку: абсолютний або відсотковий буфер, верхній ліміт по товару. Наприклад, для товару із залишком 50 одиниць можна встановити буфер 5 шт. або 10%. Тоді на маркетплейс піде лише 45 шт.
class StockCalculator
{
public function calculateMarketplaceQty(Product $product, string $marketplace): int
{
$available = $product->available_stock;
$buffer = $product->stock_buffer ?? config("marketplaces.{$marketplace}.default_buffer", 2);
$pctBuffer = (int) ceil($available * config("marketplaces.{$marketplace}.buffer_pct", 0) / 100);
$reserved = max($buffer, $pctBuffer);
$qty = max(0, $available - $reserved);
$maxQty = $product->max_marketplace_stock ?? PHP_INT_MAX;
return min($qty, $maxQty);
}
}
Налаштовуємо алепти — якщо залишок на сайті більше нуля, а на маркетплейсі нуль вже 2 години, ви отримуєте повідомлення. Це страхує від розсинхронізації. Сценарії алептів:
| Ситуація | Повідомлення | Дія |
|---|---|---|
| Розсинхронізація > 1 години | Telegram / Email | Автоматична повторна синхронізація |
| Помилка API маркетплейсу | Telegram | Ручна перевірка логів |
| Вичерпання буфера | Поповнення складу |
Докладніше про порівняння API маркетплейсів
| Маркетплейс | Особливості API | Ліміт запитів | Швидкість оновлення |
|---|---|---|---|
| Ozon | PUT /v2/products/stocks | 100 товарів за запит | До 1 хвилини |
| Wildberries | PUT /api/v3/warehouses/{id}/stocks | 50 запитів/сек | До 2 хвилин |
Що входить в роботу?
| Складова | Опис |
|---|---|
| Документація | Архітектура, схема даних, інструкція з експлуатації |
| Доступи | Налаштування API-ключів, прав доступу до облікової системи та маркетплейсів |
| Навчання | Демонстрація роботи бота, розбір логів та алептів для вашої команди |
| Підтримка | Гарантійне обслуговування протягом місяця, потім — за договором |
Типові помилки при інтеграції
- Невірний артикул — різниця у форматах SKU між обліковою системою та маркетплейсом. Вирішується єдиною системою мапінгу.
- Перевищення ліміту запитів — занадто часті оновлення. Збільшуємо інтервал або використовуємо батчі.
- Помилка авторизації — прострочений токен. Налаштовуємо автоматичне оновлення ключів.
- Розбіжність залишків — відсутність обліку резервів. Впроваджуємо буферний сток.
Процес роботи
- Аналітика — вивчаємо вашу облікову систему, поточні API, обсяг каталогу.
- Проектування — схема даних, логіка буфера, інтеграційні модулі.
- Розробка — пишемо код синхронізації, алептів, логування.
- Тестування — на тестовому контурі перевіряємо всі сценарії (включно з помилками).
- Деплой — розгортання на вашому сервері або хмарі, налаштування моніторингу.
- Супровід — гарантійний період, навчання команди.
Строки реалізації
- Базова версія (Ozon + WB + 1С): 4–5 робочих днів.
- Складні буферні схеми та додаткові маркетплейси: +1–2 дні.
Отримайте консультацію — оцінимо ваш проект за один день. Замовте розробку бота, щоб позбутися штрафів та заощадити час співробітників.







