ผู้ติดต่อ
ลูกค้าและผู้ขาย — รหัสที่เอกสารขายและเอกสารซื้อทุกฉบับต้องใช้
ผู้ติดต่อคือลูกค้า ผู้ขาย หรือทั้งสองอย่าง เอกสารขายอ้างอิงผู้ติดต่อผ่าน contactId เอกสารซื้อก็เช่นกัน โดยทั่วไปนี่คือข้อมูลชุดแรกที่ระบบเชื่อมต่อจะต้องซิงก์
กลุ่มนี้มีสองเรื่องที่ต่างจากส่วนอื่นของ API
- การอ่านคืน object ตรง ๆ ไม่ห่อด้วย
data - การเขียนใช้
multipart/form-dataไม่ใช่ JSON เพราะ endpoint นี้เดิมออกแบบมาให้อัปโหลดไฟล์ในเว็บแอป ABSERP ได้ สัญญาของฟอร์มใน Open API จึงเป็นแบบเดียวกัน แต่ตัว Open API เองไม่เปิดให้อัปโหลดไฟล์เหล่านั้น (ดูด้านล่าง) หากต้องการตั้งรูปประจำตัวให้ใช้avatarUrlแทน
สามเส้นทางเข้าถึงข้อมูลชุดเดียวกัน
| กลุ่ม | พฤติกรรมของการค้นหาและสร้าง |
|---|---|
/contacts | ทั้งหมด กำหนด contactType ได้เอง |
/customers | บังคับ contactType: "client" ทั้งการค้นหาและการสร้าง — ตอนสร้างไม่ต้องส่ง contactType เอง ค่าที่ส่งมาจะถูกละเลย |
/vendors | บังคับ contactType: "supplier" ทั้งการค้นหาและการสร้าง — ตอนสร้างไม่ต้องส่ง contactType เอง ค่าที่ส่งมาจะถูกละเลย |
การดำเนินการกับ {id} ใช้ร่วมกัน GET /customers/9 และ GET /contacts/9 คืนแถวเดียวกัน ควรใช้เส้นทางย่อเมื่อโค้ดส่วนนั้นทำงานกับด้านเดียวอยู่แล้ว เพราะช่วยตัดตัวกรองที่ต้องจำออกไปหนึ่งตัว
ค้นหาผู้ติดต่อ
GET /contacts → แบ่งหน้า คืน ตรง ๆ
| พารามิเตอร์ | หมายเหตุ |
|---|---|
search | ค้นจากรหัส ชื่อ เลขผู้เสียภาษี อีเมล และเบอร์โทร |
contactType | client, supplier หรือ both |
isActive | true / false |
isDeleted | true เพื่อดูแถวที่ลบแบบ soft delete |
page / limit | ดูการแบ่งหน้า |
ชื่อพารามิเตอร์คือ contactType ไม่ใช่ type
curl -X GET "$ABSERP_API_URL/openapi/v1/contacts?contactType=client&isActive=true&limit=100" \
-H "Authorization: Bearer $ABSERP_API_KEY"{
"items": [
{
"id": 12,
"code": "CUST-001",
"name": "บริษัท เอซีเอ็มอี จำกัด",
"businessType": "corporation",
"taxId": "0105551234567",
"branchType": "head_office",
"branchCode": "00000",
"contactType": "client",
"contactName": "สมชาย ใจดี",
"email": "[email protected]",
"phone": "021234567",
"address": "…",
"creditDays": 30,
"creditLimit": 100000,
"paymentTermDays": 30,
"currency": "THB",
"bank": null,
"isActive": true,
"createdAt": 1735689600
}
],
"pagination": {
"previousPage": null,
"currentPage": 1,
"nextPage": null,
"totalPages": 1,
"totalRows": 1
}
}ค้นหาผู้ติดต่อที่คุณมีข้อมูลอยู่แล้ว
ไม่มี endpoint แบบ "ค้นด้วยเลขผู้เสียภาษี" หากต้องการจับคู่ลูกค้าที่มีอยู่ในระบบของคุณ ให้ค้นด้วยค่าที่คุณเชื่อถือมากที่สุดแล้วตรวจผลลัพธ์
curl -X GET "$ABSERP_API_URL/openapi/v1/contacts?search=0105551234567&contactType=client" \
-H "Authorization: Bearer $ABSERP_API_KEY"จากนั้นเก็บ id ที่ได้ผูกกับข้อมูลฝั่งคุณ การค้นครั้งเดียวแล้วเก็บ id ไว้ประหยัดกว่าการค้นก่อนสร้างเอกสารทุกครั้งมาก และช่วยกันการสร้างข้อมูลซ้ำเมื่อชื่อสะกดต่างกันเล็กน้อย
สร้างผู้ติดต่อ
POST /contacts → 201 คืนผู้ติดต่อที่สร้างแล้ว ตรง ๆ โครงสร้างเดียวกับ GET /contacts/{id} (id, code, name, contactType, businessType, taxId, email, phone, creditDays, creditLimit, paymentTermDays, currency, isActive, createdAt, …)
เก็บ id จาก response นี้ไว้ใช้ต่อได้ทันที ไม่ต้องเรียกรายการพร้อม search เพื่อหา id ซ้ำอีก
body เป็น multipart/form-data ฟิลด์ที่จำเป็นคือ name และ contactType
curl -X POST "$ABSERP_API_URL/openapi/v1/contacts" \
-H "Authorization: Bearer $ABSERP_API_KEY" \
-F "name=บริษัท เอซีเอ็มอี จำกัด" \
-F "contactType=client" \
-F "businessType=corporation" \
-F "taxId=0105551234567" \
-F "branchType=head_office" \
-F "branchCode=00000" \
-F "contactName=สมชาย ใจดี" \
-F "[email protected]" \
-F "phone=021234567" \
-F "creditDays=30" \
-F "currency=THB"การส่ง endpoint นี้เป็น JSON เป็นความผิดพลาดที่พบมากที่สุด เพราะ request จะผ่านเข้าไปได้ แต่ทุกฟิลด์จะว่าง และคุณจะได้ข้อผิดพลาดว่า name จำเป็น
ฟิลด์
| ฟิลด์ | จำเป็น | หมายเหตุ |
|---|---|---|
name | ใช่ | ไม่เกิน 255 ตัวอักษร |
contactType | ใช่ เฉพาะ /contacts | client, supplier หรือ both — สร้างผ่าน /customers หรือ /vendors ไม่ต้องส่งฟิลด์นี้ ระบบตั้งค่าให้เองและไม่สนใจค่าที่ส่งมา |
businessType | ไม่ | corporation หรือ individual |
taxId | ไม่ | ไม่เกิน 20 ตัวอักษร |
branchType | ไม่ | head_office หรือ branch |
branchCode | ไม่ | ไม่เกิน 10 ตัวอักษร เช่น 00000 สำหรับสำนักงานใหญ่ |
branchName | ไม่ | ไม่เกิน 100 ตัวอักษร |
contactName | ไม่ | ชื่อผู้ที่ติดต่อได้ |
email, phone, website | ไม่ | phone ไม่เกิน 30 ตัวอักษร |
telegram, lineId, whatsappId, discordId | ไม่ | บัญชีแอปแชท |
address | ไม่ | ที่อยู่สำหรับออกเอกสาร |
shippingInfo | ไม่ | ที่อยู่จัดส่ง |
creditDays | ไม่ | จำนวนเต็ม |
creditLimit | ไม่ | ต้องเป็น 0 หรือมากกว่า |
paymentTermDays | ไม่ | จำนวนเต็ม |
currency | ไม่ | 3 ตัวอักษรพอดี |
remark | ไม่ | หมายเหตุภายใน |
avatarUrl | ไม่ | URL รูปประจำตัวของผู้ติดต่อ |
การ อัปโหลดไฟล์ รูปประจำตัวและรูป QR บัญชีธนาคารไม่ได้เป็นส่วนหนึ่งของ API นี้ ตั้งค่าได้จากเว็บแอป ABSERP เท่านั้น หากต้องการตั้งรูปประจำตัวจากระบบที่เชื่อมต่อ ให้ส่ง avatarUrl แทน
ข้อมูลธนาคารส่งในฟอร์มเดียวกัน ได้แก่ bankCompany, accountNo, accountName, accountType, accountBranch, accountBranchCode, swiftCode (ไม่เกิน 11) และ bankAddress เวลาอ่านจะคืนซ้อนอยู่ใต้คีย์ bank
code (CUST-001, VD-001) ระบบ ABSERP กำหนดให้ ตั้งเองไม่ได้
อ่านผู้ติดต่อรายรายการ
GET /contacts/{id} → คืนผู้ติดต่อ ตรง ๆ
GET /contacts/{id}/credit-usageไม่เปิดให้ใช้ผ่าน Open API (ใช้ได้ในเว็บแอปเท่านั้น) ค่าcreditLimitและcreditDaysอยู่บนตัวผู้ติดต่ออยู่แล้ว หากขั้นตอนงานของคุณต้องคุมวงเงินเครดิต ให้คำนวณยอดที่ใช้ไปจากใบแจ้งหนี้ที่ดึงผ่านGET /sales/documentsเพราะ endpoint เอกสารขายจะไม่ตรวจให้
แก้ไขผู้ติดต่อ
PATCH /contacts/{id} → { "success": true, "message": "…" }
ฟิลด์เหมือนตอนสร้างทั้งหมดแต่ไม่บังคับ และเพิ่ม isActive เข้ามา ใช้ multipart/form-data เช่นเดียวกัน
ส่งเฉพาะฟิลด์ที่เปลี่ยน ฟิลด์ที่ไม่ส่งจะคงค่าเดิม ฟิลด์ที่ส่งเป็นค่าว่างจะถูกล้าง
ลบและกู้คืน
DELETE /contacts/{id} ลบแบบ soft delete เอกสารที่อ้างอิงผู้ติดต่ออยู่แล้วยังทำงานได้ตามปกติ ซึ่งเป็นเหตุผลที่การลบเป็นแบบ soft delete และการดึงรายการด้วย isDeleted=true ยังเห็นแถวนั้นอยู่
การกู้คืน (
PATCH /contacts/{id}/restore) ไม่เปิดให้ใช้ผ่าน Open API (ใช้ได้ในเว็บแอปเท่านั้น) ผู้ติดต่อที่ลบแล้วต้องกู้คืนจากใน ABSERP
โดยทั่วไปการปิดใช้งาน (isActive: false) เหมาะกว่าอยู่แล้ว เพราะผู้ติดต่อจะไม่ปรากฏในตัวเลือกอีก ข้อมูลยังอยู่ครบ และเปิดใช้งานกลับได้ผ่าน PATCH /contacts/{id}
รหัสข้อผิดพลาด
| สถานะ | รหัส | สาเหตุ |
|---|---|---|
| 400 | BadRequest | ขาด name/contactType หรือค่า enum ไม่ถูกต้อง (businessType, branchType, contactType, currency ที่ไม่ใช่ 3 ตัวอักษรพอดี) ตอนสร้างหรือแก้ไข |
| 404 | NotFound | ไม่พบ :id ในองค์กรนี้ |
ไม่มีรหัสข้อมูลซ้ำ/ขัดแย้งโดยเฉพาะสำหรับผู้ติดต่อ taxId, phone หรือ email ที่ตรงกับผู้ติดต่อที่มีอยู่แล้วระบบจะรับไว้ ไม่ปฏิเสธ ส่วน code (CUST-001) ระบบ ABSERP กำหนดให้เองจึงชนกันไม่ได้
FileSizeExceeded และ FileTypeError มีอยู่ใน endpoint ต้นทางสำหรับการอัปโหลดรูปประจำตัวและรูป QR บัญชีธนาคาร แต่ฟิลด์เหล่านั้นไม่ได้เป็นส่วนหนึ่งของสัญญา Open API ที่เอกสารนี้ระบุ (ดู "ฟิลด์" ด้านบน) หากส่ง avatarUrl ตามที่เอกสารนี้แนะนำ คุณจะไม่พบรหัสทั้งสองนี้
ขั้นตอนถัดไป
อ่านต่อที่ สินค้าและคลังสินค้า