رفتن به محتوا

موجودی

مخاطب: برنامه‌نویس سایت فروشگاهی، نرم‌افزار انبارداری یا حسابداری که می‌خواهد موجودی پنل دیجی‌کالا را بخواند، با موجودی خود همگام کند یا فروش‌های خود را در آن ثبت کند.

دیجی‌کالا برای هر تنوع چند عدد موجودی جدا نگه می‌دارد: کالایی که در انبار خود شماست، کالایی که در انبار دیجی‌کالاست، واحدهایی که برای سفارش‌ها رزرو شده‌اند و واحدهایی که در راه‌اند. سلر ۳۶۰ همه‌ی این اعداد را در یک مدل موجودی واحد کنار هم می‌گذارد؛ همان مدلی که همه‌ی صفحه‌های پنل سلر ۳۶۰ از آن استفاده می‌کنند.

با مسیرهای این صفحه می‌توانید:

کار مسیر در دسترس
خواندن موجودی همه‌ی تنوع‌ها GET /v1/stock فعال
خواندن موجودی یک تنوع GET /v1/stock/{variant_id} فعال
تاریخچه‌ی روزانه‌ی موجودی GET /v1/stock/history فعال
تعیین عدد مطلق موجودی فروشنده PUT /v1/stock/{variant_id} فعال
ثبت فروش یا برگشت (تغییر نسبی) POST /v1/stock/{variant_id}/adjustments فعال
تعیین موجودی چند تنوع در صف POST /v1/stock/batch فعال

و با رویدادهای وب‌هوک stock.changed، stock.out، stock.low و stock.stockout_soon حداکثر حدود ۱۵ ثانیه پس از هر تغییر خبردار شوید.

دسترسی برای
stock:read همه‌ی مسیرهای خواندن این صفحه
stock:write تعیین مطلق، تغییر نسبی و تغییر در صف
catalog:read پیشنهاد می‌شود: برای خواندن عنوان و کد تنوع‌ها (GET /v1/variants)

کلید را با کمترین دسترسی لازم بسازید. نرم‌افزاری که فقط موجودی را نمایش می‌دهد، به stock:write نیاز ندارد.

ماژول «API و وب‌هوک» باید برای پنل فعال باشد؛ در غیر این صورت همه‌ی مسیرها با کد 403 و خطای module_inactive پاسخ می‌دهند. برای پنلی که اشتراک آن به پایان رسیده است، خواندن ممکن است ولی همه‌ی نوشتن‌ها با خطای subscription_inactive رد می‌شوند.

https://api.seller360.ir
فیلد برچسب در پنل معنی
sellable «قابل فروش» عددی که همین حالا در دیجی‌کالا فروختنی است. سایت شما باید همین عدد را نشان دهد.
seller_stock «موجودی در انبار فروشنده» کالایی که در انبار خودتان دارید و در پنل دیجی‌کالا ثبت کرده‌اید.
warehouse_stock «موجودی در انبار دیجی‌کالا» کالای شما که در انبار دیجی‌کالاست.
reserved.digikala «رزرو ارسال دیجی‌کالا» واحدهای رزروشده برای سفارش‌هایی که دیجی‌کالا ارسال می‌کند.
reserved.seller «رزرو ارسال فروشنده» واحدهای رزروشده برای سفارش‌هایی که خودتان ارسال می‌کنید.
warehouse_available «باقی‌مانده در انبار دیجی‌کالا» انبار دیجی‌کالا منهای رزرو دیجی‌کالا.
reservation_shortfall — رزرو دیجی‌کالا بیش از موجودی انبار آن؛ این واحدها را شما تامین می‌کنید.
seller_available «باقی‌مانده در انبار فروشنده» موجودی شما منهای کسری رزرو و رزرو ارسال فروشنده.
sellable_calculated «تعداد قابل فروش» محاسبه‌ی سلر ۳۶۰ از روی اعداد بالا.
in_transit.orders «در راه برای سفارش‌ها» واحدهای محموله‌های سفارش در راه انبار دیجی‌کالا.
in_transit.consignment «در محموله‌ی انبارش» محموله‌های انبارش ساخته‌شده و هنوز دریافت‌نشده.
version — شماره‌ی نسخه؛ با هر تغییر بزرگ‌تر می‌شود.
observed_at — زمان آخرین خواندن این اعداد از دیجی‌کالا.
stale — true اگر پایش این پنل از حد معمول عقب افتاده باشد.
warehouse_available = max(0, warehouse_stock − reserved.digikala)
reservation_shortfall = max(0, reserved.digikala − warehouse_stock)
seller_available = max(0, seller_stock − reservation_shortfall − reserved.seller)
sellable_calculated = warehouse_available + seller_available

