← Tất cả bài viết
Hướng dẫn

Tải tin nhắn WhatsApp cũ hơn bằng yêu cầu lịch sử theo nhu cầu

Để tải tin nhắn WhatsApp cũ hơn qua UnifyPort, hãy đăng ký conversation.history trước, rồi yêu cầu lịch sử bằng một tin nhắn đã lưu làm mốc before. Phản hồi HTTP không chứa nội dung tin nhắn: 202 và status: accepted chỉ xác nhận đã tiếp nhận yêu cầu. Lịch sử khả dụng sẽ đến bất đồng bộ. Vì vậy, hãy xây dựng nút “Tải tin nhắn trước đó” theo cơ chế best-effort, không phải công cụ xuất kho lưu trữ đầy đủ hay vòng lặp phân trang tự khẳng định đã đến cuối lịch sử.

Điểm chính

  • Thao tác này dành cho trò chuyện riêng của provider=whatsapp, không dành cho nhóm, kênh hoặc whatsapp-protocol.
  • Chuẩn bị đăng ký sự kiện và lưu trữ bền vững trước khi gửi yêu cầu.
  • Chuyển mốc bằng ID, thời gian gửi và chiều của một tin nhắn nội dung gốc thực sự.
  • Dữ liệu có thể đến thành nhiều lô, bị lặp, đến muộn hoặc không đến. Không có callback không có nghĩa là đã hoàn tất.
  • Lịch sử bổ sung dòng thời gian, không nên kích hoạt trả lời tự động dành cho tin nhắn mới.

Tách phản hồi yêu cầu khỏi kết quả lịch sử

Tài liệu yêu cầu lịch sử hội thoại định nghĩa POST /v1/accounts/{account_id}/conversations/history/request. Thao tác này khởi tạo việc chuyển dữ liệu bất đồng bộ; đây không phải API đọc REST trả ngay các tin nhắn đã lưu.

Quan sátĐiều có thể xác nhậnĐiều không thể xác nhận
HTTP 202, data.status: acceptedYêu cầu đã được tiếp nhậnTin nhắn đã đến hoặc thao tác đã hoàn tất
HTTP request_idMã tham chiếu để chẩn đoán yêu cầu HTTPID tác vụ hoặc khóa liên kết callback
conversation.history có data.history.source: on_demandĐã nhận một lô lịch sử theo yêu cầuĐây là lô duy nhất hoặc cuối cùng
Lô rỗng hoặc ít tin nhắnNội dung của lô đóĐã hết lịch sử khả dụng
HTTP hết thời gian chờMáy khách chưa nhận được phản hồi xác địnhYêu cầu chưa tạo ra tác động nào

Hướng dẫn khôi phục runtime tài khoản nhắn tin giải quyết việc khôi phục kết nối. Đây là công việc khác với bổ sung lịch sử: cả kết nối lại lẫn yêu cầu lịch sử đều không bảo đảm lấy lại toàn bộ tin nhắn bị bỏ lỡ trong thời gian gián đoạn.

Chuẩn bị bộ nhận trước khi bật nút

Thêm conversation.history vào danh sách đăng ký của endpoint mà không bỏ các sự kiện hộp thư đang cần. Tiếp tục dùng message.received cho lưu lượng trực tiếp. Khi sửa endpoint hiện có, làm theo tài liệu cấu hình webhook và tránh vô tình xóa signing_secret.

Tuân thủ quy tắc chuyển webhook: kiểm tra X-Device-Signature bằng HMAC-SHA256 trên X-Device-Timestamp, một dấu chấm và phần thân yêu cầu nguyên gốc. Kiểm tra độ mới của timestamp, sau đó lưu bền vững dữ liệu đã xác thực trước khi trả 2xx.

Lịch sử cần nhánh xử lý trùng lặp riêng. Các phần khác nhau của WhatsApp HistorySync có thể dùng lại ID sự kiện cấp cao nhất. Không được bỏ cả lô chỉ vì ID đó đã xuất hiện. Trong workspace, hợp nhất tin nhắn theo provider, account_id, data.conversation.id và từng data.messages[].id.

Không đưa nội dung lịch sử vào bộ kích hoạt trả lời tự động cho tin nhắn trực tiếp. Nhận một câu hỏi cũ hôm nay không chứng minh khách hàng vừa hỏi lại hôm nay.

Tạo mốc before hợp lệ

Chọn tin nhắn đã quan sát được từ cùng tài khoản nhắn tin và cùng cuộc trò chuyện riêng. Mốc cần message_id, sent_at và direction. Không suy đoán các giá trị này từ tiêu đề cuộc trò chuyện, thời gian nhận sự kiện hay số điện thoại.

Phần thân yêu cầu minh họa dưới đây tuân theo cấu trúc tài liệu. Thay các giá trị mẫu bằng giá trị thực tế đã lưu:

{
  "conversation_id": "100000000000002@lid",
  "before": {
    "message_id": "MSG_HISTORY_ANCHOR_001",
    "sent_at": "2026-09-28T03:00:00Z",
    "direction": "inbound"
  },
  "limit": 50
}

Gửi phần thân tới thao tác POST đã nêu, dùng X-Api-Key được giữ ở backend. account_id phải là một đoạn đường dẫn không rỗng, không chứa khoảng trắng hay dấu gạch chéo, kể cả dấu gạch chéo đã mã hóa. Không đặt ID hội thoại vào đoạn đường dẫn dành cho tài khoản.

Với yêu cầu tiếp theo, chọn tin nhắn nội dung gốc sớm nhất trong dữ liệu đã nhận và có đầy đủ trường làm mốc. Loại các bản ghi tổng hợp có type: call. JavaScript sau chỉ tạo mốc từ tin nhắn đã được chọn và kiểm tra; đây không phải bộ nhận hay worker phân trang tự động:

