vsmsconnect — API — xero-webhook

← all endpoints

POST/webhooks/xero auth: hmac (x-xero-signature)

Xero-initiated webhook delivery. Verifies HMAC-SHA256 over the raw request body using `XERO_WEBHOOK_SIGNING_KEY` (constant-time compared to the base64 `x-xero-signature` header). Valid signature → fan each event to the `xero:webhook:events` Redis Stream and respond `200` within Xero's 5-second ack budget. Xero's intent-to-receive handshake (`events: []`) flows through the same code path. NOT mounted under `/api/v1`.

handlers: XeroWebhookController.handle

Inputs

namerequireddefaultdescription
x-xero-signature header
string
yes—Base64-encoded HMAC-SHA256 of the raw request body.
events body
XeroWebhookEvent[]
no—Array of event objects (`tenantId`, `tenantType`, `eventCategory`, `eventType`, `resourceId`, `resourceUrl`, `eventDateUtc`, `eventSequence`). Empty array is the intent-to-receive ping.
firstEventSequence body
integer
no—Sequence number of the first event in the batch.
lastEventSequence body
integer
no—Sequence number of the last event in the batch.
entropy body
string
no—Random salt included by Xero.

Outputs

200
empty
Valid signature — events XADDed to Redis Stream, empty body.
401
APIError
XERO_WEBHOOK_SIGNATURE_INVALID — HMAC mismatch.
503
APIError
XERO_WEBHOOK_NOT_CONFIGURED — `XERO_WEBHOOK_SIGNING_KEY` is unset (dev safe default).