Khách hàng
Tổng quan
| Method + path | Scope | Dùng để |
|---|---|---|
GET /customers | customers_list | Liệt kê để đồng bộ (keyset), hoặc tra một khách theo matchField |
GET /customers/:id | customers_detail | Lấy một khách theo id |
POST /customers | customers_create + customers_update | Tạo hoặc cập nhật (upsert) |
PATCH /customers/:id/fields | customers_update | Ghi trường tuỳ chỉnh |
GET /customer-properties | customers_list | Trạng thái, nguồn, nhóm, ngành, nền tảng của khách |
GET /custom-fields | custom_field_list | Định nghĩa trường của khách hàng |
Key chỉ thấy những khách mà người tạo key được thấy (theo phạm vi phân quyền của họ). Đường dẫn bên dưới tính từ /api/open/v1 — xem Tổng quan.
Đối tượng khách hàng
{
"id": "1f0c6a7e-5d1b-4a8e-9a63-2c1f0f6b9d10",
"customerCode": "KH-001",
"fullName": "Nguyễn Thị Lan",
"phoneNumber": "84901234567",
"email": "lan@example.com",
"address": "12 Lý Thường Kiệt, Hà Nội",
"companyName": null,
"notes": null,
"gender": "female",
"dateOfBirth": "1995-04-12",
"status": { "id": 3, "name": "Đang chăm sóc" },
"assignedStaffId": "7a2d…",
"customFields": { "ma_erp": "ERP-778", "hang_thanh_vien": "vang" },
"lastModifiedSource": "api:ERP Kho",
"createdAt": "2026-10-01T02:15:00.000Z",
"updatedAt": "2026-10-08T03:12:45.123Z"
}
Liệt kê khách hàng
GET /api/open/v1/customers?updatedSince=2026-10-01T00:00:00Z&updatedUntil=2026-10-08T00:00:00Z&limit=50&excludeSource=api:ERP%20Kho
Trả { "data": [khách hàng…], "nextCursor": "…" | null, "window": {…} } — tối đa 50 khách mỗi lần, cửa sổ tối đa 30 ngày. Tham số: xem Phân trang keyset.
Tra một khách
GET /api/open/v1/customers?matchField=phone&value=0901234567
GET /api/open/v1/customers/1f0c6a7e-5d1b-4a8e-9a63-2c1f0f6b9d10
matchField là phone, email, customerCode, hoặc mã một trường tuỳ chỉnh kiểu văn bản có bật "duy nhất". Trả { "data": khách hàng }, hoặc { "data": null } khi không có. Khớp nhiều hơn một ⇒ 409 OPEN_API_MATCH_AMBIGUOUS.
Tạo hoặc cập nhật (upsert)
POST /api/open/v1/customers
- Request Body
- Response
{
"matchBy": ["customerCode", { "field": "ma_erp" }, "phone"],
"customerCode": "KH-001",
"fullName": "Nguyễn Thị Lan",
"phoneNumber": "0901234567",
"email": "lan@example.com",
"gender": "female",
"dateOfBirth": "1995-04-12",
"statusId": 3,
"customFields": { "ma_erp": "ERP-778", "hang_thanh_vien": "vang" }
}
{
"data": { "id": "1f0c6a7e-…", "customerCode": "KH-001", "fullName": "Nguyễn Thị Lan", "…": "…" },
"created": false
}
201 khi tạo mới, 200 khi cập nhật.
| Trường | Kiểu | Ghi chú |
|---|---|---|
matchBy | mảng (≤ 5) | Thứ tự tiêu chí tìm khách có sẵn: "customerCode", "phone", "email", hoặc { "field": "<mã trường duy nhất>" } |
customerCode | chuỗi ≤ 50 | Mã khách tự đặt, duy nhất trong cửa hàng. Vắng khi tạo ⇒ tự sinh |
fullName, phoneNumber, email, address, companyName, notes | chuỗi | Trường mặc định |
gender | male / female / other | |
dateOfBirth | YYYY-MM-DD | |
statusId | số | Id trạng thái khách — GET /customer-properties |
leadSourceId, leadGroupId, leadIndustryId, leadPlatformId | số | Id nguồn / nhóm / ngành / nền tảng — cùng danh mục trên |
customFields | object | Theo mã trường — xem Trường tuỳ chỉnh |
Cách tìm khách có sẵn: đi lần lượt các tiêu chí trong matchBy, bỏ qua tiêu chí không có giá trị trong body, dừng ở tiêu chí đầu tiên khớp đúng một khách. Không gửi matchBy ⇒ mặc định customerCode → các trường tuỳ chỉnh "duy nhất" có trong customFields → phone → email.
- Khớp ⇒ cập nhật các trường bạn gửi (trường không gửi giữ nguyên). Gửi
customerCodekhác mã hiện tại ⇒ đổi mã. - Không khớp ⇒ tạo khách mới. Body phải đủ các trường bắt buộc theo cấu hình cửa hàng (mặc định: Họ và tên; nhiều cửa hàng bắt buộc thêm Nhóm khách hàng, Nguồn… — thiếu thì trả
400 SCRM_CUSTOMER_FIELD_REQUIREDkèmparams.fieldKey).
Đặt customerCode = mã khách bên hệ thống của bạn (hoặc lưu vào một trường tuỳ chỉnh "duy nhất" như ma_erp) để các lần đồng bộ sau luôn khớp đúng khách, kể cả khi SĐT thay đổi.
Trạng thái và thuộc tính khách
GET /api/open/v1/customer-properties
{
"data": {
"statuses": [{ "id": 3, "name": "Mới", "code": null, "isActive": true, "isDefault": true }],
"leadSources": [{ "id": 12, "name": "Facebook Ads", "code": "fb_ads", "parentId": null, "isActive": true }],
"leadGroups": [{ "id": 7, "name": "Khách lẻ", "code": "retail", "parentId": null, "isActive": true }],
"leadIndustries": [],
"leadPlatforms": [{ "id": 21, "name": "Zalo", "code": null, "parentId": null, "isActive": true }]
}
}
Gửi id vào statusId / leadSourceId / leadGroupId / leadIndustryId / leadPlatformId khi upsert. Danh mục do cửa hàng cấu hình — nên tải khi khởi động tích hợp và làm mới định kỳ.
Ghi trường tuỳ chỉnh
PATCH /api/open/v1/customers/1f0c6a7e-5d1b-4a8e-9a63-2c1f0f6b9d10/fields
{ "customFields": { "hang_thanh_vien": "kim_cuong", "ngay_mua_cuoi": "2026-10-07", "ghi_chu_kho": null } }
Chỉ các trường gửi lên bị đổi; null / "" ⇒ xoá giá trị. Trả { "data": khách hàng } sau khi ghi.
Định nghĩa trường
GET /api/open/v1/custom-fields
Trả mọi trường của khách hàng — trường mặc định (isDefault: true, gửi ở cấp gốc body như fullName) và trường tuỳ chỉnh (gửi trong customFields):
{
"data": [
{ "key": "fullName", "label": "Họ và tên", "type": "text", "required": true, "unique": false, "isDefault": true, "options": null, "relation": null },
{ "key": "ma_erp", "label": "Mã ERP", "type": "text", "required": false, "unique": true, "isDefault": false, "options": null, "relation": null },
{
"key": "hang_thanh_vien", "label": "Hạng thành viên", "type": "select", "required": false, "unique": false, "isDefault": false,
"options": [{ "value": "vang", "label": "Vàng" }, { "value": "kim_cuong", "label": "Kim cương" }],
"relation": null
}
]
}
Mã trường do cửa hàng cấu hình ở Cấu hình → CRM → Trường tuỳ chỉnh. Gọi GET /custom-fields khi khởi động tích hợp để kiểm tra mã trường và lựa chọn hợp lệ, thay vì viết cứng.