Chuyển tới nội dung chính

REST API Hỗ trợ

REST API của Hỗ trợ cho server của bạn làm việc với hộp thư như một nhân viên: liệt kê hội thoại từ mọi kênh, đọc dòng thời gian, trả lời hoặc ghi chú nội bộ, giao việc, gắn tag và đánh dấu đã xử lý. Dùng nó để nối hộp thư với ERP, CRM, hệ thống đơn hàng hay bot của riêng bạn. Webhook báo cho bạn khi có chuyện xảy ra, nên không cần gọi API liên tục để dò.

Trước khi bắt đầu​

  • Một API key tạo trong dashboard (API Keys). Gửi trong header Authorization: Bearer ht_... tới https://api.hatang.dev. Xem Xác thực.

  • Key cần đúng scope:

    ScopeCho phép
    chat:readLiệt kê, đọc site, hội thoại, dòng thời gian, khách truy cập, phiếu hỗ trợ, báo cáo, kịch bản, chu trình, chiến dịch, câu trả lời mẫu, quy tắc phân phối và nguồn kiến thức
    chat:writeMọi thứ của chat:read, cộng với trả lời, cập nhật hội thoại, phiếu, site, kịch bản, chu trình, chiến dịch, câu trả lời mẫu, quy tắc phân phối và nguồn kiến thức
    crm:read / crm:writeKhách hàng, trường tuỳ chỉnh của khách hàng và Zalo ZNS (key có scope chat:* cũng dùng được)
    products:read / products:writeSản phẩm và đơn hàng (key có scope chat:* cũng dùng được)

    Scope write bao gồm read; chat:* và * bao trùm tất cả.

  • Module Hỗ trợ phải đang bật cho doanh nghiệp. Khi module tắt, mọi endpoint trả 403 product_disabled (Bật/tắt module).

ghi chú

chat:reply và chat:manage là quyền của nhân viên trong dashboard (Nhân viên và phân quyền), không phải scope của API key.

1. Liệt kê hội thoại​

GET /chat/conversations trả về hội thoại có hoạt động mới nhất trước, mặc định 50 hội thoại mỗi trang (tối đa 100).

Tham số queryÝ nghĩa
statusPhân tách bằng dấu phẩy: open, pending, resolved, closed
unansweredtrue: chỉ hội thoại mà khách là người nhắn cuối
assignee_idHội thoại đang giao cho nhân viên này
site_idHội thoại của một site
visitor_idHội thoại của một khách truy cập
qTừ khoá tìm kiếm (tối đa 200 ký tự)
flaghidden (đang tạm ẩn), spam hoặc none. Mặc định chỉ trả hội thoại không gắn cờ
limit1–100, mặc định 50
afterCon trỏ: id của hội thoại cuối cùng ở trang trước
curl "https://api.hatang.dev/chat/conversations?status=open,pending&unanswered=true&limit=20" \
-H "Authorization: Bearer ht_123..."
Response (rút gọn)
{
"object": "list",
"has_more": true,
"data": [
{
"id": "cnv_...",
"site_id": "site_...",
"visitor_id": "vis_...",
"channel": "zalo",
"channel_account_id": "...",
"status": "open",
"assignee_kind": null,
"assignee_id": null,
"seq": 14,
"agent_unread": 2,
"visitor_unread": 0,
"last_message_at": "2026-10-23T08:15:02.000Z",
"last_message_preview": "Shop còn size M không ạ?",
"last_message_sender_type": "visitor",
"first_response_at": null,
"tags": [],
"member_ids": [],
"flag": null,
"subject": null,
"created_at": "2026-10-23T08:14:40.000Z",
"updated_at": "2026-10-23T08:15:02.000Z",
"visitor": { "id": "vis_...", "name": "Lan", "...": "..." }
}
]
}

channel là một trong web, zalo, zalo_personal, messenger, instagram, tiktok, tiktokshop, whatsapp, telegram, x, line hoặc email. Hội thoại có cùng các trường này ở mọi nơi, kể cả trong webhook.

cẩn thận

Tham số boolean trên query được hiểu là "có mặt nghĩa là true". Gửi unanswered=true để lọc, còn không thì bỏ hẳn tham số; unanswered=false không tắt bộ lọc.

2. Đọc dòng thời gian​

GET /chat/conversations/{id}/messages trả về tin nhắn và sự kiện theo thứ tự seq. Mỗi phần tử có kind: "message" hoặc kind: "event".

