Webhooks
Register HTTPS endpoints to receive signed event notifications. Manage endpoints
under Marketplace → Webhooks in the LedgerBee app, or via the API — the
Webhook Endpoints tag in the API Reference (create, list,
update, delete, roll-secret, and a test delivery; scopes
webhook-endpoints-read / webhook-endpoints-write).
Endpoint URLs must be public HTTPS — plain http and private/loopback
hosts are rejected at creation. Creating an endpoint returns a signing secret
of the form whsec_…, shown once; store it to verify every delivery.
Delivery envelope
Every delivery POSTs a JSON envelope — and the whole envelope is what gets signed:
Code
Signing — Standard Webhooks
Every delivery is signed following the Standard Webhooks specification. Each request carries three headers:
webhook-id— unique message id; matchesidin the bodywebhook-timestamp— send time in unix seconds (use it for a replay window; reject timestamps far outside your clock)webhook-signature—v1,<base64 HMAC-SHA256>over{id}.{timestamp}.{rawBody}(space-separated entries; verify against each)
Verifying a delivery
Do not hand-roll the HMAC check. Use one of the Standard Webhooks drop-in
libraries with the endpoint secret (returned once when you create the
endpoint or roll its secret). Verify against the raw request body — don't
re-serialize the parsed JSON; whitespace changes break the HMAC:
Code
Retries
A non-2xx response or a timeout is retried up to 8 total attempts over
roughly 21 hours, with exponential backoff (30s → 2m → 8m → 32m → ~2h →
~8.5h → 10h). Every retry carries the same webhook-id — but is
re-signed with the new send time, so verify against the headers of the
delivery you received, and deduplicate on webhook-id. Deliveries can arrive
out of order. After the schedule is exhausted the delivery is marked failed in
the endpoint's delivery log (Marketplace → Webhooks).
Reconciling subscription events
Every subscription.* event's data carries partnerReferenceId — the
clientReferenceId passed when binding an embedded checkout. It's your join
key: match the event to your own order without storing LedgerBee ids first. If a delivery is missed (endpoint down, not yet subscribed), recover
over the API instead of replaying:
GET /v1/subscriptions?partnerReferenceId=<yours> — see
Subscriptions.
Access-boundary subscription events carry entitlementIds so consumers can
apply the current product-entitlement union without a second lookup. Paused and
churned events carry an empty array for deterministic revocation. See Product
Entitlements for the grant and revoke contract.
A billing run can hold an invoice below your minimum invoice amount instead of
issuing it. The billing-held event reports the held periods, and the billed
event of the invoice that later carries them lists the same periods in its
heldPeriods array. See
Held billing periods.
Best practices
- Verify the signature before trusting the payload.
- Return
2xxquickly; do heavy work asynchronously. The response body is ignored. - Expect retries and rare duplicates — make handling idempotent on
webhook-id. - Store the
secretsecurely; roll it from Marketplace → Webhooks if exposed (deliveries re-sign with the new secret immediately). - Use the test delivery (UI button or
POST /v1/webhook-endpoints/{id}/test) to wire up verification before real traffic arrives.
Event types
Subscribe an endpoint to any of the topics below. Each delivery carries the topic string in the envelope type field and the topic-specific payload in data — see the delivery envelope for the wrapper.
Subscription
subscription.assigned
Fired when a subscription is assigned to a customer (may be future-dated / upcoming).
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer the subscription was assigned to. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
assignedAt | string (date-time) | ISO 8601 timestamp of when the subscription was assigned. |
subscription.started
Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
startedAt | string (date-time) | ISO 8601 timestamp of when the subscription became active. |
monthlyRevenue | string or null | What the subscription bills per month, as a decimal string, excluding VAT. Every billing interval is converted to one month (a quarter is divided by 3, half a year by 6, a year by 12, weekly prices are multiplied by 52/12), with plan discounts, interval discounts and recurring surcharges applied. One-off charges are not included, and neither are add-ons: each add-on is its own subscription with its own figure. Usage-based lines count only through a prepaid commitment or a fee their price charges at zero usage; read GET /v1/subscriptions/{id}/usage for the usage recorded so far. During a trial it is the price billing starts at. Null only when the subscription could not be priced. |
currency | string or null | Currency code (ISO 4217) of monthlyRevenue: the currency the subscription bills in. |
subscription.updated
Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction).
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
changedFields | string[] | Names of the subscription fields changed in this update. |
updatedAt | string (date-time) | ISO 8601 timestamp of when the update was applied. |
subscription.transitioned
Fired on a structural change: plan replace, product edit, billing cadence change, phase change, or realign.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
transitionType | plan_replaced | products_edited | billing_cadence_changed | billing_realigned | phase_changed | Which kind of structural change occurred. phase_changed is sent on the day a change made earlier takes effect, when it changes the entitlements or the monthly revenue. |
transitionedAt | string (date-time) | ISO 8601 timestamp of when the change was made. For a change scheduled for a later date this is before it takes effect; see effectiveDate. |
effectiveDate | string | The date (YYYY-MM-DD) the change takes effect. Later than transitionedAt when the change was scheduled; a phase_changed event follows on that date when the entitlements or the monthly revenue change. |
monthlyRevenue | string or null | What the subscription bills per month, as a decimal string, excluding VAT. Every billing interval is converted to one month (a quarter is divided by 3, half a year by 6, a year by 12, weekly prices are multiplied by 52/12), with plan discounts, interval discounts and recurring surcharges applied. One-off charges are not included, and neither are add-ons: each add-on is its own subscription with its own figure. Usage-based lines count only through a prepaid commitment or a fee their price charges at zero usage; read GET /v1/subscriptions/{id}/usage for the usage recorded so far. During a trial it is the price billing starts at. Null only when the subscription could not be priced. This is the figure the subscription bills from effectiveDate. |
currency | string or null | Currency code (ISO 4217) of monthlyRevenue: the currency the subscription bills in. |
subscription.paused
Fired when a subscription is paused.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
pausedAt | string (date-time) | ISO 8601 timestamp of when the subscription was paused. |
subscription.resumed
Fired when a subscription resumes from a pause.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
resumedAt | string (date-time) | ISO 8601 timestamp of when the subscription resumed. |
subscription.trial_ended
Fired when a subscription trial ends. The payload outcome says whether billing begins (ACTIVE) or the subscription was held for a missing payment card (PAUSED).
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
endedAt | string (date-time) | ISO 8601 timestamp of when the trial ended. |
outcome | ACTIVE | PAUSED | Status the subscription landed in when the trial ended: ACTIVE (billing begins) or PAUSED (held until a payment card is added). |
subscription.cancellation_scheduled
Fired when a future cancellation is scheduled for a subscription (still active until then).
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
effectiveDate | string (date-time) or null | When the cancellation takes effect, if known. |
scheduledAt | string (date-time) | ISO 8601 timestamp of when the cancellation was scheduled. |
subscription.cancellation_cleared
Fired when a previously scheduled cancellation is cleared.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
clearedAt | string (date-time) | ISO 8601 timestamp of when the scheduled cancellation was cleared. |
subscription.churned
Fired when a subscription is cancelled/finalized — revoke entitlement on this event.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owned the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
entitlementIds | string (uuid)[] | The full entitlement id set granted as of this event. An empty array means no access; consumers should re-sync instead of applying a diff. |
reason | string or null | Free-text cancellation reason, if one was supplied. |
churnedAt | string (date-time) | ISO 8601 timestamp of when the subscription was cancelled. |
mergedIntoSubscriptionId | string (uuid) or null | Set when this cancellation is one half of a subscription merge: the id of the surviving subscription that carries this subscription’s lines forward. Do NOT revoke entitlements on a merge churn — access continues on the surviving subscription. |
subscription.billed
Fired once per subscription that billed onto an invoice — one per child on a parent-paid consolidated invoice, one per member on a billing-group invoice. amount is always the whole document total; deduplicate on invoiceId, attribute on billingGroupId, never sum amount across events.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
billingGroupId | string (uuid) or null | Billing group whose shared invoice this event reports, or null. When set, every member of the group receives its own billed event for the same invoiceId, each carrying the whole document total — deduplicate on invoiceId. |
invoiceId | string (uuid) | Id of the invoice produced by the billing run. |
invoiceNumber | string | Human-facing invoice number. |
amount | string | Total invoice amount of the whole document, as a decimal string — NOT this subscription's share. On a shared invoice every subscription on it reports the same figure. |
currency | string | ISO 4217 currency code of the invoice. |
usageCommitment | object or null | Prepaid usage-commitment portion of the invoice. Null when the invoice carries no commitment lines. |
usageCommitment.committedAmount | string | Sum of the prepaid usage-commitment lines on this invoice, as a decimal string. Present only when usageCommitment is non-null. |
usageCommitment.trueUpAmount | string | Signed sum of the usage true-up (settlement) lines on this invoice, as a decimal string. Positive = overage billed, negative = underage refunded. Present only when usageCommitment is non-null. |
heldPeriods | object[] | Billing periods of this subscription that earlier runs held below the minimum invoice amount and this invoice now covers. Each one was reported by a subscription.billing_held event when it was held. Empty when none. |
billedAt | string (date-time) | ISO 8601 timestamp of when the invoice was produced. |
subscription.billing_held
Fired when a billing run holds an invoice instead of issuing it, because it is below the minimum invoice amount or below the smallest amount the subscription's card can be charged: nothing is invoiced or charged, and the held periods are added to the subscription's next invoice. One event per subscription with a period on the held invoice.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
billingGroupId | string (uuid) or null | Billing group whose shared invoice was held, or null. When set, every member with a period on the held invoice receives its own event. |
heldPeriods | object[] | The billing periods this hold kept off an invoice, for this subscription. They are added to the subscription's next invoice, where subscription.billed lists them again. |
heldAmount | string | What the held invoice came to including VAT, as a decimal string — the whole document, including periods held earlier that it would have carried. |
currency | string | ISO 4217 currency code of the held invoice. |
heldPeriodCount | integer | How many of the subscription's billing periods are on hold now, this hold's included. |
maxPeriodsOnOneInvoice | integer | The most billing periods one invoice covers for this subscription. The invoice that would cover this many is issued whatever it comes to. |
reason | below_minimum_invoice_amount | below_card_minimum | Why the invoice was held: below the seller's minimum invoice amount, or below the smallest amount the subscription’s card can be charged. |
minimumAmount | string | The minimum the invoice was below, as a decimal string. |
minimumCurrency | string | Currency of minimumAmount: the seller's accounting currency for the minimum invoice amount, the invoice's own for the card minimum. |
nextBillingDate | string | The date the subscription is billed next. The held periods are added to that invoice; if it is below the minimum too, it can be held again until the limit is reached. |
invoicedByDate | string | The latest billing date on which the held periods are invoiced whatever the total comes to: when the limit is reached, or the seller's financial year ends if that comes first. |
heldAt | string (date-time) | ISO 8601 timestamp of the billing run that held the invoice. |
subscription.payment_succeeded
Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal. On a billing-group card charge one event fires per member, each carrying the full charged amount and the shared billingGroupId.
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
billingGroupId | string (uuid) or null | Billing group whose card paid the invoice, or null when the subscription's own card did. When set, every member of the group receives its own payment_succeeded for the same invoiceId — deduplicate on invoiceId. |
invoiceId | string (uuid) | Id of the invoice the charge paid. |
invoiceNumber | string | Human-facing number of the invoice the charge paid. |
amount | string | Charged amount, as a decimal string — the whole invoice, NOT this subscription's share when the invoice is shared. |
currency | string | ISO 4217 currency code of the charge. |
paidThroughDate | string or null | The date the subscription is now paid through: the exclusive end of the latest service period covered by a settled invoice (equivalently, the first day not yet paid for). Null when no covered period exists, e.g. a one-off-only invoice. This is the paid-through marker — nextBillingDate is NOT: that says when the next invoice is created. |
occurredAt | string (date-time) | ISO 8601 timestamp of when the charge cleared. |
subscription.error
Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient).
| Field | Type | Description |
|---|---|---|
subscriptionId | string (uuid) | Stable id of the subscription (the chain head id, fixed at creation and unchanged across plan / direction / cadence changes and cancellation). Correlate events to a subscription on this id. |
versionId | string (uuid) | Internal version-chain row the event was emitted on. Advanced/debug only — it drifts across changes; correlate on subscriptionId or partnerReferenceId, not this. |
customerId | string (uuid) | Id of the customer that owns the subscription. |
partnerReferenceId | string or null | Your clientReferenceId from embedded checkout, echoed back for reconciliation. Null when none was set. |
errorType | recipient_undeliverable | charge_failed | dunning_exhausted | Which problem occurred — see the subscription.error sub-events table for the full set and meaning. |
message | string | Human-readable description of the problem. |
occurredAt | string (date-time) | ISO 8601 timestamp of when the problem occurred. |
The errorType field discriminates which problem occurred — it is one of:
errorType | Meaning |
|---|---|
recipient_undeliverable | A document recipient for the subscription is undeliverable (e.g. the email hard-bounced); the document was not delivered. |
charge_failed | A card charge (first or recurring) for the subscription failed. Automatic retries continue across the grace window, and this fires on each decline. The raw provider decline is not exposed on the payload. |
dunning_exhausted | Automatic card-charge retries for the subscription are exhausted after the grace window; no further automatic attempts will be made and the outstanding invoice becomes collectible. Fires once per subscription, distinct from the per-decline charge_failed — a billing group emits one per member, each naming that member, so "once per subscription" holds on both rails. |
Billing
billing.invoice_sent
Fired when an invoice document is sent to the customer.
| Field | Type | Description |
|---|---|---|
invoiceId | string (uuid) | Id of the invoice that was sent. |
invoiceNumber | string | Human-facing invoice number. |
customerId | string (uuid) | Id of the customer the invoice was sent to. |
subscriptionId | string (uuid) or null | Subscription the invoice relates to, or null when the document is not a single subscription's — a billing-group invoice (see billingGroupId), a parent-paid consolidated invoice, or a manually created one. |
billingGroupId | string (uuid) or null | Billing group the invoice is issued to, or null. A group's shared invoice names the group and never a subscription, so subscriptionId is null whenever this is set. |
amount | string | Total invoice amount, as a decimal string. |
currency | string | ISO 4217 currency code of the invoice. |
sentAt | string (date-time) | ISO 8601 timestamp of when the invoice was sent. |
billing.credit_note_sent
Fired when a credit note document is sent to the customer.
| Field | Type | Description |
|---|---|---|
creditNoteId | string (uuid) | Id of the credit note that was sent. |
creditNoteNumber | string | Human-facing credit note number. |
customerId | string (uuid) | Id of the customer the credit note was sent to. |
subscriptionId | string (uuid) or null | Subscription the credit note relates to, or null when the document is not a single subscription's — a billing-group credit note (see billingGroupId), a parent-paid consolidated one, or a manually created one. |
billingGroupId | string (uuid) or null | Billing group the credit note is issued to, or null. A group's credit note names the group and never a subscription, so subscriptionId is null whenever this is set. |
amount | string | Total credit note amount, as a decimal string. |
currency | string | ISO 4217 currency code of the credit note. |
heldPeriods | object[] | Billing periods held below the minimum invoice amount that this credit note settles: a held period goes out on a credit note when the document it rides nets negative. Empty when none. |
sentAt | string (date-time) | ISO 8601 timestamp of when the credit note was sent. |
billing.invoice_updated
Fired when an invoice is changed, in the app or through the API alike: its fields, its lines or their order, or its status. A draft scheduled or cancelled fires it, and so does an invoice reaching sent once it is delivered, beside billing.invoice_sent. A save that changes nothing fires nothing; changedFields names what moved.
| Field | Type | Description |
|---|---|---|
invoiceId | string (uuid) | Id of the invoice that changed. |
invoiceNumber | string or null | Human-facing invoice number, or null while none has been assigned (a draft gets its number when sent). |
customerId | string (uuid) or null | Id of the customer the invoice is for after the change, or null when none. |
status | string | The invoice's status after the change, e.g. draft, scheduled or cancelled. |
subtotal | string | Invoice total before VAT after the change, as a decimal string. |
vat | string | VAT on the invoice after the change, as a decimal string. |
amount | string | Invoice total including VAT after the change, as a decimal string. |
currency | string | ISO 4217 currency code of the invoice after the change. |
changedFields | (customerId | customerDepartmentId | customerContactId | eanNumber | date | dueDate | paymentTerms | paymentTermType | currency | reference | ourReference | description | notes | subject | tagIds | lines | subtotal | vat | amount | status | invoiceNumber | externalId | scheduledSendAt | recipientContactIds | additionalEmails | allowedPaymentProviders | paymentDetailId | hideBankDetails | hideFik | cashPaymentAccountId | reminderConfigId)[] | Names of the fields the change altered. lines means a line was added, removed or changed; subtotal, vat and amount are listed when the totals moved. A save that changes nothing sends no event. |
updatedAt | string (date-time) | ISO 8601 timestamp of when the change was saved. |
billing.invoice_deleted
Fired when a draft invoice is deleted, in the app or through the API alike. Only drafts can be deleted; a sent invoice is corrected with a credit note instead.
| Field | Type | Description |
|---|---|---|
invoiceId | string (uuid) | Id of the deleted invoice. It no longer exists in LedgerBee. |
invoiceNumber | string or null | Human-facing invoice number, or null while none has been assigned (a draft gets its number when sent). |
customerId | string (uuid) or null | Id of the customer the invoice was for, or null when none. |
deletedAt | string (date-time) | ISO 8601 timestamp of when the invoice was deleted. |
billing.invoice_paid
Fired when a customer invoice becomes paid in full: by payments, by a settlement, or by a credit note applied to it. Only the invoice fires it — the credit note it was settled against does not, and neither does a reminder fee or an advance. A partial payment fires nothing. An invoice reopened (a payment reverted) and paid again fires again. Invoices brought in by an import do not fire it.
| Field | Type | Description |
|---|---|---|
invoiceId | string (uuid) or null | Id of the paid invoice, or null for an invoice booked without an invoice document in LedgerBee (a sales voucher entered as a journal entry). Identify those by invoiceNumber and customerId. |
invoiceNumber | string or null | Human-facing invoice number, or null when the booking carries none. |
customerId | string (uuid) | Id of the customer who owed the invoice. |
customerName | string or null | The customer's name as it stands when the invoice became paid, or null when the customer is gone. |
originalAmount | string | Invoice total in the invoice's own currency (originalCurrency), as a decimal string. |
originalCurrency | string | ISO 4217 currency code the invoice was issued in. |
baseCurrencyAmount | string | Invoice total in the company's own currency (baseCurrency), as a decimal string. |
baseCurrency | string | ISO 4217 code of the company's own currency, the one its books are kept in. |
settledDate | string | The day the invoice became paid (YYYY-MM-DD): the date of the payment, settlement or credit note that covered the last of it. |
dueDate | string or null | The day the invoice was due (YYYY-MM-DD), or null when it has none. |
Customer
customer.created
Fired when a customer is created (payload flags whether it was a portal self-signup).
| Field | Type | Description |
|---|---|---|
customerId | string (uuid) | Id of the created customer. |
selfSignup | boolean | True when the customer was created via portal self-signup; false for operator/API/import creation. |
partnerReferenceId | string or null | Your own order/cart id, echoed from the checkout-vouch token that created this customer. Non-null only on a partner-vouched checkout; null for every other creation path. Use it to map the customer back to the order in your system — the same identifier the subscription webhooks carry. |
createdAt | string (date-time) | ISO 8601 timestamp of when the customer was created. |
Card
card.added
Fired when a card is successfully saved for a customer (provider-opaque).
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the saved card (LedgerBee CustomerPaymentMethod id). |
customerId | string (uuid) | Id of the customer the card was saved for. |
cardMask | string or null | Masked card number, if known. |
cardType | string or null | Card network/brand, if known — never the payment provider. |
expiryMonth | integer or null | Card expiry month (1–12), if known. |
expiryYear | integer or null | Card expiry year (4-digit), if known. |
isDefault | boolean | True when this card is the customer’s default after being saved. |
addedAt | string (date-time) | ISO 8601 timestamp of when the card was saved. |
card.removed
Fired when a saved card is removed in-app or cancelled at the provider.
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the removed card. |
customerId | string (uuid) | Id of the customer the card belonged to. |
cardMask | string or null | Masked card number, if known. |
cardType | string or null | Card network/brand, if known. |
reason | removed_by_customer | removed_by_provider | Why the card was removed: removed_by_customer = removed in-app (portal/operator); removed_by_provider = cancelled out-of-band at the provider. |
removedAt | string (date-time) | ISO 8601 timestamp of when the card was removed. |
card.updated
Fired when a saved card’s details change (network auto-update or refresh).
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the updated card. |
customerId | string (uuid) | Id of the customer that owns the card. |
cardMask | string or null | Masked card number after the update, if known. |
cardType | string or null | Card network/brand after the update, if known. |
expiryMonth | integer or null | Card expiry month (1–12) after the update, if known. |
expiryYear | integer or null | Card expiry year (4-digit) after the update, if known. |
isDefault | boolean | Whether this card is the customer’s default. |
changedFields | string[] | Names of the card fields that changed in this update. |
updatedAt | string (date-time) | ISO 8601 timestamp of when the update was applied. |
card.expiring
Fired when a saved card is approaching expiry.
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the expiring card. |
customerId | string (uuid) | Id of the customer that owns the card. |
cardMask | string or null | Masked card number, if known. |
cardType | string or null | Card network/brand, if known. |
expiryMonth | integer or null | Card expiry month (1–12), if known. |
expiryYear | integer or null | Card expiry year (4-digit), if known. |
signaledAt | string (date-time) | ISO 8601 timestamp of when the expiry signal was raised. |
card.expired
Fired when a saved card is observed to have expired.
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the expired card. |
customerId | string (uuid) | Id of the customer that owns the card. |
cardMask | string or null | Masked card number, if known. |
cardType | string or null | Card network/brand, if known. |
expiryMonth | integer or null | Card expiry month (1–12), if known. |
expiryYear | integer or null | Card expiry year (4-digit), if known. |
expiredAt | string (date-time) | ISO 8601 timestamp of when the card was observed expired. |
card.default_changed
Fired when the customer’s default card changes (explicit or auto-default).
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) | Id of the card that is now the customer’s default. |
customerId | string (uuid) | Id of the customer whose default card changed. |
previousDefaultCardId | string (uuid) or null | Id of the card that was previously default, or null if the customer had no default before. |
changedAt | string (date-time) | ISO 8601 timestamp of when the default changed. |
card.backup_changed
Fired when the customer’s designated backup card is set, replaced, or cleared.
| Field | Type | Description |
|---|---|---|
cardId | string (uuid) or null | Id of the card that is now the customer’s designated backup, or null when the designation was cleared. |
customerId | string (uuid) | Id of the customer whose backup card changed. |
previousBackupCardId | string (uuid) or null | Id of the card that was previously the backup, or null if the customer had no backup before. |
changedAt | string (date-time) | ISO 8601 timestamp of when the backup designation changed. |
card.add_failed
Fired when a card-save attempt fails (decline or authentication failure).
| Field | Type | Description |
|---|---|---|
customerId | string (uuid) | Id of the customer the failed card-save was for. |
reason | string | Machine/short reason for the failure (decline or authentication failure). |
failedAt | string (date-time) | ISO 8601 timestamp of when the card-save attempt failed. |
Quote
quote.sent
Fired when a quote is sent to the customer.
| Field | Type | Description |
|---|---|---|
quoteId | string (uuid) | Id of the quote that was sent. |
quoteNumber | string or null | Human-facing quote number (allocated on send). |
customerId | string (uuid) | Id of the customer the quote was sent to. |
sentAt | string (date-time) | ISO 8601 timestamp of when the quote was sent. |
quote.converted
Fired when a quote is converted into an order confirmation or an invoice.
| Field | Type | Description |
|---|---|---|
quoteId | string (uuid) | Id of the quote that was converted. |
quoteNumber | string or null | Human-facing quote number. |
targetType | invoice | orderConfirmation | What the quote was converted into. |
targetId | string (uuid) | Id of the document the conversion produced (an invoice or order confirmation). |
customerId | string (uuid) | Id of the customer the documents belong to. |
convertedAt | string (date-time) | ISO 8601 timestamp of when the conversion happened. |
Order confirmation
order_confirmation.sent
Fired when an order confirmation is sent to the customer.
| Field | Type | Description |
|---|---|---|
orderConfirmationId | string (uuid) | Id of the order confirmation that was sent. |
orderConfirmationNumber | string or null | Human-facing order confirmation number (allocated on send). |
customerId | string (uuid) | Id of the customer the order confirmation was sent to. |
sentAt | string (date-time) | ISO 8601 timestamp of when the order confirmation was sent. |
order_confirmation.converted
Fired when an order confirmation is converted into an invoice.
| Field | Type | Description |
|---|---|---|
orderConfirmationId | string (uuid) | Id of the order confirmation that was converted. |
orderConfirmationNumber | string or null | Human-facing order confirmation number. |
targetType | invoice | Order confirmations only ever convert into an invoice. |
targetId | string (uuid) | Id of the invoice the conversion produced. |
customerId | string (uuid) | Id of the customer the documents belong to. |
convertedAt | string (date-time) | ISO 8601 timestamp of when the conversion happened. |
Project
project.created
Fired when a project is created (payload carries the owned dimension id for correlation with the dimensions API).
| Field | Type | Description |
|---|---|---|
projectId | string (uuid) | Id of the created project. |
name | string | Project name at creation time. |
dimensionId | string (uuid) | Id of the dimension the project owns; usable with the dimensions API. |
externalReference | string or null | Partner-supplied external reference, null when not set. |
createdAt | string (date-time) | ISO 8601 timestamp of when the project was created. |
project.updated
Fired when a project's fields are updated (payload lists the changed field names). Also fires on un-archive.
| Field | Type | Description |
|---|---|---|
projectId | string (uuid) | Id of the updated project. |
changedFields | string[] | Names of the project fields the update changed. |
updatedAt | string (date-time) | ISO 8601 timestamp of the update. |
project.archived
Fired when a project is archived (its dimension is deactivated; postings history is preserved).
| Field | Type | Description |
|---|---|---|
projectId | string (uuid) | Id of the archived project. |
archivedAt | string (date-time) | ISO 8601 timestamp of the archive action. |
Checkout
checkout.card_ready
Fired when the buyer's card lands on a checkout session's card window — confirm may proceed. The card-status poll remains authoritative.
| Field | Type | Description |
|---|---|---|
sessionId | string | The checkout session id — the same opaque id your backend received from the session mint. |
clientReferenceId | string or null | Your own reference from the session mint; null when none was supplied. |
planVersionId | string (uuid) | The plan version the session pinned. |
planItemId | string (uuid) | The pricing-card item the session pinned. |
card | object or null | The captured card to display to the buyer; null when the provider returned no display details. |
card.label | string | Ready-to-render card label. Present only when card is non-null. |
card.cardType | string or null | Card network/brand, if known — never the payment provider. Present only when card is non-null. |
card.cardMask | string or null | Masked card number, if known. Present only when card is non-null. |
card.accountIdentifier | string or null | Masked account identifier for non-card methods (e.g. a Link email); null for plain cards. Present only when card is non-null. |
checkout.card_failed
Fired when a checkout card window closes without a card (the provider window expired mid-capture) — open a fresh window to retry.
| Field | Type | Description |
|---|---|---|
sessionId | string | The checkout session id — the same opaque id your backend received from the session mint. |
clientReferenceId | string or null | Your own reference from the session mint; null when none was supplied. |
planVersionId | string (uuid) | The plan version the session pinned. |
planItemId | string (uuid) | The pricing-card item the session pinned. |
reason | WINDOW_EXPIRED | Why the card capture failed. WINDOW_EXPIRED: the provider window lapsed without a card landing. |
checkout.session_expired
Fired when a checkout session expires unconsumed — the abandoned-checkout signal.
| Field | Type | Description |
|---|---|---|
sessionId | string | The checkout session id — the same opaque id your backend received from the session mint. |
clientReferenceId | string or null | Your own reference from the session mint; null when none was supplied. |
planVersionId | string (uuid) | The plan version the session pinned. |
planItemId | string (uuid) | The pricing-card item the session pinned. |
Stock
stock.balance_changed
Fired for every stock movement that changes sellable stock, carrying the position's on-hand after it — the signal a sales channel republishes availability on.
| Field | Type | Description |
|---|---|---|
productId | string (uuid) | The product whose on-hand changed. |
warehouseId | string (uuid) or null | The warehouse the change happened in; null for a movement outside every warehouse. |
locationId | string (uuid) or null | The bin within that warehouse, when the position names one. |
onHand | string | Sellable on-hand after the movement, at the stock ledger's own scale. Only stock whose quality status is AVAILABLE is counted, so a movement touching quarantined or damaged stock alone fires nothing. |
movementId | string (uuid) | The movement that changed it — the idempotency key for this event. |
occurredAt | string (date-time) | When the movement happened (ISO 8601). |
shipment.dispatched
Fired when a shipment leaves the warehouse and its cost of goods sold posts.
| Field | Type | Description |
|---|---|---|
shipmentId | string (uuid) | |
shipmentNo | string or null | The document number, allocated at dispatch. |
warehouseId | string (uuid) | |
customerId | string (uuid) or null | |
dispatchedAt | string (date-time) | When the goods left (ISO 8601). |
shipment.cancelled
Fired when a DISPATCHED shipment is cancelled and its posting unwound. Cancelling a draft moves nothing and fires nothing.
| Field | Type | Description |
|---|---|---|
shipmentId | string (uuid) | |
shipmentNo | string or null | |
warehouseId | string (uuid) | |
customerId | string (uuid) or null | |
wasDispatched | true | Always true — the event fires on an unwound dispatch, and a cancelled draft publishes nothing. |
Flow
flow.tap
Fired when a flow tap this endpoint is named on fires: once per document, carrying the tap id, the optional subject and body the tap was written with, and the object the step declares for that outcome when the tap attaches it (otherwise null). Subscribing makes the endpoint available to taps; it receives only the taps that name it.
| Field | Type | Description |
|---|---|---|
tapId | string (uuid) | The tap that fired; stable across every delivery it produces. |
subject | string or null | The subject line the tap's author wrote; null when they wrote none. |
body | string or null | The body the tap's author wrote, verbatim; null when they wrote none. |
payload | object or null | The object the step handed over when the subject left it (for a new supplier, the supplier as it was classified), when the tap attaches it; otherwise null. |
Agent
agent.message
Fired when an agent's Post block that names this endpoint posts: once per message that reaches the block, carrying the agent, the run, the post's title and text, and the message's structured content. Subscribing makes the endpoint available to Post blocks; it receives only the posts of the blocks that name it.
| Field | Type | Description |
|---|---|---|
routineId | string (uuid) | The agent that posted; stable across every post it makes. |
agentName | string | The agent's name when it posted. |
runId | string (uuid) | The run that posted. One run posts once per message that reaches the block. |
nodeId | string | The Post block on the agent that posted, so an agent with several can be told apart. |
topic | string or null | The topic the message carried when it reached the block, or null when it carried none. |
title | string | The post's title: the message's topic, else the block's own title, else the agent's name. |
text | string | The post's text, as plain text: the block's own text with its variables filled in, else everything that arrived. A table is written out as lines of text. |
data | any or null | The structured content the message carried: for a Hivey block's answer, an object whose tables field lists each table with its title, columns and rows; for an Event block's message, an object with the events it passed on (and dropped, how many older ones were left out); for a value a Change block set, that value (plain text a Change block set arrives as the text, with null data); for a message that joined several, an array of each one's data. Null for plain text or nothing. |