function beforeFromMessage(message) {
  if (!message || message.type === 'call' ||
      typeof message.id !== 'string' || !message.id ||
      typeof message.sent_at !== 'string' ||
      !Number.isFinite(Date.parse(message.sent_at)) ||
      !['inbound', 'outbound'].includes(message.direction)) {
    throw new Error('Select a native content message with complete anchor fields');
  }
  return {
    message_id: message.id,
    sent_at: message.sent_at,
    direction: message.direction
  };
}

Lưu ý rằng type không được sao chép vào before. Nếu không có mốc hợp lệ, hãy tắt thao tác và giải thích lý do. Không dùng bản ghi cuộc gọi tổng hợp hay tự tạo thời điểm cũ hơn.

Biểu diễn sự chưa chắc chắn trong hộp thư

Đây là các hành vi ứng dụng được khuyến nghị, không phải trạng thái API bổ sung:

  1. Trước khi gửi: lưu tài khoản, hội thoại, mốc và thời gian yêu cầu của ứng dụng. Thực hiện tuần tự các yêu cầu của nhân viên trong từng hội thoại để giảm thao tác chồng chéo.
  2. Sau khi được tiếp nhận: hiển thị “Đã tiếp nhận yêu cầu; đang chờ lịch sử khả dụng”. Tiếp tục nhận tin nhắn trực tiếp một cách độc lập.
  3. Mỗi khi có lô: hợp nhất từng tin nhắn theo cách idempotent. Giữ các chỉnh sửa trực tiếp và cơ chế ngăn khôi phục nội dung đã xóa, thay vì để lịch sử cũ ghi đè trạng thái mới.
  4. Sau khi nhận nội dung cũ hơn: cho phép người dùng chủ động gửi yêu cầu tiếp theo bằng mốc hợp lệ sớm nhất. Nếu chưa có mốc hợp lệ cũ hơn, hiển thị “Chưa nhận được mốc cũ hơn”, không phải “Đã tải toàn bộ lịch sử”.
  5. Sau timeout hoặc khi không có callback: giữ trạng thái chưa xác định và tiếp tục nhận các lô đến muộn. Không tự động gửi lại yêu cầu cũ.

Tài liệu không định nghĩa cursor trang tiếp theo hay trạng thái hoàn tất. account.history.synced là bản tổng kết một batch/chunk của HistorySync, không phải bằng chứng rằng một yêu cầu theo nhu cầu đã xong hoặc kho lưu trữ đã đầy đủ. Đừng biến nó thành tín hiệu hoàn tất tác vụ không có trong hợp đồng API.

Cũng cần tách quan hệ trích dẫn trong lịch sử khỏi khả năng gửi. Tin nhắn lịch sử không có reply_token; hướng dẫn trả lời có trích dẫn giải thích vì sao ID tin nhắn cha không thể thay thế token. Tệp đính kèm không khả dụng phải được hiển thị đúng như vậy, không phải như một tệp đã tải xuống.

Lỗi và kiểm tra trước khi triển khai

400 có thể là invalid_request, provider_invalid_request — bao gồm mốc cuộc gọi tổng hợp — hoặc unsupported_conversation_type. Các provider khác trả 501 unsupported_by_provider. Hãy sửa phạm vi áp dụng hoặc dữ liệu đầu vào thay vì tạo vòng lặp thử lại. Lưu HTTP request_id để chẩn đoán, nhưng không coi đó là khóa liên kết callback.

Trước khi đưa vào sử dụng, nên kiểm tra lô trùng, hai phần khác nhau dùng cùng ID sự kiện, callback đến sau HTTP timeout, tin nhắn trực tiếp xen kẽ lịch sử và mốc thiếu chiều tin nhắn. Đây là các ca kiểm tra đề xuất, không phải kết quả đã ghi nhận.

UnifyPort cung cấp giao diện không chính thức. Tính năng này bổ sung ngữ cảnh hội thoại theo cơ chế best-effort, không cung cấp bản sao lưu đầy đủ, phát lại được bảo đảm hay quyền truy cập tài khoản bất kỳ. Vẫn cần kho tin nhắn được phép lưu và quy tắc thời hạn lưu trữ của riêng bạn.

Câu hỏi thường gặp

202 có nghĩa đã lấy được tin nhắn cũ không?

Không. Nó chỉ xác nhận tiếp nhận yêu cầu. Tin nhắn khả dụng sẽ đến qua các sự kiện lịch sử bất đồng bộ.

Có thể yêu cầu liên tục đến khi nhận một lô ít tin nhắn không?

Không nên dùng đó làm điều kiện kết thúc. Kích thước lô không chứng minh tính đầy đủ, và yêu cầu tự động có thể chồng chéo với kết quả đến muộn.

Có thể dùng cho nhóm WhatsApp, LINE hoặc Zalo không?

Thao tác này chỉ được mô tả cho trò chuyện riêng của provider=whatsapp. Ngay cả khi đội hỗ trợ dùng chung hộp thư WhatsApp và Zalo, cấu trúc webhook thống nhất cũng không có nghĩa mọi kênh đều hỗ trợ yêu cầu lịch sử.

Bước tiếp theo và nguồn tham khảo

Triển khai bộ nhận và trạng thái chưa xác định theo tài liệu yêu cầu lịch sử hội thoại trước khi bật nút trong hộp thư.

Tài liệu chính thức được đối chiếu ngày 2026-09-30:

UnifyPort API

Biến tích hợp nhắn tin thành một pipeline sản phẩm ổn định.

Bắt đầu bằng cách gửi qua một API, rồi đưa mọi tin nhắn inbound trở lại hệ thống kinh doanh bằng sự kiện chuẩn.