API

Webhook

Nhận sự kiện tin đã gửi, đã tới máy, thất bại, mẫu được duyệt… Địa chỉ gốc: https://app.zapro.vn/v1.

ZaPro nhận webhook của Zalo thay bạn (Zalo bắt trả lời trong 2 giây), lưu lại và gửi tới máy chủ của bạn, tự gửi lại trong khoảng 24 giờ nếu chưa nhận được 2xx.

Sự kiện

message.sentmessage.deliveredmessage.failedtemplate.approvedtemplate.rejectedoa.connectedoa.disconnectedoa.follower.addedoa.follower.removedoa.message.received

Quản lý địa chỉ nhận

GET/v1/webhooks

POST/v1/webhooks Body { "url": "https://…", "events": ["message.failed"] }. Trả về secret, chỉ hiện một lần. URL phải là địa chỉ https công khai; ZaPro không gửi tới localhost hay mạng nội bộ, và không đi theo chuyển hướng.

DELETE/v1/webhooks/{id}

Kiểm chữ ký

Mỗi lần gửi có header ZaPro-Signature: t=…,v1=…, trong đó v1 là HMAC-SHA256 của t + "." + body với secret của địa chỉ nhận. Luôn kiểm chữ ký trên body gốc, chưa parse JSON.

Node.js, không cần thư viện
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = Buffer.from(createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex"));
  const got = Buffer.from(parts.v1 ?? "");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300;
  if (got.length !== expected.length || !timingSafeEqual(got, expected) || !fresh) throw new Error("Chữ ký không hợp lệ");
  return JSON.parse(rawBody);
}

Thử nhận webhook ngay trên máy: thêm địa chỉ ở trang Webhooks, rồi gửi tin thử tới sandbox. API gốc: https://app.zapro.vn/v1/webhooks.