Webhooks
Receive AccountingKit events and configure Xero callbacks.
Customer webhooks
Register an HTTPS destination through POST /v1/webhook-endpoints with one or more event types:
connection.createdconnection.updatedconnection.disconnectedsync.completedinvoice.updatedinvoice.payment_changedinvoice.paidautomation.succeededautomation.failed
The response includes a signing secret once. Store it in your secret manager.
Deliveries include the event ID, event type, creation time, environment, and data. Verify the HMAC signature against the exact raw request body before parsing JSON. Deduplicate on event ID and return a successful response quickly; webhook delivery is retried as a durable operation.
The signature is sent in AccountingKit-Signature as t=<unix-seconds>,v1=<hex-hmac>. The signed
message is <timestamp>.<exact-raw-body>. AccountingKit-Event carries the event ID. The Node SDK
provides constructWebhookEvent(rawBody, signature, signingSecret), which performs constant-time
signature comparison, rejects payloads outside a five-minute replay window, and validates the event
envelope before returning it.
Xero webhooks
For a customer-owned Xero app, configure the callback URL shown in the console:
POST /webhooks/xero/{provider_app_id}The opaque path identifies the registered app, allowing AccountingKit to load its encrypted webhook
key before parsing or trusting the request body. The hosted trial app retains POST /webhooks/xero.
Both routes validate X-Xero-Signature before persisting any event. The receiver stores the minimal
parsed event and its operation/outbox record in one transaction; it never stores the raw webhook
body and acknowledges without waiting for a Xero API call.
Invoice events enqueue a targeted live invoice read and emit invoice.updated with a constrained,
provider-neutral payment snapshot. When the live amount paid, amount due, or status differs from the
previously cached invoice, AccountingKit also emits invoice.payment_changed. A transition from any
non-paid state to paid emits invoice.paid. Consumers can therefore update operational paid fields
and alerts without guessing from the original Xero notification. Other supported Xero categories
currently enqueue a full connection sync. The webhook payload is a change notification; the
subsequent Xero read remains the source of truth. Event IDs, sequence cursors, and gaps are scoped
to the Xero app. A gap queues reconciliation only for active connections created with that app.
The same invoice pipeline runs on a configurable 15-minute safety-net schedule and through
POST /v1/connections/:connection_id/sync. This catches provider events that never arrived while
preserving the same event identity, payment state comparison, signed delivery, and PDF refresh
contract.
Every invoice event includes document.refresh_required, the invoice.download_pdf provider
action, both AccountingKit and Xero invoice IDs, and a provider revision. Consumers that cache a
rendered invoice must replace that snapshot before presenting or sending it; the original PDF is not
a timeless representation of a mutable Xero invoice.
Delivery operations
Each outbound delivery has persisted attempts, response status, response body excerpt, next attempt, and terminal state. Operators can correlate a delivery with its operation and request ID without exposing signing secrets or accounting payloads in logs.
After correcting the destination, requeue a terminal delivery with
POST /v1/webhook-deliveries/:delivery_id/replay, an Idempotency-Key, and a non-empty reason.
The original delivery and attempt history remain intact.