Webhooks
Subscribing to accounting events, the event types available, verifying deliveries, and building a receiver that survives retries and out-of-order delivery.
ReferenceFor Developers
Event types
| Event | Fires when |
|---|---|
| accounting.journal_entry.created | A journal entry posts. |
| accounting.journal_entry.updated | A journal entry record changes. |
| accounting.bill.created | A bill is created. |
| accounting.bill.updated | A bill changes. |
| accounting.invoice.created | An invoice is created. |
| accounting.invoice.updated | An invoice changes. |
| accounting.payment.created | A payment is recorded. |
| accounting.payment.updated | A payment changes. |
| accounting.bank_transaction.created | A bank transaction enters the feed. |
| accounting.bank_transaction.updated | A bank transaction changes, including on categorization. |
| accounting.reconciliation.updated | A reconciliation changes state. |
Building a receiver
- 1
Expose an HTTPS endpoint and register it as a subscription.
Subscribe only to the events you act on.
- 2
Verify the delivery before trusting it.
An endpoint that acts on any request that reaches it is an endpoint anyone can drive.
- 3
Return 2xx quickly, and do the work asynchronously.
A slow receiver causes timeouts, which cause retries, which cause duplicates.
- 4
Deduplicate on the event identifier.
Delivery is at-least-once. Assume you will occasionally see the same event twice.
- 5
Do not assume ordering.
An update can arrive before the create it relates to. Fetch current state from the API rather than reconstructing it from the event sequence.
- 6
Monitor the deliveries view.
Recent deliveries and their outcomes are visible in settings — the first place to look when an integration goes quiet.
Common questions
Failed deliveries are retried, and the deliveries view shows what happened to each one. For a long outage, reconcile by querying the API for the affected period rather than relying on retries alone.
Subscriptions are managed at the organization level; each event identifies the entity it belongs to, so filter in your receiver.
Fields that do not appear in your view — internal state, a provenance record — can change. Compare against what you hold rather than assuming every update is material to you.
Was this useful?

