ข้ามไปยังเนื้อหา

ข้อผิดพลาด

ทุกความล้มเหลวกลับมาเป็น JSON รูปแบบเดียวกันเสมอ ไม่ว่าจะผิดพลาดเรื่องอะไร รหัสสถานะ HTTP บอกประเภทของปัญหา ส่วนช่อง error บอกว่าเป็นตัวไหนแน่ชัด

{
"ok": false,
"error": "shop_not_in_scope",
"message": "this API key cannot access that shopId"
}
ช่อง มีเสมอไหม หมายเหตุ
ok มี เป็น false เสมอเมื่อผิดพลาด คำตอบที่สำเร็จจะเป็น "ok": true
error มี รหัสที่เครื่องอ่านได้และเสถียร ให้แตกสาขาที่ช่องนี้
message ในทางปฏิบัติมี ข้อความสำหรับคนอ่าน เป็นภาษาอังกฤษ แก้ถ้อยคำได้ตลอด
retryAfterSec เฉพาะ rate_limited จำนวนวินาทีที่ควรรอ คำตอบนั้นยังมี limit และ windowSec ด้วย
สถานะ หมายความว่า ควรลองใหม่ไหม
200 สำเร็จ ผลลัพธ์ที่ data เป็นอาเรย์ว่างก็ยังนับว่าสำเร็จ —
400 คำขอผิดรูป ขาดพารามิเตอร์ ส่งพารามิเตอร์ที่ขัดกันเอง หรือ cursor ตายแล้ว ไม่ ให้แก้คำขอ
401 ไม่มีกุญแจ กุญแจผิด หรือกุญแจถูกยกเลิก ไม่ ให้แก้กุญแจ
403 กุญแจถูกต้อง แต่ร้านหรือแบรนด์สมาชิกที่ขออยู่นอกขอบเขต หรือเส้นนั้นต้องใช้สิทธิ์รายกุญแจที่กุญแจใบนี้ยังไม่ได้รับ ไม่ ให้ขอรหัสที่กุญแจอ่านได้ หรือขอเปิดสิทธิ์
404 ไม่มีบิลหรือสมาชิกนั้น หรือ อยู่นอกขอบเขตของคุณ ไม่
429 ยิงถี่เกินไปในนาทีนี้ หรือโควตารายวันหมด ควร แต่ต้องรอก่อน
500 มีบางอย่างล้มเหลวฝั่งเรา ควร แบบถอยเวลาเพิ่มขึ้น
503 ระบบตรวจกุญแจไม่พร้อมชั่วคราวฝั่งเรา ควร แบบถอยเวลาเพิ่มขึ้น

สังเกตความต่างระหว่าง 403 กับ 404 ซึ่งตั้งใจให้ต่างกัน เส้นแบบลิสต์ตอบ 403 เพราะ shopId หรือ providerId ที่ส่งมาเป็นค่าที่คุณรู้อยู่แล้ว ส่วนเส้นที่ขอรายการเดียว ตอบ 404 ทั้งกรณี “ไม่มีบิลนี้” และ “บิลนี้อยู่ในร้านที่คุณอ่านไม่ได้” เพื่อไม่ให้คำตอบยืนยันว่ารหัสนั้นมีอยู่ที่อื่นใน ScanFood หรือไม่

