Mục này hướng dẫn bạn sử dụng Partner API để tạo, tra cứu, lọc khách hàng và gắn thuộc tính tùy chỉnh — nền tảng cho mọi kịch bản đồng bộ CRM, lead nurturing, và remarketing đa kênh.
| Method | Endpoint | Chức năng |
|---|---|---|
POST | /partner/bizs/{bizAlias}/customers | Tạo khách hàng mới |
GET | /partner/bizs/{bizAlias}/pages/{page_pid}/customers/{customer_pid} | Lấy thông tin 1 khách hàng |
GET | /partner/bizs/{bizAlias}/customers | Tìm kiếm & lọc danh sách khách hàng |
GET | /partner/bizs/{bizAlias}/customers-internal | Tra cứu batch theo customer_pids |
GET | /partner/bizs/{bizAlias}/customers/count | Đếm tổng số khách hàng |
GET | /partner/bizs/{bizAlias}/tags | Lấy danh sách tag |
POST /partner/bizs/{bizAlias}/customers
CreateCustomerByPhoneDto| Field | Type | Bắt buộc | Mô tả |
|---|---|---|---|
platform | string | ✅ | Nền tảng kênh: "messenger", "zalo", "web",… |
phone | string | ✅ | Số điện thoại khách hàng (dùng làm định danh) |
page_pid | string | ✅ | Mã trang kênh mà khách hàng thuộc về |
name | string | ❌ | Tên hiển thị khách hàng |
picture | string | ❌ | URL ảnh đại diện |
attrs | array | ❌ | Danh sách thuộc tính tùy chỉnh (xem bên dưới) |
Mỗi phần tử trong attrs theo schema NameAndValueDto:
| Field | Type | Bắt buộc | Mô tả |
|---|---|---|---|
name | string | ✅ | Tên attribute (ví dụ: email, city, source) |
value | string | ✅ | Giá trị attribute |
cURL:
bashcurl -X POST "https://api.smax.ai/partner/bizs/my-shop/customers" \ -H "Authorization: Bearer <TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "platform": "zalo", "phone": "0901234567", "page_pid": "page_abc123", "name": "Nguyễn Văn A", "picture": "https://example.com/avatar.jpg", "attrs": [ { "name": "email", "value": "nguyenvana@gmail.com" }, { "name": "city", "value": "Hồ Chí Minh" }, { "name": "source", "value": "facebook_ads" }, { "name": "campaign", "value": "summer_sale_2026" } ] }'
JavaScript:
javascriptconst BASE_URL = "https://api.smax.ai"; const TOKEN = process.env.SMAX_API_TOKEN; const BIZ_ALIAS = "my-shop"; async function createCustomer({ phone, name, pagePid, platform, attrs }) { const response = await fetch(`${BASE_URL}/partner/bizs/${BIZ_ALIAS}/customers`, { method: "POST", headers: { "Authorization": `Bearer ${TOKEN}`, "Content-Type": "application/json" }, body: JSON.stringify({ platform: platform || "zalo", phone, page_pid: pagePid, name, attrs: attrs || [] }) }); if (!response.ok) { throw new Error(`Create customer failed: ${response.status}`); } return response.json(); } // Sử dụng const customer = await createCustomer({ phone: "0901234567", name: "Nguyễn Văn A", pagePid: "page_abc123", platform: "zalo", attrs: [ { name: "email", value: "nguyenvana@gmail.com" }, { name: "source", value: "landing_page" } ] }); console.log("Created:", customer);
Python:
pythonimport requests import os BASE_URL = "https://api.smax.ai" TOKEN = os.environ["SMAX_API_TOKEN"] BIZ_ALIAS = "my-shop" def create_customer(phone, name, page_pid, platform="zalo", attrs=None): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json" } payload = { "platform": platform, "phone": phone, "page_pid": page_pid, "name": name, "attrs": attrs or [] } response = requests.post(url, json=payload, headers=headers) response.raise_for_status() return response.json() # Sử dụng customer = create_customer( phone="0901234567", name="Nguyễn Văn A", page_pid="page_abc123", attrs=[ {"name": "email", "value": "nguyenvana@gmail.com"}, {"name": "source", "value": "webinar_registration"} ] ) print("Created:", customer)
💡 Mẹo: Trường
phoneđóng vai trò như primary key để SmaxAI nhận diện khách hàng. Nếu bạn POST một số điện thoại đã tồn tại, hệ thống sẽ cập nhật thay vì tạo trùng.
GET /partner/bizs/{bizAlias}/pages/{page_pid}/customers/{customer_pid}
| Parameter | Mô tả |
|---|---|
bizAlias | Mã doanh nghiệp |
page_pid | Mã trang kênh |
customer_pid | Mã khách hàng cần tra cứu |
cURL:
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/pages/page_abc123/customers/cust_xyz789" \ -H "Authorization: Bearer <TOKEN>"
Python:
pythondef get_customer(page_pid, customer_pid): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/pages/{page_pid}/customers/{customer_pid}" headers = {"Authorization": f"Bearer {TOKEN}"} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() customer = get_customer("page_abc123", "cust_xyz789") print(f"Tên: {customer.get('name')}") print(f"SĐT: {customer.get('phone')}") print(f"Attrs: {customer.get('attrs')}")
customer_pid (ví dụ: từ webhook, từ thread, từ kết quả tìm kiếm)GET /partner/bizs/{bizAlias}/customers
⚠️ Yêu cầu role: GET_LIST_CUSTOMERS
| Parameter | Type | Bắt buộc | Mô tả |
|---|---|---|---|
phone | string | ❌ | Lọc theo 1 số điện thoại cụ thể |
phones | array | ❌ | Lọc theo nhiều SĐT cùng lúc |
platform | string | ❌ | Lọc theo nền tảng (messenger, zalo, web…) |
page_pids | array | ❌ | Lọc theo danh sách trang kênh |
exists_phone | boolean | ❌ | true = chỉ KH có SĐT, false = KH không có SĐT |
lt_created_at | string | ❌ | KH được tạo trước thời điểm này (ISO 8601) |
limit | number | ❌ | Số kết quả trả về (phân trang) |
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/customers?phone=0901234567" \ -H "Authorization: Bearer <TOKEN>"
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/customers?platform=zalo&exists_phone=true&limit=50" \ -H "Authorization: Bearer <TOKEN>"
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/customers?phones[]=0901234567&phones[]=0912345678&phones[]=0923456789" \ -H "Authorization: Bearer <TOKEN>"
pythondef search_customers(platform=None, exists_phone=None, limit=20, lt_created_at=None, page_pids=None): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers" headers = {"Authorization": f"Bearer {TOKEN}"} params = {"limit": limit} if platform: params["platform"] = platform if exists_phone is not None: params["exists_phone"] = str(exists_phone).lower() if lt_created_at: params["lt_created_at"] = lt_created_at if page_pids: params["page_pids"] = page_pids response = requests.get(url, headers=headers, params=params) response.raise_for_status() return response.json() # Lấy 30 khách Messenger có SĐT, tạo trước 2026-07-01 results = search_customers( platform="messenger", exists_phone=True, limit=30, lt_created_at="2026-07-01T00:00:00Z" ) print(f"Tìm thấy: {len(results)} khách hàng")
GET /partner/bizs/{bizAlias}/customers-internal
⚠️ Yêu cầu role: GET_LIST_CUSTOMERS
Endpoint này cho phép tra cứu nhiều khách hàng cùng lúc theo danh sách customer_pids — hữu ích khi bạn đã có sẵn danh sách ID từ threads hoặc đơn hàng.
| Parameter | Type | Bắt buộc | Mô tả |
|---|---|---|---|
customer_pids | array | ✅ | Danh sách mã khách hàng cần tra cứu |
page_pids | array | ✅ | Danh sách mã trang kênh tương ứng |
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/customers-internal?customer_pids[]=cust_001&customer_pids[]=cust_002&page_pids[]=page_abc123" \ -H "Authorization: Bearer <TOKEN>"
pythondef get_customers_batch(customer_pids, page_pids): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers-internal" headers = {"Authorization": f"Bearer {TOKEN}"} params = { "customer_pids": customer_pids, "page_pids": page_pids } response = requests.get(url, headers=headers, params=params) response.raise_for_status() return response.json() # Lấy thông tin 3 khách hàng cùng lúc customers = get_customers_batch( customer_pids=["cust_001", "cust_002", "cust_003"], page_pids=["page_abc123"] )
💡 Khi nào dùng
**customers-internal**thay vì**customers**?
- Bạn đã có danh sách
customer_pid(từ threads, orders, webhook…) và cần lấy thông tin chi tiết- Cần tra cứu nhanh nhiều KH trong 1 request thay vì gọi
GET /customers/{pid}nhiều lần
GET /partner/bizs/{bizAlias}/customers/count
Trả về tổng số khách hàng của Business, hữu ích cho dashboard và báo cáo.
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/customers/count" \ -H "Authorization: Bearer <TOKEN>"
pythondef count_customers(): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers/count" headers = {"Authorization": f"Bearer {TOKEN}"} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() total = count_customers() print(f"Tổng khách hàng: {total}")
GET /partner/bizs/{bizAlias}/tags
Tag (nhãn) dùng để phân loại khách hàng trong SmaxAI. Endpoint này trả về toàn bộ danh sách tag đã tạo trong Business.
bashcurl -X GET "https://api.smax.ai/partner/bizs/my-shop/tags" \ -H "Authorization: Bearer <TOKEN>"
pythondef get_tags(): url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/tags" headers = {"Authorization": f"Bearer {TOKEN}"} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() tags = get_tags() for tag in tags: print(f"Tag: {tag.get('name')} (ID: {tag.get('id')})")
💡 Ứng dụng thực tế: Dùng danh sách tag ID để lọc khách hàng theo phân nhóm, hoặc hiển thị lên dropdown trong CRM nội bộ.
Kịch bản: Đội marketing có danh sách khách hàng đăng ký webinar trên Google Sheets. Bạn cần tự động đồng bộ sang SmaxAI để chatbot chăm sóc follow-up.
Google Sheets n8n Workflow SmaxAI ┌──────────┐ ┌───────────────────┐ ┌──────────────┐ │ Dữ liệu │ │ 1. Trigger: │ │ │ │ KH mới │────►│ Sheet Updated │ │ /customers │ │ │ │ │ │ (POST) │ │ • Tên │ │ 2. Loop each row │────►│ │ │ • SĐT │ │ │ │ Tạo KH + │ │ • Email │ │ 3. HTTP Request │ │ attrs │ │ • Nguồn │ │ POST /customers │ │ │ └──────────┘ │ │ │ /customers │ │ 4. Check response │◄────│ (Response) │ │ → Log kết quả │ │ │ └───────────────────┘ └──────────────┘
Webinar RegistrationsSheet1| Field | Giá trị |
|---|---|
| Method | POST |
| URL | https://api.smax.ai/partner/bizs/{{ $env.SMAX_BIZ_ALIAS }}/customers |
| Authentication | Header Auth |
| Header Name | Authorization |
| Header Value | Bearer {{ $env.SMAX_API_TOKEN }} |
| Body Type | JSON |
Body JSON:
json{ "platform": "zalo", "phone": "{{ $json['SĐT'] }}", "page_pid": "{{ $env.SMAX_PAGE_PID }}", "name": "{{ $json['Họ và tên'] }}", "attrs": [ { "name": "email", "value": "{{ $json['Email'] }}" }, { "name": "source", "value": "webinar_registration" }, { "name": "campaign", "value": "{{ $json['Chiến dịch'] }}" }, { "name": "registered_at", "value": "{{ $now.toISO() }}" } ] }
{{ $json.statusCode }} equals 201Để đồng bộ ngược từ SmaxAI về Google Sheets (ví dụ: cập nhật trạng thái sau khi chatbot tương tác), bạn thêm 1 workflow riêng:
SmaxAI Webhook n8n Workflow Google Sheets ┌──────────────┐ ┌────────────────────┐ ┌──────────────┐ │ KH tương tác │ │ 1. Webhook Trigger │ │ │ │ với chatbot │───►│ │ │ Cập nhật │ │ │ │ 2. GET /customers │ │ cột "Trạng │ │ (Webhook) │ │ ?phone=... │───►│ thái" = │ │ │ │ │ │ "Đã tương │ │ │ │ 3. Update Sheet │ │ tác bot" │ └──────────────┘ └────────────────────┘ └──────────────┘
Kịch bản: Bạn muốn xây dựng dashboard theo dõi số lượng khách hàng theo thời gian, phân theo kênh và nguồn.
pythonimport requests import json from datetime import datetime, timedelta import os BASE_URL = "https://api.smax.ai" TOKEN = os.environ["SMAX_API_TOKEN"] BIZ_ALIAS = os.environ["SMAX_BIZ_ALIAS"] def collect_customer_stats(): headers = {"Authorization": f"Bearer {TOKEN}"} # 1. Đếm tổng KH count_url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers/count" total = requests.get(count_url, headers=headers).json() # 2. Đếm KH có SĐT has_phone_url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers?exists_phone=true&limit=1" # Dùng response metadata để lấy total count # 3. Đếm KH theo từng platform platforms = ["messenger", "zalo", "web"] by_platform = {} for platform in platforms: url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/customers?platform={platform}&limit=1" resp = requests.get(url, headers=headers).json() by_platform[platform] = resp.get("total", 0) # 4. Lấy danh sách tags tags_url = f"{BASE_URL}/partner/bizs/{BIZ_ALIAS}/tags" tags = requests.get(tags_url, headers=headers).json() stats = { "timestamp": datetime.now().isoformat(), "total_customers": total, "by_platform": by_platform, "total_tags": len(tags) if isinstance(tags, list) else 0 } return stats # Chạy và lưu kết quả stats = collect_customer_stats() print(json.dumps(stats, indent=2, ensure_ascii=False)) # Lưu vào file hoặc push vào NocoDB / database để Metabase đọc with open(f"stats_{datetime.now().strftime('%Y%m%d')}.json", "w") as f: json.dump(stats, f, ensure_ascii=False, indent=2)
| Tần suất | Mục đích |
|---|---|
| Mỗi 15 phút | Dashboard real-time |
| Mỗi giờ | Báo cáo trong ngày |
| Mỗi ngày lúc 00:00 | Snapshot hàng ngày cho trend chart |
401 Unauthorizedjson{ "statusCode": 401, "message": "Unauthorized" }
Nguyên nhân: Token không hợp lệ, hết hạn, hoặc thiếu header Authorization.
Giải pháp: Kiểm tra lại token, đảm bảo format Bearer <token> (có khoảng trắng sau "Bearer").
403 Forbiddenjson{ "statusCode": 403, "message": "Forbidden resource" }
Nguyên nhân: Token không có role GET_LIST_CUSTOMERS.
Giải pháp: Liên hệ admin SmaxAI để cấp thêm quyền cho API token.
400 Bad Request khi tạo KHjson{ "statusCode": 400, "message": ["phone must be a string", "page_pid should not be empty"] }
Nguyên nhân: Thiếu trường bắt buộc (platform, phone, page_pid) hoặc sai kiểu dữ liệu.
Giải pháp: Kiểm tra body JSON đúng schema CreateCustomerByPhoneDto. Cả 3 trường platform, phone, page_pid đều bắt buộc.
Khi POST một SĐT đã tồn tại trên cùng Business, API sẽ không tạo bản ghi trùng. Hành vi cụ thể (cập nhật hay bỏ qua) phụ thuộc vào cấu hình Business. Khuyến nghị: luôn kiểm tra KH tồn tại bằng GET /customers?phone=... trước khi tạo mới nếu bạn cần kiểm soát chặt chẽ.
Trước khi đưa vào production, hãy kiểm tra:
bizAlias và page_pid cho Business cần tích hợpGET_LIST_CUSTOMERS) cho các endpoint cần dùng0901234567, không dùng +84901234567)429 (rate limit) và 5xx (server error)Trên trang này