Developer
Webhooks
Signed, retried, logged deliveries for every event that matters.
When something happens in a business — an invoice is posted, money comes in, a customer is added — Trabalance writes the event in the same database transaction as the fact itself, then delivers it to every subscriber with a signed HTTP POST. An event can never exist without its fact, nor a fact without its event.
Two kinds of subscriber
| Subscriber | Set up where | Signed with |
|---|---|---|
| A business's own endpoint | Settings → API keys & webhooks → Add endpoint (HTTPS URL + events). Secret shown once. | The endpoint's `whsec_…` secret |
| Your OAuth app | Developer portal → app → Webhooks (events) and Settings (webhook URL). Delivered for every business that authorised the app and still holds a live token. | The app's webhook signing secret |
1
Receive
A
POST with Content-Type: application/json and the headers below. Read the raw body before parsing.2
Verify
Check
Trabalance-Signature — see Signature verification.3
Answer 2xx within 10 seconds
Do slow work after responding. Anything else is retried — see Retry logic.
4
Be idempotent
A delivery can arrive more than once (a timeout on our side after you processed it). Use
Trabalance-Event-Id to deduplicate.Headers
| Header | Value |
|---|---|
| Trabalance-Event | The event type, e.g. `invoice.created` |
| Trabalance-Event-Id | UUID of the event — stable across retries and redeliveries |
| Trabalance-Delivery-Id | UUID of this attempt |
| Trabalance-Signature | `t=<unix seconds>,v1=<hex HMAC-SHA256>` |
| Trabalance-Redelivery | `true` when a human re-sent it from the delivery log |
| User-Agent | `Trabalance-Webhooks/1.0` |
ℹ️Test it
Every endpoint in Settings has Send test — it emits a real ping event through the same pipeline, so what you see in the delivery log is exactly what production will do.