این اعداد روی یک تنوع واقعی (محافظ ولتاژ، کد 84780448) اندازه‌گیری شده است. خریداری در دیجی‌کالا کالا را به سبد برد و به درگاه بانک رفت، ولی پرداخت نکرد:

لحظه seller_stock reserved.digikala sellable
پیش از خرید 39 0 39
خریدار در درگاه بانک (دیده‌شده در پایش ۱۵ ثانیه‌ای) 39 1 38

«موجودی در انبار فروشنده» تغییر نکرد؛ فقط رزرو بالا رفت و «قابل فروش» یکی کم شد. سایتی که sellable را نشان دهد، از همان لحظه آخرین واحد را به خریدار دیگری نمی‌فروشد.

  • شماره‌ی نسخه (version): هر بار یکی از اعداد موجودی یک تنوع تغییر کند، نسخه‌ی آن بزرگ‌تر می‌شود. پیام‌های وب‌هوک ممکن است تکراری، دیر یا جابه‌جا برسند؛ عددی را که نسخه‌اش از نسخه‌ی ذخیره‌شده‌ی شما کوچک‌تر یا برابر است، نادیده بگیرید.
  • تازگی: موجودی هر پنل حدود هر ۱۵ ثانیه از دیجی‌کالا خوانده می‌شود. زمان آخرین خواندن در observed_at است.
  • stale: اگر خواندن یک پنل بیش از حد معمول عقب بماند (مثلا دیجی‌کالا در دسترس نباشد)، این فیلد true می‌شود. در این حالت اعداد آخرین مقدار شناخته‌شده‌اند.
