เอกสาร API — ส่งชัวร์ (REST API v1)
API สำหรับตรวจสอบความเสี่ยงการจัดส่ง COD และรายงานผลการจัดส่ง สำหรับร้านค้าสมาชิกระดับ API ที่ผ่านการยืนยันตัวตน (KYC) แล้วเท่านั้น
Base URL (ระหว่างพัฒนา): http://localhost:3000
> 💡 OpenAPI 3.0 Spec: สามารถดาวน์โหลดข้อกำหนด API ฉบับเต็มในรูปแบบ OpenAPI 3.0 / Swagger / Postman ได้ที่ [/api/openapi.json](file:///api/openapi.json) (หรือ URL https://www.sendsures.com/api/openapi.json)
การยืนยันตัวตน (Authentication)
สร้าง API key ได้จากหน้า ตั้งค่า → API keys ในคอนโซลร้านค้า ระบบแสดงคีย์เพียงครั้งเดียวตอนสร้าง — โปรดเก็บไว้ในที่ปลอดภัย
ส่งคีย์ผ่านเฮดเดอร์ Authorization ในทุกคำขอ:
Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX- คีย์มีขอบเขตสิทธิ์ (scopes):
checkสำหรับตรวจสอบเบอร์ และreportสำหรับส่งรายงาน - คีย์แต่ละอันมีเพดานการเรียกต่อนาที (
rate_limit_per_min, ค่าเริ่มต้น 60) - บัญชีร้านค้าต้องมีสถานะ KYC = approved จึงจะเรียกใช้งานได้
รหัสข้อผิดพลาด (Error codes)
เมื่อเกิดข้อผิดพลาด ระบบตอบกลับในรูปแบบเดียวกันทุกจุด:
{
"error": {
"code": "RATE_LIMITED",
"message_th": "มีการเรียกใช้งานถี่เกินไป กรุณาลองใหม่ภายหลัง",
"message_en": "Rate limit exceeded"
}
}| code | HTTP | ความหมาย | |---|---|---| | PHONE_REQUIRED | 400 | ไม่ได้ระบุหมายเลขโทรศัพท์ (จำเป็นทุกครั้ง) | | INVALID_TH_PHONE | 400 | รูปแบบหมายเลขโทรศัพท์ไทยไม่ถูกต้อง | | UNAUTHORIZED | 401 | ไม่มีสิทธิ์ / API key ไม่ถูกต้องหรือถูกยกเลิก | | KYC_REQUIRED | 403 | บัญชีร้านค้ายังไม่ผ่านการยืนยันตัวตน (KYC) | | RATE_LIMITED | 429 | เรียกใช้งานเกินเพดานที่กำหนด | | INSUFFICIENT_CREDITS | 402 | เครดิตไม่เพียงพอสำหรับการตรวจสอบ | | DUPLICATE_TRACKING | 409 | หมายเลขพัสดุนี้ถูกรายงานไปแล้วโดยร้านของคุณ | | NOT_FOUND | 404 | ไม่พบข้อมูลที่ต้องการ | | VALIDATION_ERROR | 400 | ข้อมูลที่ส่งมาไม่ผ่านการตรวจสอบรูปแบบ | | INTERNAL | 500 | ข้อผิดพลาดภายในระบบ |
POST /api/v1/check — ตรวจสอบความเสี่ยงเบอร์โทรศัพท์
ต้องใช้ scope check — ตรวจสอบได้ทีละหนึ่งเบอร์ต่อคำขอ โดย phone เป็นคีย์ค้นหาเพียงอย่างเดียว ส่วน name และ address เป็นข้อมูลประกอบ (ไม่บังคับ) ใช้ปรับระดับความเชื่อมั่นหรือเพิ่มสัญญาณที่อยู่เท่านั้น
คำขอ:
{
"phone": "0891234567",
"name": "สมชาย ใจดี",
"address": "99/12 ม.4 ต.บางรักน้อย อ.เมือง จ.นนทบุรี",
"ref": "ORDER-1234"
}ตัวอย่าง curl:
curl -X POST http://localhost:3000/api/v1/check \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{"phone":"0891234567","name":"สมชาย ใจดี","ref":"ORDER-1234"}'ผลลัพธ์ 200:
{
"phone_masked": "08X-XXX-4567",
"score": 67,
"band": "ORANGE",
"confidence": "HIGH",
"recommended_action": "REQUEST_DEPOSIT_OR_TRANSFER",
"stats": {
"no_data": false,
"verified_rejections_6m": 3,
"verified_rejections_24m": 3,
"distinct_merchants": 3,
"total_value_thb": 4150,
"successful_deliveries_12m": 0,
"last_event_month": "2026-05"
},
"name_match": "match",
"address_signal": { "has_history": false, "verified_events": 0 },
"notes": [],
"disclaimer": "ข้อมูลนี้เป็นสถิติจากรายงานของร้านค้าสมาชิก...",
"checked_at": "2026-07-26T04:00:00Z"
}คำอธิบายฟิลด์สำคัญ:
band— ระดับความเสี่ยง:GREEN(0–30),YELLOW(31–60),ORANGE(61–80),RED(81–100)recommended_action—PROCEED_COD|CONFIRM_BEFORE_PACK|REQUEST_DEPOSIT_OR_TRANSFER|PREPAID_ONLYconfidence—LOW|MEDIUM|HIGHตามจำนวนเหตุการณ์ที่ตรวจสอบแล้วใน 12 เดือนname_match—match|mismatch|no_name_history| null (ระบบไม่เปิดเผยชื่อที่บันทึกไว้)notes— อาจมี"POSSIBLE_NUMBER_RECYCLED"เมื่อชื่อผู้รับไม่ตรงกับประวัติเดิม (เบอร์อาจเปลี่ยนเจ้าของ)stats.no_data: true— เบอร์นี้ยังไม่มีประวัติในระบบ (จัดเป็นความเสี่ยงต่ำ ข้อมูลน้อย)
POST /api/v1/reports — ส่งรายงานผลการจัดส่ง
ต้องใช้ scope report — ทุกรายงานต้องมีหมายเลขพัสดุ (tracking number) และจะถูกตรวจสอบกับข้อมูลผู้ให้บริการขนส่งก่อนมีผลต่อคะแนนเสมอ รายงานที่ยังไม่ผ่านการตรวจสอบไม่ถูกนำไปคำนวณ
ประเภทรายงาน (type):
| type | ความหมาย | |---|---| | cod_rejected | ผู้รับปฏิเสธรับพัสดุ / พัสดุตีกลับ | | cancelled_after_ship | ยกเลิกออเดอร์หลังจัดส่งแล้ว | | return_abuse | การคืนสินค้าที่ผิดปกติ | | successful_delivery | เหตุการณ์เชิงบวก: รับพัสดุและชำระ COD สำเร็จ |
คำขอ:
{
"type": "cod_rejected",
"phone": "0891234567",
"tracking_no": "MOCKR123456",
"carrier": "flash",
"order_value_thb": 1290,
"order_date": "2026-07-10",
"customer_name": "สมชาย ใจดี",
"address": "99/12 ม.4 ต.บางรักน้อย อ.เมือง จ.นนทบุรี"
}ตัวอย่าง curl:
curl -X POST http://localhost:3000/api/v1/reports \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{"type":"cod_rejected","phone":"0891234567","tracking_no":"MOCKR123456","carrier":"flash","order_value_thb":1290,"order_date":"2026-07-10"}'ผลลัพธ์ 201:
{ "id": "8b6f8a1e-1234-4cde-9abc-1234567890ab", "verification_status": "pending" }- รายงานซ้ำ (ร้านเดิม + tracking เดิม) → 409
DUPLICATE_TRACKING - เมื่อรายงานเชิงลบผ่านการตรวจสอบ ร้านผู้รายงานได้รับ +2 เครดิต (เชิงบวก +1 สูงสุด +10/วัน)
carrierระบุได้:flash|jt|kerry|thaipost|ninja|otherหรือเว้นว่างให้ระบบตรวจจับอัตโนมัติ
GET /api/v1/reports — รายการรายงานของร้านคุณ
ดูเฉพาะรายงานของร้านตัวเองเท่านั้น (ไม่มีการเข้าถึงข้อมูลร้านอื่น)
พารามิเตอร์: status (pending | verified | unverifiable | contradicted | disputed | removed), limit (ค่าเริ่มต้น 50), cursor (ค่า next_cursor จากหน้าก่อนหน้า รูปแบบ <ISO datetime>|<uuid>)
curl "http://localhost:3000/api/v1/reports?status=verified&limit=20" \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"DELETE /api/v1/reports/:id — ถอนรายงาน
ถอนได้เฉพาะรายงานของร้านตัวเองที่ยังมีสถานะ pending เท่านั้น
curl -X DELETE http://localhost:3000/api/v1/reports/8b6f8a1e-1234-4cde-9abc-1234567890ab \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"GET /api/v1/me — ข้อมูลบัญชีร้านค้า
โปรไฟล์ร้าน ระดับการใช้งาน (tier) ยอดเครดิตคงเหลือ และการใช้งานวันนี้
curl http://localhost:3000/api/v1/me \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"POST /api/v1/bulk-check — ตรวจสอบหลายเบอร์ในคำขอเดียว
ส่งรายการได้สูงสุด 2,000 รายการต่อคำขอ ประมวลผลแบบ synchronous แต่ละรายการนับเป็นหนึ่งการตรวจสอบตามเพดานการใช้งานปกติ ผลลัพธ์เป็นอาร์เรย์ของผลตรวจ (หรือ error รายแถว)
curl -X POST http://localhost:3000/api/v1/bulk-check \
-H "Authorization: Bearer ss_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{"items":[{"phone":"0891234567","ref":"A-1"},{"phone":"0612345678","ref":"A-2"}]}'POST /api/ingest/feed — รับข้อมูลจากคู่ค้าอัตโนมัติ
ปลายทางสำหรับพันธมิตร push ข้อมูลเข้าระบบ ใช้ Authorization: Bearer ss_feed_... (Feed token สร้างจากหน้า "นำเข้าข้อมูลจัดส่ง" สำหรับคลังสินค้า/OMS หรือผู้ดูแลระบบสร้างให้พันธมิตรขนส่ง) ส่งได้สูงสุด 500 รายการต่อครั้ง, 60 ครั้ง/นาที
Feed แบบร้านค้า (คลังสินค้า / Fulfillment / OMS) — แต่ละรายการกลายเป็นรายงานของร้าน (สถานะรอตรวจสอบ เข้าคิวยืนยันกับขนส่งตามปกติ):
curl -X POST http://localhost:3000/api/ingest/feed \
-H "Authorization: Bearer ss_feed_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"status": "ปฏิเสธรับ",
"phone": "0891234567",
"tracking_no": "TH0123456789012",
"carrier": "flash",
"order_value_thb": 1290,
"order_date": "2026-07-10"
}
]
}'ค่า status รองรับทั้งไทย/อังกฤษ: จัดส่งสำเร็จ|delivered, ปฏิเสธรับ|refused|returned|rts, ยกเลิกหลังส่ง|cancelled, ตีกลับโดยมิชอบ|return_abuse
Feed แบบขนส่ง (Flash / ไปรษณีย์ไทย / J&T / อื่น ๆ — ผู้ดูแลระบบสร้างให้) — ส่งเฉพาะเลขพัสดุ + สถานะ (ไม่มีข้อมูลส่วนบุคคล) ระบบเก็บเป็นหลักฐานให้เครื่องยืนยันรายงาน ใช้แทนการเรียก API ขนส่ง:
curl -X POST http://localhost:3000/api/ingest/feed \
-H "Authorization: Bearer ss_feed_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "tracking_no": "TH0123456789012", "status": "5", "occurred_at": "2026-07-27T09:00:00+07:00" }
]
}'ผลลัพธ์ทั้งสองแบบ: { "total": n, "inserted": n, "duplicates": n, "invalid": n, "errors": [...] }
นำเข้าไฟล์ Excel/CSV — หน้า /app/import รองรับไฟล์ .xlsx/.csv สูงสุด 2,000 แถว (หัวตารางไทยหรืออังกฤษ: สถานะ/status, เบอร์โทร/phone, เลขพัสดุ/tracking_no, ขนส่ง/carrier, มูลค่า/order_value_thb, วันที่/order_date, ชื่อผู้รับ/customer_name, ที่อยู่/address) พร้อมไฟล์ต้นแบบให้ดาวน์โหลดในหน้าเดียวกัน
Webhooks — เหตุการณ์ score.changed
เมื่อระดับความเสี่ยง (band) ของเบอร์ที่ร้านคุณเคยตรวจสอบหรือรายงานภายใน 90 วันมีการเปลี่ยนแปลง ระบบส่ง POST ไปยัง endpoint ที่ตั้งค่าไว้ (หน้า ตั้งค่า → Webhooks):
{
"event": "score.changed",
"phone_masked": "08X-XXX-4567",
"old_band": "YELLOW",
"new_band": "ORANGE",
"occurred_at": "2026-07-26T04:00:00Z"
}- ส่งซ้ำสูงสุด 3 ครั้งแบบ backoff เมื่อปลายทางตอบไม่สำเร็จ
- payload เป็นข้อมูลปกปิดเท่านั้น — ไม่มีเบอร์เต็ม ชื่อ หรือข้อมูลร้านอื่น
การตรวจสอบลายเซ็น: ทุกคำขอมีเฮดเดอร์ X-SongSure-Signature เป็นค่า hex ของ HMAC-SHA256 ของ raw body ด้วย secret ของ endpoint คุณ
// Node.js — ตรวจสอบลายเซ็น webhook
import { createHmac, timingSafeEqual } from "node:crypto";
function verifySongSureSignature(rawBody, signatureHeader, secret) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
return timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}เพดานการใช้งาน (Rate limits)
| ระดับ | ตรวจสอบ/วัน | burst/นาที | |---|---|---| | free | 20 (จากนั้นหัก 1 เครดิต/ครั้ง) | 10 | | pro | 2,000 | 60 | | api | ตามโควตารายเดือนของร้านค้า (`monthly_quota`) | ตาม rate_limit_per_min ของคีย์ |
เมื่อเกินเพดาน ระบบตอบ HTTP 429 พร้อม code RATE_LIMITED
ข้อจำกัดการใช้ข้อมูล: ข้อมูลนี้เป็นสถิติจากรายงานของร้านค้าสมาชิกซึ่งผ่านการตรวจสอบกับผู้ให้บริการขนส่ง ใช้เพื่อประกอบการประเมินความเสี่ยงในการจัดส่งเท่านั้น ไม่ใช่การยืนยันว่าบุคคลใดกระทำความผิด เจ้าของหมายเลขสามารถตรวจสอบและโต้แย้งข้อมูลได้ที่หน้า "ตรวจสอบข้อมูลของฉัน"