API สำหรับผู้ค้า: เชื่อม SKU การแจ้งสินค้าสั่งซื้อล่วงหน้า และสต็อกคลังเซินเจิ้นเข้ากับระบบของคุณ
สำหรับนิติบุคคลที่เปิดร้านบน Shopee, Coupang และ momo ส่งบาร์โค้ดสินค้าที่สร้างตอนลงขายเข้ามาทาง API แจ้งเลขพัสดุและรายการสินค้าข้างในล่วงหน้าเมื่อสั่งซื้อ เมื่อสินค้าถึงคลังเซินเจิ้น ระบบจะเปิดใบงานอัตโนมัติ ติดบาร์โค้ด และสแกนขึ้นชั้นวางทีละชิ้น พร้อมส่งข้อมูลสต็อกและส่วนต่างกลับแบบเรียลไทม์
นิติบุคคล
ผู้ที่สมัครได้ (ต้องมีเลขประจำตัวผู้เสียภาษี 8 หลัก)
200 รายการ
จำนวน SKU สูงสุดต่อคำขอแบบกลุ่ม
WO-SK
เปิดใบงานติดบาร์โค้ดอัตโนมัติเมื่อเข้าคลัง
60 ครั้ง / นาที
ค่าจำกัดอัตราเริ่มต้นต่อคีย์
1 ภาพรวมบริการ
ระยะที่ 1 ครอบคลุม “สินค้าและการรับเข้าคลัง” ตั้งแต่สร้าง SKU จนสินค้าขึ้นชั้นวางเป็นสต็อกในคลังเซินเจิ้น
สิ่งที่ทำได้ในตอนนี้
- สร้างหรืออัปเดต SKU แบบกลุ่ม (อ้างอิง
seller_skuของคุณ) โดยแต่ละสีและไซซ์มีบาร์โค้ดสินค้าแยกกัน และผูกกับรหัสตัวเลือกสินค้าบน Shopee / Coupang / momo - ตรวจสอบข้อกำหนดการนำเข้าอัตโนมัติตามพิกัดศุลกากรไต้หวัน 11 หลัก และระบุสินค้าที่ต้องผ่านการตรวจสอบ ต้องมีใบอนุญาต หรือห้ามนำเข้า
- แจ้งเลขพัสดุและรายการสินค้าในแต่ละกล่องล่วงหน้าเมื่อสั่งซื้อ เมื่อสินค้าถึงคลังเซินเจิ้น ระบบจะเปิดใบงานติดบาร์โค้ด WO-SK อัตโนมัติ และคลังจะติดบาร์โค้ดและสแกนขึ้นชั้นวางทีละชิ้น
- ค้นหาสต็อกแยกตามคลังและประวัติความเคลื่อนไหวของสต็อก และรับการแจ้งเตือนผ่าน webhook แบบเรียลไทม์เมื่อสินค้าถึงคลัง รับเข้าคลังเสร็จ มีส่วนต่างของจำนวน หรือสต็อกเปลี่ยนแปลง
ขั้นตอนการรับเข้าคลัง
- สร้าง SKU: ส่งบาร์โค้ดสินค้า ตัวเลือกสินค้า ชื่อสินค้าที่สำแดง และพิกัดศุลกากร
- แจ้งรับเข้าคลังล่วงหน้า: ส่งเลขพัสดุและจำนวนที่แจ้งของแต่ละ SKU
- เข้าคลังเซินเจิ้น: เมื่อสแกนเลขพัสดุ ระบบจะเปิดใบงาน WO-SK และพิมพ์ออกมาอัตโนมัติ
- ติดบาร์โค้ดและขึ้นชั้นวาง: คลังพิมพ์บาร์โค้ดสินค้า ติดทีละชิ้น และสแกนนับจำนวน
- รับเข้าคลังเสร็จสิ้น: จำนวนที่รับจริงเข้าสู่สต็อกคลังเซินเจิ้น สินค้าชำรุดนับแยก และแจ้งส่วนต่างไปยังระบบของคุณ
ฟีเจอร์ที่อยู่ระหว่างวางแผน
คำสั่งจัดส่งสินค้าแบบกลุ่ม ชุดการจัดส่งที่จัดกลุ่มอัตโนมัติตามข้อกำหนดการสำแดง รวมถึงสต็อกที่เตรียมไว้ล่วงหน้า การคัดแยก และใบปะหน้าพัสดุของแพลตฟอร์มที่คลังเถาหยวน จะประกาศในหน้านี้เมื่อเปิดใช้งาน
2 การสมัครและคีย์ API
API สำหรับผู้ค้าเปิดให้เฉพาะนิติบุคคล และคีย์แต่ละคีย์ผูกกับบัญชีผู้ค้าที่ได้รับอนุมัติแล้วหนึ่งบัญชี
ขั้นตอนการเปิดใช้งาน
- ที่ศูนย์สมาชิก ให้เพิ่มผู้สำแดงประเภท “บริษัท” และกรอกเลขประจำตัวผู้เสียภาษี 8 หลัก
- ติดต่อฝ่ายบริการลูกค้าของ HowBridge เพื่อขอเปิดใช้ API สำหรับผู้ค้า เมื่อผ่านการพิจารณาแล้วจะได้รับคีย์
- คีย์จะแสดงเพียงครั้งเดียว โปรดเก็บไว้ใน environment variable ฝั่งเซิร์ฟเวอร์ และห้ามใส่ไว้ในเบราว์เซอร์หรือแอป
- หากต้องการใช้ webhook ให้ตั้งค่าและยืนยัน URL ในหน้า API ของศูนย์สมาชิกก่อน จากนั้นจึงสมัครรับอีเวนต์ของผู้ค้า
Authorization: Bearer <คีย์> โทเค็นที่สร้างจากการเข้าสู่ระบบแอปหรือเว็บไซต์ของสมาชิกทั่วไปไม่สามารถเรียกใช้ API สำหรับผู้ค้าได้Authorization: Bearer 12|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Accept: application/json
3 ข้อกำหนดทั่วไป
ทุก endpoint ใช้กฎต่อไปนี้ร่วมกัน
Base URL
รูปแบบและภาษา
คำขอและการตอบกลับเป็น JSON ข้อความแสดงข้อผิดพลาดเป็นภาษาจีนตัวเต็มโดยค่าเริ่มต้น ส่ง Accept-Language: en เพื่อรับเป็นภาษาอังกฤษ ส่วนการตรวจสอบในโปรแกรมให้ใช้ error.code ซึ่งเป็นภาษาอังกฤษคงที่เสมอ
โครงสร้างการตอบกลับ
เมื่อสำเร็จจะตอบกลับ {"success": true, "data": …, "meta": …} เมื่อล้มเหลวจะตอบกลับ {"success": false, "error": {"code", "message", "errors", "context"}} โดย errors คือรายละเอียดแยกตามฟิลด์ ข้อยกเว้นเดียวคือกรณีไม่ได้ส่งคีย์หรือคีย์ไม่ถูกต้อง: HTTP 401 และ body เป็น {"message": "Unauthenticated."}
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "…",
"errors": [
{ "code": "TRACKING_IN_USE", "field": "packages.0.tracking_no", "message": "…" }
]
}
}
การจำกัดอัตรา
แต่ละคีย์เรียกใช้ได้ 60 ครั้งต่อนาทีและ 5,000 ครั้งต่อวัน (แพ็กเกจปริมาณสูง 300 ครั้งต่อนาทีและ 50,000 ครั้งต่อวัน) คำขอแบบกลุ่มนับเป็นหนึ่งครั้ง หากต้องการข้อมูลแบบเรียลไทม์ โปรดสมัครรับ webhook แทนการ polling
| Header ของการตอบกลับ | คำอธิบาย |
|---|---|
X-RateLimit-Limit | จำนวนสูงสุดต่อนาที |
X-RateLimit-Remaining | จำนวนครั้งที่เหลือในนาทีนี้ |
X-RateLimit-Limit-DayX-RateLimit-Remaining-Day | จำนวนสูงสุดต่อวันและจำนวนครั้งที่เหลือ |
Retry-After | จำนวนวินาทีที่ต้องรอก่อนลองใหม่เมื่อเกินขีดจำกัด |
Idempotency (Idempotency-Key)
คำขอที่เขียนข้อมูลสามารถส่ง header Idempotency-Key ได้ (8–128 ตัวอักษร ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข และ _-:.) เมื่อเครือข่ายหมดเวลา ให้ส่งซ้ำด้วย key เดิมและเนื้อหาเดิม จะได้รับการตอบกลับของครั้งแรกพร้อม header Idempotent-Replayed: true หากใช้ key เดิมแต่เนื้อหาต่างไปจะตอบกลับ 422 ระบบเก็บบันทึกไว้ 24 ชั่วโมง
การตอบกลับแบบกลุ่ม
endpoint แบบกลุ่มรายงานผลทีละรายการ: สำเร็จทั้งหมดตอบกลับ 200 ล้มเหลวบางส่วนตอบกลับ 207 ล้มเหลวทั้งหมดตอบกลับ 422 ทุกรายการมี index, status (created / updated / failed) และสาเหตุที่ล้มเหลว
อักขระที่ใช้ในรหัสระบุ
seller_sku ใช้ได้เฉพาะตัวอักษรภาษาอังกฤษ ตัวเลข และ ._- (1–64 ตัวอักษร) ส่วนบาร์โค้ดสินค้าใช้ / และ + ได้เพิ่มเติม (3–64 ตัวอักษร) ตัวพิมพ์ใหญ่และตัวพิมพ์เล็กถือว่าเหมือนกัน
4 SKU สินค้า
SKU ใช้ seller_sku ของคุณเป็นคีย์ที่ไม่ซ้ำ: การส่ง seller_sku เดิมซ้ำคือการอัปเดต และจะแก้ไขเฉพาะฟิลด์ที่ส่งมาเท่านั้น
สร้างหรืออัปเดต SKU แบบกลุ่ม
POST/api/v1/merchant/skus/batch
สูงสุด 200 รายการต่อครั้ง แต่ละรายการประมวลผลแยกกัน รายการหนึ่งล้มเหลวจะไม่กระทบรายการอื่น
| ฟิลด์ | ชนิดข้อมูล | จำเป็น | คำอธิบาย |
|---|---|---|---|
seller_sku | string | จำเป็น | รหัส SKU ของคุณ เช่น รหัส SKU ของตัวเลือกสินค้าบน Shopee |
product_name | string | จำเป็นเมื่อสร้างใหม่ | ชื่อสินค้า SKU ที่มีชื่อเดียวกันจะถูกจัดอยู่ภายใต้สินค้าเดียวกัน |
barcode | string | ไม่บังคับ | บาร์โค้ดสินค้า คลังจะพิมพ์ฉลากและสแกนขึ้นชั้นวางตามรหัสนี้ สีและไซซ์ที่ต่างกันต้องใช้บาร์โค้ดต่างกัน หากไม่มีบาร์โค้ดสามารถเว้นว่างได้ ระบบจะสร้างบาร์โค้ดระบบให้ หากยาวเกิน 16 ตัวอักษร ฉลากจะพิมพ์บาร์โค้ดระบบแทน |
gtin | string | ไม่บังคับ | GTIN (8 / 12 / 13 / 14 หลัก มีการตรวจสอบเลขตรวจสอบ) สำหรับสินค้าบน Shopee ที่ “ไม่มี GTIN” ให้ส่ง 00 |
spec | object | ไม่บังคับ | ตัวเลือกสินค้า เช่น {"color": "ดำ", "size": "M"} สูงสุด 5 รายการ |
declared_name_zhdeclared_name_en | string | ไม่บังคับ | ชื่อสินค้าที่สำแดง (จีน / อังกฤษ) ให้ระบุวัสดุและการใช้งาน อย่าเขียนว่า “ตัวอย่างสินค้า” หรือ “ของขวัญ” |
declared_unit_value | number | ไม่บังคับ | ราคาต่อหน่วยที่สำแดง คือราคาซื้อต่อหน่วยจากซัพพลายเออร์ ไม่ใช่ราคาขายบนแพลตฟอร์ม |
declared_currency | string | ไม่บังคับ | CNY, TWD หรือ USD จำเป็นเมื่อกรอกราคาต่อหน่วย |
hs_code | string | ไม่บังคับ | รหัสพิกัดศุลกากร 11 หลัก ระบบใช้รหัสนี้ตรวจสอบข้อกำหนดการนำเข้า |
origin_country | string | ไม่บังคับ | รหัส ISO ของประเทศต้นกำเนิด ค่าเริ่มต้น CN |
weight_g | integer | ไม่บังคับ | น้ำหนักต่อชิ้น (กรัม) |
dimensions_cm | array | ไม่บังคับ | ยาว กว้าง สูง (เซนติเมตร) เช่น [20, 15, 3] |
battery_type | string | ไม่บังคับ | none, contained (แบตเตอรี่ในตัว), packed (แบตเตอรี่แถมมาในกล่อง), standalone (แบตเตอรี่อย่างเดียว) |
channels | array | ไม่บังคับ | การจับคู่สินค้าบนแพลตฟอร์ม สูงสุด 20 ชุด: platform (shopee / coupang / momo / other), shop_id, item_id, model_id, platform_sku |
ตัวอย่างคำขอ (POST JSON)
curl -X POST https://0523.tw/api/v1/merchant/skus/batch \ -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sku-sync-20260917-001" \ -d '{ "items": [ { "seller_sku": "TEE-RED-S", "barcode": "4710000000011", "product_name": "Cotton T-shirt", "spec": { "color": "red", "size": "S" }, "declared_name_en": "Cotton knitted T-shirt", "declared_unit_value": 18.5, "declared_currency": "CNY", "hs_code": "61091000006", "weight_g": 160, "channels": [ { "platform": "shopee", "shop_id": "123456", "item_id": "2233", "model_id": "445566" } ] } ] }'
ตอบกลับ 200
{
"success": true,
"data": [
{
"index": 0,
"seller_sku": "TEE-RED-S",
"status": "created",
"sku": {
"seller_sku": "TEE-RED-S",
"barcode": "4710000000011",
"system_barcode": null,
"pick_code": "131999",
"hs_code": "61091000006",
"regulation": { "status": "ok", "import_codes": [], "reasons": [] },
"channels": [ { "platform": "shopee", "shop_id": "123456", "item_id": "2233", "model_id": "445566", "platform_sku": null } ]
}
}
],
"meta": { "summary": { "created": 1, "updated": 0, "failed": 0 } }
}
ผลตรวจสอบข้อกำหนดการนำเข้า (regulation.status)
| ok | ไม่มีรหัสข้อกำหนดการนำเข้า |
| review_required | ข้อกำหนดครอบคลุมสินค้าเพียงบางส่วน (เช่น C02 “สินค้าบางส่วนภายใต้รายการนี้ต้องผ่านการตรวจสอบ”) ต้องยืนยันตามการใช้งานจริงของสินค้า |
| formal_required | มีข้อกำหนดการนำเข้าเกี่ยวข้อง (การตรวจสอบ การกักกันโรค ใบอนุญาต ฯลฯ) ไม่สามารถใช้การสำแดงแบบย่อได้ |
| blocked | สินค้าที่มีแหล่งกำเนิดในจีนแผ่นดินใหญ่และห้ามนำเข้า (MW0 ประเทศต้นกำเนิดคือจีนแผ่นดินใหญ่) ไม่สามารถแจ้งรับเข้าคลังล่วงหน้าได้ |
| unclassified | ยังไม่ได้ระบุพิกัดศุลกากร จึงตรวจสอบไม่ได้ |
ค้นหา SKU
GET/api/v1/merchant/skus
กรองได้ด้วย seller_sku, barcode, regulation_status, updated_since (ISO 8601) และแบ่งหน้าด้วย page / per_page (สูงสุด 100)
SKU รายการเดียว
GET/api/v1/merchant/skus/{seller_sku}
อัปเดตการจับคู่สินค้าบนแพลตฟอร์ม
PUT/api/v1/merchant/skus/{seller_sku}/channels
รายการที่ส่งมาจะแทนที่การจับคู่เดิมทั้งหมด ตัวเลือกสินค้าเดียวกันบนแพลตฟอร์มไม่สามารถผูกกับสอง SKU พร้อมกันได้
ดาวน์โหลดฉลากบาร์โค้ดสินค้า
GET/api/v1/merchant/skus/{seller_sku}/label.pdf?qty=10
ตอบกลับเป็นไฟล์ PDF ฉลากขนาด 40×30mm โดย qty คือจำนวนแผ่น (1–1000) คลังเซินเจิ้นใช้ฉลากแบบเดียวกันเมื่อติดบาร์โค้ด endpoint นี้มีไว้สำหรับกรณีที่คุณต้องการติดบาร์โค้ดเองก่อนจัดส่ง
5 การแจ้งรับเข้าคลังล่วงหน้า
หลังจากซัพพลายเออร์จัดส่งสินค้าที่สั่งซื้อแล้ว ให้แจ้งเลขพัสดุและรายการสินค้าข้างในล่วงหน้า ใบรับเข้าคลังหนึ่งใบมีเลขพัสดุได้หลายเลข และแต่ละเลขระบุ SKU และจำนวน
สร้างใบรับเข้าคลัง
POST/api/v1/merchant/inbound-orders
ตรวจสอบทั้งใบ: หากมีข้อผิดพลาดใดๆ จะไม่มีการสร้างใบนั้น เลขพัสดุหนึ่งเลขอยู่ได้ในใบรับเข้าคลังที่กำลังดำเนินการเพียงใบเดียวในเวลาเดียวกัน SKU ที่ซ้ำกันในพัสดุเดียวกันจะถูกรวมจำนวน
| ฟิลด์ | ชนิดข้อมูล | จำเป็น | คำอธิบาย |
|---|---|---|---|
reference_no | string | จำเป็น | เลขใบสั่งซื้อหรือเลขใบรับเข้าคลังของคุณ ต้องไม่ซ้ำภายในผู้ค้ารายเดียวกัน (ตัวอักษรภาษาอังกฤษ ตัวเลข และ ._-/) |
supplier_order_no | string | ไม่บังคับ | เลขคำสั่งซื้อของซัพพลายเออร์ เช่น เลขคำสั่งซื้อ 1688 |
warehouse_code | string | ไม่บังคับ | คลังที่รับเข้า ขณะนี้รับเฉพาะ SZ (คลังเซินเจิ้น) |
notes | string | ไม่บังคับ | หมายเหตุ (สูงสุด 1,000 ตัวอักษร) |
packages | array | จำเป็น | รายการพัสดุ สูงสุด 50 ชิ้น |
packages[].tracking_no | string | จำเป็น | เลขพัสดุของบริษัทขนส่งในจีน |
packages[].carrier | string | ไม่บังคับ | รหัสบริษัทขนส่ง เช่น yto, sf |
packages[].items | array | จำเป็น | สินค้าในพัสดุ: seller_sku และ qty รวมทั้งใบรับเข้าคลังได้สูงสุด 500 บรรทัด |
ตัวอย่างคำขอ (POST JSON)
curl -X POST https://0523.tw/api/v1/merchant/inbound-orders \ -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: po-20260917-0001" \ -d '{ "reference_no": "PO-20260917-0001", "supplier_order_no": "1688-3312456789", "packages": [ { "tracking_no": "YT1234567890123", "carrier": "yto", "items": [ { "seller_sku": "TEE-RED-S", "qty": 40 }, { "seller_sku": "TEE-RED-M", "qty": 60 } ] } ] }'
reference_no เดิมอีกครั้งจะตอบกลับ 409 INBOUND_REFERENCE_EXISTS และ error.context.inbound_order_id จะมี id ของใบรับเข้าคลังเดิม หากต้องการลองใหม่อย่างปลอดภัย ให้ส่ง Idempotency-Keyสถานะใบรับเข้าคลัง
| created | แจ้งล่วงหน้าแล้ว ยังไม่มีพัสดุถึงคลัง |
| partially_arrived | พัสดุบางส่วนถึงคลังเซินเจิ้นแล้ว |
| arrived | พัสดุทั้งหมดถึงคลังแล้ว กำลังติดบาร์โค้ดและขึ้นชั้นวาง |
| completed | ขึ้นชั้นวางครบทั้งหมด จำนวนตรงกับที่แจ้งล่วงหน้า |
| completed_with_discrepancy | เสร็จสิ้นทั้งหมด แต่มีการรับขาด รับเกิน หรือสินค้าชำรุด |
| cancelled | ยกเลิกแล้ว |
สถานะพัสดุ
| awaiting_arrival | รอถึงคลัง |
| labeling | เข้าคลังแล้วและเปิดใบงานแล้ว กำลังติดบาร์โค้ดและขึ้นชั้นวาง |
| received | ขึ้นชั้นวางเสร็จสิ้น |
| mismatch | เจ้าของพัสดุที่บันทึกตอนเข้าคลังไม่ตรงกับที่คุณแจ้งล่วงหน้า ฝ่ายบริการลูกค้ากำลังตรวจสอบ |
| cancelled | ยกเลิกหรือเป็นโมฆะแล้ว เลขพัสดุถูกปลดให้ใช้ใหม่ได้ |
ค้นหาใบรับเข้าคลัง
GET/api/v1/merchant/inbound-orders
GET/api/v1/merchant/inbound-orders/{id}
กรองได้ด้วย status, reference_no, updated_since พัสดุแต่ละชิ้นจะตอบกลับจำนวนที่แจ้งล่วงหน้า จำนวนที่รับจริง จำนวนที่ชำรุด และส่วนต่าง
ยกเลิกใบรับเข้าคลัง
POST/api/v1/merchant/inbound-orders/{id}/cancel
ยกเลิกได้เฉพาะเมื่อยังไม่มีพัสดุใดถึงคลัง หลังยกเลิกแล้วสามารถแจ้งเลขพัสดุล่วงหน้าใหม่ได้
6 การค้นหาสต็อก
สต็อกแยกตามคลัง: SZ คลังเซินเจิ้น, TY คลังเถาหยวน (สต็อกคลังเถาหยวนจะเปิดพร้อมฟีเจอร์การจัดส่ง)
ค้นหาสต็อก
GET/api/v1/merchant/inventory?warehouse_code=SZ
กรองได้ด้วย warehouse_code และ seller_sku[] (สูงสุด 200 รายการ)
on_hand | จำนวนในคลัง |
reserved | จำนวนที่ถูกกันไว้สำหรับคำสั่งซื้อ |
available | จำนวนที่ใช้ได้ = ในคลัง − ที่กันไว้ |
damaged | จำนวนที่ชำรุด ไม่สามารถจัดส่งได้ |
ตอบกลับ 200
{
"success": true,
"data": [
{ "seller_sku": "TEE-RED-S", "barcode": "4710000000011", "warehouse_code": "SZ",
"on_hand": 38, "reserved": 0, "available": 38, "damaged": 2, "updated_at": "2026-09-17T15:20:11+08:00" }
],
"meta": { "total": 1, "page": 1, "per_page": 100, "last_page": 1 }
}
ประวัติความเคลื่อนไหวสต็อก
GET/api/v1/merchant/inventory/movements?after_id=0&limit=200
บันทึกความเคลื่อนไหวที่เพิ่มได้อย่างเดียวและไม่มีการแก้ไข ใช้เคอร์เซอร์ after_id เลื่อนไปหน้าถัดไป (สูงสุด 500 รายการต่อครั้ง) และเก็บค่า meta.next_after_id จากการตอบกลับไว้ เพื่อดึงข้อมูลต่อสำหรับการกระทบยอด
7 อีเวนต์ Webhook
เมื่อเกิดอีเวนต์ ระบบจะส่งข้อมูลไปยัง URL ของคุณทันที โดยไม่ต้อง polling
วิธีตั้งค่า
- ไปที่หน้า API ของศูนย์สมาชิกเพื่อตั้งค่า URL ของ webhook (รับเฉพาะ https) และยืนยันความเป็นเจ้าของให้เสร็จ: endpoint ของคุณต้องตอบกลับ HTTP 200 โดย body เป็น
{"challenge": "ค่าที่ได้รับ"} - เรียก
PUT /api/v1/merchant/webhook/eventsเพื่อสมัครรับอีเวนต์ของผู้ค้า การเปลี่ยน URL ในศูนย์สมาชิกภายหลังจะไม่ล้างการสมัครรับอีเวนต์ของผู้ค้า
curl -X PUT https://0523.tw/api/v1/merchant/webhook/events \ -H "Authorization: Bearer $LUCKY_MERCHANT_KEY" \ -H "Content-Type: application/json" \ -d '{"events": ["inbound.arrived", "inbound.received", "inbound.discrepancy", "inventory.changed"]}'
รายการอีเวนต์
sku.regulation_flagged | ผลตรวจสอบข้อกำหนดการนำเข้าของ SKU เปลี่ยนเป็นต้องยืนยัน ต้องยื่นใบขนสินค้าแบบเต็มรูปแบบ หรือห้ามนำเข้า |
inbound.arrived | พัสดุถึงคลังเซินเจิ้นและเปิดใบงานแล้ว |
inbound.mismatch | เจ้าของพัสดุที่บันทึกตอนเข้าคลังไม่ตรงกับที่แจ้งล่วงหน้า ฝ่ายบริการลูกค้ากำลังตรวจสอบ |
inbound.received | พัสดุขึ้นชั้นวางเสร็จสิ้น พร้อมจำนวนที่แจ้งล่วงหน้า จำนวนที่รับจริง และจำนวนที่ชำรุดของแต่ละ SKU |
inbound.discrepancy | จำนวนที่ขึ้นชั้นวางไม่ตรงกับที่แจ้งล่วงหน้าหรือมีสินค้าชำรุด (ส่งพร้อมกับ inbound.received) |
inventory.changed | สต็อกมีการเปลี่ยนแปลง พร้อมสต็อกล่าสุดของ SKU ที่เปลี่ยนแปลง |
inbound.received
{
"event": "inbound.received",
"delivery_id": "5b0f1c2e-8f3a-4d7e-9c21-0a6b2d4e8f10",
"created_at": "2026-09-17T15:20:11+08:00",
"data": {
"inbound_order_id": 128,
"reference_no": "PO-20260917-0001",
"order_status": "completed_with_discrepancy",
"tracking_no": "YT1234567890123",
"work_order": "WO-SK-315",
"warehouse_code": "SZ",
"items": [
{ "seller_sku": "TEE-RED-S", "expected_qty": 40, "received_qty": 38, "damaged_qty": 2, "difference": 0 },
{ "seller_sku": "TEE-RED-M", "expected_qty": 60, "received_qty": 59, "damaged_qty": 0, "difference": -1 }
],
"received_at": "2026-09-17T15:20:10+08:00"
}
}
ตรวจสอบลายเซ็น
การส่งแต่ละครั้งจะมี X-Lucky-Event, X-Lucky-Delivery-Id และ X-Lucky-Signature: t=ประทับเวลา,v1=ลายเซ็น ใช้ webhook secret ของคุณคำนวณ HMAC-SHA256 จาก “ประทับเวลา + . + body ดิบ” แล้วเปรียบเทียบกับ v1 และปฏิเสธประทับเวลาที่เก่ากว่า 5 นาที เมื่อส่งอีเวนต์เดิมซ้ำ delivery_id จะไม่เปลี่ยน จึงใช้ตัดรายการซ้ำได้
หากการตอบกลับไม่ใช่ 2xx ระบบจะลองส่งใหม่หลังจาก 1 นาที, 5 นาที, 30 นาที, 2 ชั่วโมง และ 6 ชั่วโมง หากล้มเหลวติดต่อกัน 20 ครั้ง webhook จะถูกปิดใช้งานอัตโนมัติ และต้องตั้งค่าใหม่ที่ศูนย์สมาชิก
// PHP $body = file_get_contents('php://input'); $header = $_SERVER['HTTP_X_LUCKY_SIGNATURE'] ?? ''; parse_str(str_replace(',', '&', $header), $sig); // ['t' => '1789…', 'v1' => 'ab12…'] $expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $body, getenv('LUCKY_WEBHOOK_SECRET')); if (! hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) ($sig['t'] ?? 0)) > 300) { http_response_code(400); exit; } $event = json_decode($body, true); // de-duplicate by $event['delivery_id'] http_response_code(200);
8 รหัสข้อผิดพลาด
error.code เป็นภาษาอังกฤษคงที่ ด้านล่างคือข้อผิดพลาดที่พบบ่อย
| HTTP | error.code | คำอธิบาย |
|---|---|---|
| 401 | — | ไม่ได้ส่งคีย์ คีย์ไม่ถูกต้อง หรือคีย์หมดอายุ (body เป็น {"message": "Unauthenticated."}) |
| 403 | MERCHANT_TOKEN_REQUIRED | โทเค็นนี้ไม่มีสิทธิ์ใช้ API สำหรับผู้ค้า (เช่น โทเค็นที่สร้างจากการเข้าสู่ระบบของสมาชิกทั่วไป) |
| 403 | MERCHANT_NOT_APPROVEDMERCHANT_SUSPENDED | บัญชียังไม่ได้รับอนุมัติเป็นผู้ค้า หรือผู้ค้าถูกระงับ |
| 403 | APP_SUSPENDEDAPP_REVOKEDAPP_NOT_FOUND | แอปพลิเคชัน API ที่ผูกกับคีย์นี้ถูกระงับหรือเพิกถอนแล้ว |
| 422 | VALIDATION_FAILEDPRODUCT_NAME_REQUIRED | รูปแบบข้อมูลไม่ถูกต้อง ดูรายละเอียดแยกตามฟิลด์ใน error.errors |
| 422 | BATCH_TOO_LARGE | จำนวนรายการในคำขอแบบกลุ่มเกินขีดจำกัด |
| 207 / 409 | SKU_BARCODE_DUPLICATESKU_BARCODE_CONFLICT | บาร์โค้ดสินค้าถูกใช้โดย SKU อื่นแล้ว หรือซ้ำกับบาร์โค้ดระบบหรือรหัสหยิบสินค้าของ SKU อื่น |
| 207 / 422 | GTIN_INVALIDHS_CODE_NOT_FOUND | เลขตรวจสอบของ GTIN ไม่ถูกต้อง หรือไม่มีพิกัดศุลกากรนี้ |
| 404 / 422 | SKU_NOT_FOUNDSKU_IMPORT_BLOCKED | ไม่พบ SKU หรือ SKU เป็นสินค้าห้ามนำเข้าจึงแจ้งล่วงหน้าไม่ได้ |
| 409 | INBOUND_REFERENCE_EXISTS | เลขอ้างอิงของใบรับเข้าคลังนี้มีอยู่แล้ว |
| 422 | TRACKING_IN_USETRACKING_FORECASTED_BY_OTHERTRACKING_ALREADY_WAREHOUSEDTRACKING_NOT_AVAILABLE | เลขพัสดุอยู่ในใบรับเข้าคลังที่กำลังดำเนินการแล้ว ถูกสมาชิกรายอื่นแจ้งล่วงหน้าไว้ หรือเข้าคลังในชื่อสมาชิกรายอื่นแล้ว |
| 409 | INBOUND_NOT_CANCELLABLE | มีพัสดุถึงคลังแล้ว จึงยกเลิกใบรับเข้าคลังไม่ได้ |
| 400 / 409 / 422 | IDEMPOTENCY_KEY_INVALIDIDEMPOTENCY_IN_PROGRESSIDEMPOTENCY_KEY_REUSED | Idempotency-Key มีรูปแบบไม่ถูกต้อง ถูกใช้กับเนื้อหาที่ต่างกัน หรือคำขอก่อนหน้ายังประมวลผลอยู่ |
| 409 | CONFLICT_RETRY | ข้อมูลเดียวกันกำลังถูกแก้ไขโดยคำขออื่น โปรดส่งใหม่ในภายหลัง |
| 429 | RATE_LIMIT_EXCEEDED | เกินขีดจำกัดอัตรา ให้รอตาม Retry-After แล้วลองใหม่ |
9 ตัวอย่างโค้ด
โปรดรันตัวอย่างต่อไปนี้ฝั่งเซิร์ฟเวอร์ และอย่าใส่คีย์ไว้ในโค้ดฝั่ง frontend
use Illuminate\Support\Facades\Http; use Illuminate\Support\Str; $api = Http::withToken(config('services.lucky.merchant_key')) ->acceptJson() ->baseUrl('https://0523.tw/api/v1/merchant') ->timeout(20); // 1) Sync SKUs (up to 200 per request) $res = $api->withHeaders(['Idempotency-Key' => (string) Str::uuid()]) ->post('/skus/batch', ['items' => $items]); foreach ($res->json('data') as $row) { if ($row['status'] === 'failed') { logger()->warning('SKU failed', $row['errors']); } } // 2) Forecast an inbound order $order = $api->withHeaders(['Idempotency-Key' => 'po-' . $po->id]) ->post('/inbound-orders', [ 'reference_no' => $po->number, 'packages' => [[ 'tracking_no' => $po->tracking_no, 'items' => [['seller_sku' => 'TEE-RED-S', 'qty' => 40]], ]], ])->throw()->json('data'); // 3) Read Shenzhen stock $stock = $api->get('/inventory', ['warehouse_code' => 'SZ'])->json('data');
// Node.js 18+ (server side only) import { randomUUID } from 'node:crypto'; const base = 'https://0523.tw/api/v1/merchant'; const headers = { Authorization: `Bearer ${process.env.LUCKY_MERCHANT_KEY}`, 'Content-Type': 'application/json', Accept: 'application/json', }; const res = await fetch(`${base}/skus/batch`, { method: 'POST', headers: { ...headers, 'Idempotency-Key': randomUUID() }, body: JSON.stringify({ items }), }); const { data, meta } = await res.json(); console.log(meta.summary); // { created, updated, failed } const stock = await fetch(`${base}/inventory?warehouse_code=SZ`, { headers }).then(r => r.json());
import os, uuid, requests base = "https://0523.tw/api/v1/merchant" session = requests.Session() session.headers.update({ "Authorization": f"Bearer {os.environ['LUCKY_MERCHANT_KEY']}", "Accept": "application/json", }) r = session.post(f"{base}/inbound-orders", headers={"Idempotency-Key": "po-20260917-0001"}, json={ "reference_no": "PO-20260917-0001", "packages": [{"tracking_no": "YT1234567890123", "items": [{"seller_sku": "TEE-RED-S", "qty": 40}]}], }, timeout=20) if r.status_code == 409: existing_id = r.json()["error"]["context"]["inbound_order_id"] else: r.raise_for_status()
10 การสนับสนุนทางเทคนิค
หากพบปัญหาระหว่างการเชื่อมต่อ โปรดแจ้งเวลาที่ส่งคำขอ endpoint และ error.code เพื่อให้เราช่วยตรวจสอบได้
บัญชีทางการ LINE @0523tw
อีเมลฝ่ายเทคนิค howyunqisoftware@gmail.com
เวอร์ชัน v1 ระยะที่ 1 (2026-09-17): SKU สินค้า การแจ้งรับเข้าคลังล่วงหน้า การติดบาร์โค้ดและขึ้นชั้นวางที่คลังเซินเจิ้น การค้นหาสต็อก webhook