Cách Xero gửi webhook

Xero cần nhận 200 trong 5 giây, không kèm body, và 401 cho chữ ký sai, rồi mới bật webhook. Định dạng đã kiểm chứng và code xác minh Node.

Hành vi gửi

Lấy từ tài liệu của chính hãng, kiểm tra lần cuối 2026-08-06. Hãng không nêu con số nào thì bảng này cũng không ghi.

Thời hạn phản hồi5 giây

Trả về 200 trong vòng 5 giây, không kèm body hay cookie; trả về 401 khi chữ ký sai

Kiểm tra handler của bạn có phản hồi kịp không

Thử lạihãng không công bố
Ngừng gửihãng không công bố
Nguồnhttps://developer.xero.com/documentation/guides/webhooks/configuring-your-server/

Chữ ký

Kiểm chứng bằng một bộ xác minh chạy thật, có bộ test chứng minh, chứ không đọc từ tài liệu. Kiểm chứng lần cuối 2026-08-20.

Thuật toánHMAC-SHA256
Payload được kýraw body
Encodingbase64
Headerx-xero-signature = base64
Dung saikhông quy định

Xác minh

Dùng raw body của request, đúng từng byte, trước mọi bước parse JSON. Mọi cơ chế trên trang này đều hỏng ngay khi framework serialize lại payload.

const crypto = require("node:crypto");

// base64(HMAC-SHA256(webhooks key, raw body))
const expected = crypto
  .createHmac("sha256", webhooksKey) // developer.xero.com → My Apps → Webhooks
  .update(rawBody)
  .digest("base64");
const received = Buffer.from(req.headers["x-xero-signature"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);
// Intent to Receive needs both answers: 200 (empty body) when valid, 401 when not.

Những chỗ dễ vấp

Webhook vẫn tắt cho tới khi vượt qua bước Intent to Receive: Xero gửi một lượt ký đúng và một lượt cố tình ký sai, rồi chờ 200 cho lượt đầu và 401 cho lượt sau. Endpoint nào trả 200 cho mọi thứ sẽ không bao giờ được bật. Khi App dùng nguồn Xero và đã đặt webhooks key, AnyHook tự trả lời cả hai lượt và không lưu lượt nào.

Mỗi lượt gửi là một batch con trỏ, không phải bản ghi: mỗi sự kiện nêu một danh mục, một loại và một resourceUrl để bạn lấy dữ liệu bằng một lệnh gọi có xác thực. AnyHook đặt tên sự kiện theo sự kiện đầu tiên trong batch (invoice.update), để bộ lọc và nhật ký sự kiện đọc cùng một tên.

Đọc thêm

AnyHook đứng trước các endpoint nhận webhook từ Xero: trả lời sau khoảng 1 giây, tự thử lại theo lịch riêng khi server của bạn ngừng hoạt động, và giữ mọi sự kiện để bạn phát lại được. Đổi một URL, giữ nguyên code.

Cách hoạt động →