עדכוני מלאי ידניים במרקטפלייס הם כאב ראש מתמיד. אתם מפרטים 10 יחידות, אבל רק 3 נשארו במחסן. מתקבלת הזמנה שלא ניתן לספק — המרקטפלייס קובע קנס והדירוג של המוצר שלכם יורד. עובדים מבזבזים שעות על יישור מספרים, אבל טעות אנוש היא בלתי נמנעת: הם שוכחים לעדכן, מזינים כמות שגויה, או לא מתחשבים ברזרבות. הצוות שלנו מביא ניסיון של 10+ שנים ו-40+ פרויקטים מוצלחים של שילוב מערכות הנהלת חשבונות עם מרקטפלייס. בהשוואה לעדכונים ידניים, בוט אוטומטי מקצר את זמן ניהול המלאי בפי 10 ומפחית הזמנות מבוטלות ב-70%. עבור חנות עם מחזור של $90k–130k, החיסכון האופייני בקנסות מגיע עד $9k–13k בשנה.
למה אוטומציה עדיפה על עדכונים ידניים
הזנה ידנית דרך לוח הבקרה אורכת 1–2 שעות ביום עבור חנות עם 5,000 SKU. שגיאת ספרה אחת גוררת הזמנות מבוטלות, דירוגים שליליים ואובדן מיקומים בחיפוש. הבוט שלנו מעבד שינויים בשניות ומבטל טעויות. הוא שולף נתונים ישירות ממערכת הנהלת החשבונות שלכם — אין אפשרות לשגיאות הקלדה. התוצאה: דירוגי המוצרים משתפרים והזמנות מבוטלות יורדות ב-70%.
מקרה בוחן: עבור לקוח עם קטלוג של 15,000 SKU, עדכונים ידניים ארכו 4 שעות ביום. לאחר פריסת הבוט, הזמן ירד ל-10 דקות, והזמנות מבוטלות ירדו ב-70%. קנסות על מלאי שגוי בוטלו לחלוטין. בהשוואה למודולי ERP מוכנים, הבוט שלנו מציע תצורה גמישה יותר של רזרבות והתראות.
לפי התיעוד הרשמי של Ozon API, stock_levels מאפשר עדכון של עד 100 מוצרים לכל בקשה.
איך אנחנו משתלבים עם מקורות נתונים
יש צורך לאגד מספר מקורות. המקור העיקרי הוא מערכת המחסן שלכם (1C, MyWarehouse, Odoo). אנחנו מחברים בנוסף ספקים (דרך ייבוא) וקוראים רזרבות של מרקטפלייס. אנחנו גם מתחשבים ברזרבה וירטואלית מהאתר שלכם — עגלות קניות פתוחות.
| מערכת הנהלת חשבונות | שיטת אינטגרציה | מורכבות |
|---|---|---|
| 1C | שירות HTTP (REST) או webhook | בינונית |
| MyWarehouse | REST API | נמוכה |
| Odoo | XML-RPC / JSON-RPC | בינונית |
אנחנו מבנים נתונים באמצעות טבלאות 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() ); . הראשונה מאחסנת מלאי כולל ורזרבות, השנייה את הנתונים העדכניים לכל מרקטפלייס, והשלישית את היסטוריית הסנכרון לצורך ניפוי באגים.
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 אל 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; } } . הקוד דומה אבל מתחשב בפרטים ספציפיים — token בכותרת, מיפוי דרך 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); } } אנחנו מגדירים התראות — אם האתר שלכם מראה מלאי חיובי אבל המרקטפלייס מראה אפס במשך יותר משעתיים, אתם מקבלים הודעה. זה מונע דה-סנכרון. תרחישי התראה:
| מצב | הודעה | פעולה |
|---|---|---|
| דה-סנכרון > שעה | Telegram / אימייל | סנכרון מחדש אוטומטי |
| שגיאת API של מרקטפלייס | Telegram | בדיקת לוג ידנית |
| רזרבה מוצתה | אימייל | חידוש מלאי במחסן |
מידע נוסף על השוואת API של מרקטפלייס
| מרקטפלייס | פרטי API | מגבלת בקשות | מהירות עדכון |
|---|---|---|---|
| Ozon | PUT /v2/products/stocks | 100 מוצרים לבקשה | עד דקה |
| Wildberries | PUT /api/v3/warehouses/{id}/stocks | 50 בקשות/שנייה | עד 2 דקות |
מה כלול בעבודה?
| רכיב | תיאור |
|---|---|
| תיעוד | ארכיטקטורה, סכמת נתונים, מדריך תפעול |
| גישה | הגדרת מפתח API, הרשאות למערכת הנהלת חשבונות ומרקטפלייס |
| הדרכה | הדגמת בוט, ניתוח לוגים והתראות לצוות שלכם |
| תמיכה | אחריות לחודש אחד, ולאחר מכן לפי הסכם |
טעויות אינטגרציה אופייניות
- SKU שגוי — הבדלי פורמט בין מערכת הנהלת החשבונות למרקטפלייס. נפתר עם מערכת מיפוי אחידה.
- חריגה ממגבלות בקשות — עדכונים תכופים מדי. הגדלת מרווח או שימוש בקבוצות.
- שגיאת הרשאה — token שפג תוקפו. הגדרת חידוש מפתח אוטומטי.
- אי-התאמה במלאי — הזנחת רזרבות. יישום מלאי רזרבה.
התהליך שלנו
- ניתוח — לימוד מערכת הנהלת החשבונות שלכם, ה-API הנוכחיים, גודל הקטלוג.
- עיצוב — סכמת נתונים, לוגיקת רזרבות, מודולי אינטגרציה.
- פיתוח — כתיבת קוד סנכרון, התראות, לוגים.
- בדיקות — בדיקת כל התרחישים (כולל שגיאות) בסביבת staging.
- פריסה — התקנה על השרת שלכם או בענן, הגדרת ניטור.
- תחזוקה — תקופת אחריות, הדרכת צוות.
לוח זמנים
- גרסה בסיסית (Ozon + WB + 1C): 4–5 ימי עסקים.
- תוכניות רזרבה מורכבות ומרקטפלייס נוספים: +1–2 ימים.
קבלו ייעוץ — נעריך את הפרויקט שלכם ביום אחד. הזמינו פיתוח בוט כדי לבטל קנסות ולחסוך זמן לצוות שלכם.







