# Webhooks & reconciliation

Subscribe to subscription events to react to lifecycle changes and reconcile
them against your own records. See [Webhooks](/guides/webhooks) for endpoint
setup, the signed-envelope format, signature verification, and retries; this page
covers the subscription topics and how to reconcile them.

## Topics

{/* @codegen webhook-topics-subscription — generated by `pnpm docs:generate`; do not edit by hand */}

| Topic | Fires when |
|---|---|
| `subscription.assigned` | Fired when a subscription is assigned to a customer (may be future-dated / upcoming). |
| `subscription.started` | Fired when a subscription becomes active — grant entitlement/access on this event, not on assigned. |
| `subscription.updated` | Fired when a config property changes without a structural transition (e.g. name, payment method, billing direction). |
| `subscription.transitioned` | Fired on a structural change: plan replace, product edit, billing cadence change, or realign. |
| `subscription.paused` | Fired when a subscription is paused. |
| `subscription.resumed` | Fired when a subscription resumes from a pause. |
| `subscription.trial_ended` | Fired when a subscription trial ends and normal billing begins (the sub stays active). |
| `subscription.cancellation_scheduled` | Fired when a future cancellation is scheduled for a subscription (still active until then). |
| `subscription.cancellation_cleared` | Fired when a previously scheduled cancellation is cleared. |
| `subscription.churned` | Fired when a subscription is cancelled/finalized — revoke entitlement on this event. |
| `subscription.billed` | Fired once per (child) subscription when a billing run produces its invoice. |
| `subscription.payment_succeeded` | Fired when a card charge for the subscription clears — the success pair of the charge_failed error signal. |
| `subscription.error` | Fired when a delivery/processing problem occurs for a subscription (e.g. undeliverable recipient). |

{/* @codegen-end webhook-topics-subscription */}

## `subscription.error`

The `subscription.error` topic reports a billing problem rather than a lifecycle
change.

{/* @codegen subscription-error-types — generated by `pnpm docs:generate`; do not edit by hand */}

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; the subscription is moved to AWAITING_PAYMENT so you can gate access. The raw provider decline is not exposed on the payload. |

{/* @codegen-end subscription-error-types */}

## Reconcile on the stable id

Every `subscription.*` event carries the stable id as `data.subscriptionId`, plus
`data.partnerReferenceId` and a diagnostics-only `data.versionId`. **Reconcile on
`subscriptionId` or `partnerReferenceId`, never `versionId`** — the version id
changes on every structural change (see
[Data model](/guides/subscriptions/data-model#versionid-is-for-diagnostics-only)).

`partnerReferenceId` is the `clientReferenceId` you pass when binding an
[embedded checkout](/guides/embedded-checkout/customer-binding) — your join key
for matching a subscription to your own order.

## Recover a lost event

If a delivery is lost, recover the join over the API by your own reference:

```bash
curl "https://api.ledgerbee.com/api/v1/subscriptions?partnerReferenceId=order_42" \
  -H "x-api-key: YOUR_API_KEY"
```