สถานะ error เกิดเมื่อ
400 bad_query shopId is required เส้นลิสต์บิลต้องมีร้าน
400 bad_query providerId is required เส้นลิสต์สมาชิกต้องมีแบรนด์
400 bad_query choose exactly one mode: from+to (calendar days) or updatedSince (ISO-8601) ส่งมาทั้งสองโหมด หรือไม่ส่งเลย
400 bad_query updatedSince must be an ISO-8601 datetime วันนี้ตัวตรวจยังหลวม รูปแบบนอกมาตรฐานอย่าง 2026/09/01 จึงอาจผ่านไปได้ แต่ให้ส่งเป็น ISO-8601 จริงเสมอ เพราะนั่นคือรูปแบบที่เรารองรับ
400 bad_query from/to must be YYYYMMDD ฝั่งคำขอไม่มีขีด
400 bad_query from must be <= to
400 bad_query range too wide: N days (max 31)
400 bad_query id is required ไม่มีรหัสบิลในเส้นทาง
400 bad_query เรียกเส้นค้นสมาชิกโดยไม่ส่ง providerId หรือส่ง lineUserId ที่ไม่ได้อยู่ในรูป U ตามด้วยเลขฐานสิบหก 32 ตัว
400 bad_cursor cursor no longer exists แถวที่ cursor ชี้อยู่หายไปแล้ว
400 bad_cursor cursor is not a valid member token ส่งค่าที่ไม่ใช่ token รูป m1_…
400 not_supported ส่ง updatedSince ที่เส้นลิสต์สมาชิก การซิงก์เฉพาะส่วนที่เปลี่ยนของสมาชิกยังไม่เปิด ให้ไล่หน้าด้วย cursor แทน
401 invalid_key Invalid API key ไม่มีกุญแจ ผิดรูป ไม่มีอยู่จริง หรือรหัสลับผิด ทั้งสี่แบบตอบเหมือนกัน
401 key_revoked API key has been revoked
403 shop_not_in_scope this API key cannot access that shopId
403 provider_not_in_scope this API key cannot access that providerId
403 lookup_not_enabled กุญแจใบนี้ยังไม่ได้เปิดสิทธิ์ค้นสมาชิก สิทธิ์นี้ให้เป็นรายกุญแจเหมือน tel และ email ดูที่ สมาชิก
404 not_found transaction not found รหัสไม่มีอยู่ หรือเป็นบิลของร้านนอกขอบเขต
404 not_found member not found token ไม่ถูกต้อง ไม่มีสมาชิกนั้น หรือแบรนด์อยู่นอกขอบเขต
404 not_found ค้นด้วย LINE user id แล้วไม่พบสมาชิกที่ตรงกัน คำตอบเดียวสำหรับสามกรณี ไม่ได้เป็นสมาชิกของแบรนด์นี้ เป็นสมาชิกของแบรนด์อื่น หรือไม่มีตัวตนเลย
429 rate_limited Too many requests, retry in about N seconds ยิงเกินขีดจำกัดต่อนาที ใน body มี retryAfterSec limit windowSec และส่วนหัว Retry-After บอกค่าเดียวกัน
429 quota_exceeded daily quota exceeded (N requests/day, Thailand time). Resets at 00:00 ICT.
500 internal temporary failure, please retry เป็นฝั่งเรา
503 auth_unavailable Authentication service temporarily unavailable, retry later ระบบตรวจกุญแจไม่พร้อมชั่วคราว เราตอบ 503 แทน 401 เพื่อไม่ให้คุณเสียเวลาไปไล่ตรวจกุญแจที่ไม่ได้มีปัญหาอะไรเลย

ทุกเส้นเป็น GET ที่ไม่เปลี่ยนข้อมูลของร้าน การลองใหม่จึงไม่มีทางทำให้บิลซ้ำ หรือทำอะไรซ้ำซ้อนได้ ร่องรอยที่การยิงซ้ำทิ้งไว้คือตัวนับโควตาเพิ่มขึ้นหนึ่ง และอีกหนึ่งแถวในสมุดคำขอของเรา ซึ่งเก็บไว้ 90 วัน

นโยบายลองใหม่ที่ใช้ได้จริง

สถานการณ์ นโยบาย
429 rate_limited รอตาม Retry-After วินาที แล้วลองใหม่ อย่าลดเวลารอ
429 quota_exceeded หยุดจนถึง 00:00 น. เวลาไทย หรือขอเพิ่มโควตา ลองใหม่เร็วกว่านั้นคือเผาคำขอทิ้งเปล่า ๆ
500 503 การเชื่อมต่อหลุด หมดเวลา ถอยเวลาเพิ่มขึ้นแบบมีการสุ่ม เช่น 1 วิ 2 วิ 4 วิ 8 วิ ไม่เกินห้าครั้ง
400 401 403 404 อย่าลองใหม่ คำขอเดิมยิงอีกกี่ครั้งก็ไม่สำเร็จ

อีกสองนิสัยที่ควรมี

  • เขียน log รหัส error สถานะ และพารามิเตอร์ของคำขอ แต่อย่าเขียนกุญแจลงไป รหัสกุญแจ 12 ตัวเขียนได้ ส่วนรหัสลับเขียนไม่ได้
  • ถือว่า cursor ตายคือการเริ่มหน้านั้นใหม่ ไม่ใช่ความล้มเหลว bad_cursor แปลว่าแถวที่ cursor ชี้อยู่หายไปแล้ว ให้ทิ้ง cursor แล้วขอหน้านั้นใหม่ตั้งแต่ต้นช่วง ดู การแบ่งหน้าและการซิงก์