Tham số queryÝ nghĩa
after_seqTrả các phần tử sau seq này (cũ trước). Không truyền thì nhận trang mới nhất
limit1–200, mặc định 100
include_privatetrue để lấy cả ghi chú nội bộ. Bỏ trống để không lấy
curl "https://api.hatang.dev/chat/conversations/cnv_123/messages?after_seq=10" \
-H "Authorization: Bearer ht_123..."
Một tin nhắn
{
"kind": "message",
"id": "msg_...",
"conversation_id": "cnv_123",
"seq": 11,
"sender_type": "visitor",
"sender_id": "vis_...",
"sender_name": "Lan",
"visibility": "public",
"content_type": "text",
"content": "Shop còn size M không ạ?",
"attachments": [],
"metadata": {},
"delivery_status": null,
"delivery_error": null,
"read_at": null,
"created_at": "2026-10-23T08:15:02.000Z"
}

sender_type là visitor, agent, bot hoặc system. Tệp đính kèm có url ký sẵn, dùng được trong 24 giờ; hết hạn thì đọc lại tin để có link mới.

3. Trả lời hoặc ghi chú​

POST /chat/conversations/{id}/messages gửi một tin dưới tên đội của bạn. Hạ Tầng chuyển tin qua đúng kênh của hội thoại: widget, Zalo, Messenger, email…

TrườngKiểuGhi chú
contentstringBắt buộc, 1–10.000 ký tự
visibilitypublic | privateMặc định public. private là ghi chú nội bộ, khách không thấy
sender_namestringTên khách nhìn thấy, tối đa 100 ký tự. Mặc định Support
attachmentsstring[]Tối đa 5 id của tệp đã tải lên hội thoại
metadataobjectThẻ (product, order, payment, quick_replies), tối đa 4 KB

Gửi kèm header Idempotency-Key để thử lại an toàn. Request thứ hai cùng key trong cùng hội thoại trả về tin gốc với mã 200 và "duplicate": true thay vì gửi hai lần.

curl -X POST "https://api.hatang.dev/chat/conversations/cnv_123/messages" \
-H "Authorization: Bearer ht_123..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-8812-shipped" \
-d '{"content": "Đơn #8812 đã giao cho đơn vị vận chuyển, dự kiến tới vào thứ Sáu.", "sender_name": "Shop Trà Xanh"}'
201 Created
{ "object": "chat_message", "id": "msg_...", "seq": 15, "conversation_id": "cnv_123", "duplicate": false }

Lỗi có thể gặp:

  • 409 conversation_closed: hội thoại đã closed, không nhận thêm tin.
  • 422 validation_error: content trống, quá dài, hoặc metadata vượt 4 KB.
  • Trên kênh mạng xã hội, việc gửi diễn ra bất đồng bộ. API nhận tin ngay; nếu sau đó nền tảng từ chối (ví dụ đã quá cửa sổ 24 giờ của Messenger hay WhatsApp), tin có delivery_status: "failed" kèm delivery_error. Đọc lại dòng thời gian hoặc xem trong hộp thư để biết. Trang của từng kênh giải thích quy định riêng của nền tảng đó.

Để gửi thẻ sản phẩm, dùng POST /chat/conversations/{id}/products với product_ids (tối đa 10) và intro tuỳ chọn.

4. Giao việc, gắn tag, tạm ẩn và xử lý xong​

PATCH /chat/conversations/{id} đổi một hoặc nhiều trường:

TrườngGiá trị
statusopen, pending, resolved, closed
assignee_idUser id của nhân viên, hoặc null để bỏ giao
tagsToàn bộ danh sách tag (thay danh sách hiện tại; tối đa 20 tag, mỗi tag tối đa 40 ký tự)
member_idsToàn bộ danh sách nhân viên cùng theo dõi hội thoại (tối đa 20)
flaghidden (tạm ẩn), spam, hoặc null để bỏ cờ
curl -X PATCH "https://api.hatang.dev/chat/conversations/cnv_123" \
-H "Authorization: Bearer ht_123..." \
-H "Content-Type: application/json" \
-d '{"status": "resolved", "tags": ["shipping"]}'

Response là hội thoại sau khi cập nhật. Mỗi thay đổi được ghi thành một sự kiện trên dòng thời gian, đứng tên API key.

5. Nhận thông báo bằng webhook​

Tạo endpoint webhook (dashboard Webhooks, hoặc POST /webhooks) và chọn các sự kiện Hỗ trợ cần nhận. Mỗi lần gửi có dạng { "type", "created_at", "data" }, ký như mọi webhook khác của Hạ Tầng (Webhook).