// نسخه‌ی کوچک‌تر یا برابر را نادیده بگیرید
$q = $db->prepare("UPDATE products SET sellable = ?, stock_version = ?
WHERE variant_id = ? AND stock_version < ?");
$q->execute([$s["sellable"], $s["version"], $s["variant_id"], $s["version"]]);

GET /v1/stock — موجودی همه‌ی تنوع‌ها

Section titled “GET /v1/stock — موجودی همه‌ی تنوع‌ها”

موجودی همه‌ی تنوع‌های پنل از آخرین پایش. برای همگام‌سازی کامل اولیه و برای جبران پس از قطعی مناسب است.

GET /v1/stock?page=1&size=100&sellable=1 HTTP/1.1
Host: api.seller360.ir
Authorization: Bearer s360_live_...

پارامترها

پارامتر نوع اجباری توضیح
page عدد خیر شماره‌ی صفحه؛ پیش‌فرض ۱.
size عدد خیر تعداد در هر صفحه؛ پیش‌فرض ۵۰، بیشینه ۵۰۰.
changed_since_version عدد خیر فقط تنوع‌هایی که نسخه‌ی آن‌ها از این عدد بزرگ‌تر است.
supplier_code متن خیر فقط تنوع‌های این کد فروشنده.
sellable 0 یا 1 خیر فقط قابل فروش‌ها (1) یا ناموجودها (0).

پاسخ نمونه

{
"status": "ok",
"data": [
{
"variant_id": 84780448,
"sku": "PE-5144",
"supplier_code": "5144",
"sellable": 38,
"seller_stock": 39,
"warehouse_stock": 0,
"reserved": { "total": 1, "digikala": 1, "seller": 0 },
"warehouse_available": 0,
"reservation_shortfall": 1,
"seller_available": 38,
"sellable_calculated": 38,
"in_transit": { "orders": 0, "consignment": 0 },
"version": 1842,
"observed_at": "2026-11-11T17:43:22+03:30",
"stale": false
}
],
"pager": { "page": 1, "item_per_page": 100, "total_pages": 7, "total_rows": 606 }
}

GET /v1/stock/{variant_id} — موجودی یک تنوع

Section titled “GET /v1/stock/{variant_id} — موجودی یک تنوع”

همان ساختار، برای یک تنوع. اگر تنوع در این پنل نباشد، کد 404 و خطای variant_not_found برمی‌گردد.

GET /v1/stock/history — تاریخچه‌ی روزانه فعال

Section titled “GET /v1/stock/history — تاریخچه‌ی روزانه ”

یک ردیف برای هر تنوع در هر روز (به وقت تهران) که هر شب ثبت می‌شود. بازه‌ی هر درخواست حداکثر ۹۰ روز است.

پارامتر نوع اجباری توضیح
variant_id عدد خیر فقط این تنوع.
from تاریخ بله اولین روز، شامل همان روز (مثلا 2026-10-13).
to تاریخ خیر آخرین روز، شامل همان روز؛ پیش‌فرض دیروز.
page، size عدد خیر صفحه‌بندی.

PUT /v1/stock/{variant_id} — تعیین عدد مطلق فعال

Section titled “PUT /v1/stock/{variant_id} — تعیین عدد مطلق ”

«موجودی در انبار فروشنده» را در دیجی‌کالا روی عدد داده‌شده می‌گذارد و پس از ثبت قطعی در دیجی‌کالا پاسخ می‌دهد. برای انبارگردانی و اصلاح مناسب است، نه برای ثبت فروش (هشدار ۴).

PUT /v1/stock/84780448 HTTP/1.1
Host: api.seller360.ir
Authorization: Bearer s360_live_...
Idempotency-Key: count-1405-08-21-84780448
Content-Type: application/json
{ "seller_stock": 40, "expected_version": 1842 }
فیلد بدنه نوع اجباری توضیح
seller_stock عدد بله عدد تازه؛ ۰ تا ۱۰۰٬۰۰۰.
expected_version عدد خیر اگر نسخه‌ی فعلی با این عدد برابر نباشد، تغییر انجام نمی‌شود.

پاسخ موفق: کد 200 با ساختار کامل موجودی و نسخه‌ی تازه.

POST /v1/stock/{variant_id}/adjustments — ثبت فروش یا برگشت فعال

Section titled “POST /v1/stock/{variant_id}/adjustments — ثبت فروش یا برگشت ”

موجودی فروشنده را به اندازه‌ی quantity کم یا زیاد می‌کند. بررسی و تغییر در یک قدم و زیر قفل انجام می‌شود: اگر موجودی کافی نباشد، هیچ تغییری انجام نمی‌شود. پس اگر دو خریدار هم‌زمان آخرین واحد را بخواهند، فقط یکی موفق می‌شود.

  1. پیش از فرستادن خریدار به درگاه یک تغییر با quantity منفی و reason: "sale" بفرستید.
  2. اگر خطای insufficient_stock برگشت، به خریدار بگویید کالا تمام شده است.
  3. اگر پرداخت لغو شد، همان مقدار را با quantity مثبت و reason: "return" برگردانید.
  4. اگر پاسخ را دریافت نکردید (قطع اتصال)، همان درخواست را با همان Idempotency-Key تکرار کنید؛ موجودی دو بار کم نمی‌شود.
  5. اگر خطای digikala_outcome_unknown برگشت، تکرار با همان کلید همان خطا را برمی‌گرداند. موجودی را با GET /v1/stock/{variant_id} بخوانید؛ اگر فروش ثبت نشده بود، با یک Idempotency-Key تازه دوباره بفرستید. برای این خواندن از GET /v1/stock/{variant_id}?live=1 استفاده کنید که موجودی را همان لحظه از دیجی‌کالا می‌خواند. فقط به خواندنی اعتماد کنید که observed_at آن پس از زمان همان خطا باشد؛ عدد قدیمی‌تر هنوز نتیجه‌ی تغییر را نشان نمی‌دهد. اگر چنین خواندنی نرسید، سفارش را برای بررسی دستی نگه دارید و کورکورانه دوباره نفرستید.
فیلد بدنه نوع اجباری توضیح
quantity عدد بله منفی برای کم کردن، مثبت برای زیاد کردن؛ صفر مجاز نیست.
reason sale، return، correction بله دلیل تغییر.
reference متن خیر شناسه‌ی سفارش در سایت شما، برای پیگیری.

پاسخ نمونه (کد 201)

{
"status": "ok",
"data": {
"id": "adj_5d0e77",
"quantity": -1,
"reason": "sale",
"reference": "ORD-58213",
"created_at": "2026-11-12T10:15:03+03:30",
"stock": { "variant_id": 84780448, "sellable": 37, "seller_stock": 38, "version": 1843 }
}
}

خطاهای این مسیر

کد HTTP خطا معنی تکرار بی‌خطر است؟
409 insufficient_stock موجودی کافی نیست؛ هیچ تغییری انجام نشد. خیر؛ موجودی را بخوانید.
409 stock_write_locked تقسیم موجودی در حال اجراست. بله، پس از Retry-After.
409 idempotency_mismatch این کلید یکتا قبلا با بدنه‌ی دیگری استفاده شده است. خیر؛ کلید تازه بسازید.
409 idempotency_in_progress درخواستی با همین کلید در حال انجام است. بله، چند ثانیه بعد.
502 digikala_refused دیجی‌کالا تغییر را نپذیرفت؛ هیچ تغییری ثبت نشد. پس از بررسی علت.
502 digikala_outcome_unknown پاسخ دیجی‌کالا نرسید و نتیجه معلوم نیست. خیر؛ اول موجودی را بخوانید، سپس در صورت نیاز با کلید تازه.
503 digikala_rate_limited سقف دیجی‌کالا برای این پنل پر است. بله، پس از Retry-After.
503 digikala_unavailable دیجی‌کالا در دسترس نیست و هیچ تغییری ثبت نشد. بله، پس از Retry-After.

فهرست همه‌ی خطاها در صفحه‌ی خطاها است.

POST /v1/stock/batch — تعیین موجودی چند تنوع در صف فعال

Section titled “POST /v1/stock/batch — تعیین موجودی چند تنوع در صف ”

تا ۱۰۰ تنوع در هر درخواست. پاسخ فوری 202 فقط یعنی «در صف ثبت شد»؛ نتیجه با GET /v1/jobs/{job_id} و رویداد job.completed اعلام می‌شود. ثبت در دیجی‌کالا ممکن است چند دقیقه طول بکشد (هشدار ۶).

رویداد چه وقت
stock.changed یکی از اعداد موجودی یک تنوع تغییر کرد؛ حداکثر حدود ۱۵ ثانیه پس از تغییر در دیجی‌کالا.
stock.out «قابل فروش» تنوع به صفر رسید.
stock.low باقی‌مانده در انبار دیجی‌کالا پیش از رسیدن محموله‌ی تازه تمام می‌شود (کالا از موجودی شما فروخته می‌شود ولی نشان «ارسال دیجی‌کالا» را از دست می‌دهد). حداکثر یک بار در روز برای هر تنوع.
stock.stockout_soon کل موجودی قابل فروش با سرعت فروش فعلی کمتر از آستانه‌ی روزهای هشدار شما دوام می‌آورد؛ خرید لازم است.

نمونه‌ی پیام stock.changed

{
"id": "evt_01HZY3K8",
"type": "stock.changed",
"created_at": "2026-11-11T17:43:22+03:30",
"panel_id": 1,
"livemode": true,
"data": {
"stock": { "variant_id": 84780448, "sku": "PE-5144", "sellable": 38, "seller_stock": 39, "version": 1842 },
"previous": { "sellable": 39, "seller_stock": 39, "version": 1841 }
}
}

پیش از استفاده از هر پیام، امضای آن را بررسی کنید.

Terminal window
curl -X POST https://api.seller360.ir/v1/stock/84780448/adjustments \
-H "Authorization: Bearer $S360_API_KEY" \
-H "Idempotency-Key: sale-ORD-58213-84780448" \
-H "Content-Type: application/json" \
-d '{"quantity": -1, "reason": "sale", "reference": "ORD-58213"}'