Sự kiệnKhi nào
chat.conversation.createdCó hội thoại mới trên bất kỳ kênh nào
chat.conversation.assignedNgười phụ trách thay đổi
chat.conversation.resolved, chat.conversation.closed, chat.conversation.reopenedTrạng thái thay đổi
chat.conversation.handoffTrợ lý AI chuyển hội thoại cho người
chat.conversation.taggedCó tag mới (mỗi tag mới một sự kiện, kèm tag)
chat.message.createdCó tin công khai mới, từ khách, nhân viên, bot hoặc API
chat.visitor.identifiedMột khách truy cập được nhận diện
chat.ticket.created, chat.ticket.updated, chat.ticket.resolved, chat.ticket.breachedPhiếu hỗ trợ thay đổi, quá hạn SLA
chat.rating.createdKhách đánh giá hội thoại
chat.order.created, chat.order.updated, chat.order.paidĐơn hàng
chat.flow.webhook, chat.campaign.leadBước webhook của kịch bản chạy; form chiến dịch thu được lead
chat.zns.sent, chat.zns.failedKết quả gửi Zalo ZNS

chat.message.created mang nội dung tin cùng một object conversation. Ghi chú nội bộ không bắn sự kiện này.

Tránh vòng lặp trả lời

chat.message.created bắn cả cho tin bạn vừa gửi. Nếu bot trả lời theo sự kiện này, chỉ xử lý khi data.sender_type là visitor.

6. Liên kết tới trang quản trị của bạn​

Liên kết hồ sơ đặt URL của bạn cạnh mỗi hội thoại, điền theo người trong hội thoại đó. PUT /chat/profile-links (scope chat:write) thay toàn bộ danh sách; GET /chat/profile-links (chat:read) trả về danh sách.

curl -X PUT "https://api.hatang.dev/chat/profile-links" \
-H "Authorization: Bearer ht_123..." \
-H "Content-Type: application/json" \
-d '{"data": [{"label": "Admin", "url": "https://example.com/admin/users/{{user_id}}"}, {"label": "Orders", "url": "https://example.com/admin/orders?email={{email}}"}]}'

Phản hồi là { "object": "list", "data": [...] }, mỗi liên kết có id (pl_…); gửi lại id để giữ nguyên liên kết. Thêm site_ids để chỉ hiện liên kết trong hội thoại của một số site.

BiếnGiá trị
{{user_id}}user_id đã xác minh từ identify có chữ ký; nếu không, là id khách tự khai và nhân viên thấy liên kết bị đánh dấu chưa xác minh (Nhận diện khách)
{{email}}, {{phone}}, {{name}}Thông tin liên hệ của khách
{{customer_id}}, {{conversation_id}}, {{site_id}}Id trong Hạ Tầng
{{field.<key>}}Một trường thông tin khách hàng
{{data.<key>}}Dữ liệu tuỳ chỉnh của khách (luôn bị đánh dấu chưa xác minh)

Quy tắc: chỉ https://, biến chỉ đứng sau tên miền (không bao giờ trong tên miền), mỗi URL tối đa 500 ký tự, tối đa 10 liên kết. Sai quy tắc trả 422 validation_error. Giá trị được mã hoá URL, và liên kết có biến không có giá trị sẽ không hiện.

Các endpoint khác​

Cùng API này bao phủ phần còn lại của Hỗ trợ. Mọi đường dẫn bắt đầu bằng https://api.hatang.dev/chat:

NhómĐường dẫn
Site/sites, /sites/{id}, /sites/{id}/identity-secret
Khách truy cập và bảng Đang truy cập/visitors/{id}, /visitors/{id}/conversations, /live, /live/greet
Khách hàng/customers, /customers/{id}, /customers/{id}/merge, /customers/{id}/conversations, /customers/export.csv, /customer-fields
Phiếu hỗ trợ và SLA/tickets, /tickets/stats, /tickets/{id}, /sla
Liên kết hồ sơ/profile-links
Tự động hoá/flows, /workflows, /campaigns, /routing-rules, /canned-responses
Kiến thức cho AI/sites/{id}/kb/sources, /sites/{id}/kb/files, /sites/{id}/kb/search
Bán hàng/products, /orders, /orders/{id}/payment-link
Zalo ZNS/zns/templates, /zns, /zns/bulk
Báo cáo/reports, /ratings

Mọi request và response có trong tham chiếu REST API. SDK Node.js bọc phần lớn các endpoint này trong hatang.chat.*; xem SDK Node.js.

Lỗi và giới hạn​

Lỗi dùng chung dạng { "statusCode", "name", "message" }. Rẽ nhánh theo name, không theo message.

MãnameNguyên nhân
401missing_api_keyThiếu header Authorization
403invalid_api_keyKey không tồn tại hoặc đã thu hồi
401restricted_api_keyKey thiếu scope cho endpoint này
403product_disabledModule Hỗ trợ đang tắt
404not_foundId không tồn tại trong doanh nghiệp này
409conversation_closedGửi tin vào hội thoại đã đóng
422validation_errorBody hoặc query không hợp lệ
429rate_limit_exceededVượt giới hạn tần suất

Các endpoint Hỗ trợ cho phép 50 request mỗi giây cho mỗi doanh nghiệp. Xem Lỗi và Giới hạn.

Bước tiếp theo​

Xem trang này dạng Markdown