Runtime state propagation
See how billing signals become entitlement transitions, access decisions, runtime reads, and customer-facing propagation.
Stripe signal to runtime state
Runtime state in Licenzy is a propagation model, not a direct mirror of Stripe objects:
- 01Stripe emits a billing event.
- 02Licenzy processes it into entitlement state.
- 03Your backend reads that state through runtime access and entitlement endpoints.
- 04Licenzy can emit outbound events to propagate the resulting state elsewhere.
Event lifecycle matrix
Use this matrix as the operational map from trigger to runtime consequence. Outbound events listed here describe the typical runtime-facing event family. They are not a claim of global ordering or exactly-once delivery.
| Trigger | Source | Entitlement effect | Runtime access effect | Outbound event(s) | Important payload fields |
|---|---|---|---|---|---|
| checkout.session.completed | stripe | Creates or finalizes the entitlement for the purchased product. | Access can become available once entitlement state is active. | purchase.finalized | attempt_id, entitlement_id, amount_total, stripe_checkout_session_id |
| checkout.session.expired | stripe | Marks the unfinalized attempt failed and creates no entitlement. | No new runtime access is created. | No runtime outbound event should be assumed. | attempt_id if the sender includes checkout-attempt context |
| Manual grant | portal | Creates or activates entitlement state manually. | Access can become available immediately from runtime reads. | entitlement.updated | entitlement_id, actor_user_id, reason |
| Manual revoke | portal | Cancels or deactivates entitlement state manually. | Access can be denied immediately from runtime reads. | entitlement.updated | entitlement_id, actor_user_id, reason, canceled_at |
| Usage consume | runtime | Reduces usage_remaining on the active usage-pack entitlement. | Access remains available until usage is exhausted. | usage.consumed | entitlement_id, units, usage_remaining, reason |
| Full refund | stripe | Cancels the entitlement for time_pass or usage_pack. Usage packs also move usage_remaining to 0. | Access is revoked for the refunded entitlement. | entitlement.updated | entitlement_id, status, reason, canceled_at, usage_remaining |
| Partial refund | stripe | Recorded for billing history only. No entitlement mutation by itself. | No runtime access change by itself. | No runtime outbound event should be assumed. | amount_total if the sender includes billing context for the current event |
| invoice.payment_failed | stripe | Moves the subscription-backed runtime state into a non-healthy billing state when applicable. | Access can become unavailable if the resulting entitlement state is no longer active. | invoice.payment_failed | entitlement_id, stripe_subscription_id, current_period_end, reason |
| customer.subscription.deleted | stripe | Cancels the subscription-backed entitlement. | Access becomes unavailable when the canceled state takes effect. | subscription.deleted | entitlement_id, stripe_subscription_id, canceled_at, reason |
| Dispute created | stripe | Suspends subscription-backed runtime state conservatively as past_due. | Access can be denied while the dispute is open. | Typically subscription.updated when runtime state changes. | entitlement_id, stripe_subscription_id, status, reason |
| Dispute closed | stripe | Allows the subscription-backed entitlement to move into whatever state the current subscription lifecycle now supports. | Access follows the resulting entitlement state after the dispute closes. | Typically subscription.updated when runtime state changes. | entitlement_id, stripe_subscription_id, status, reason |
What can transition runtime state
- Checkout finalization and expiration.
- Subscription creation, renewal, failure, update, and deletion.
- Refund and dispute lifecycle changes.
- Manual portal grant, revoke, and usage adjustment.
- Runtime usage consumption for active usage-pack entitlements.
These inputs do not all originate from the same place, but they converge on the same runtime entitlement layer.
How consumers read and propagate state
POST /v1/access/checkgives your backend the smallest runtime decision.GET /v1/customer/access/:subject_refgives a richer runtime customer view.GET /v1/entitlements/:subject_refexposes the direct entitlement rows.- Outbound Licenzy webhooks propagate resulting runtime changes to your own systems.
If you are implementing the receiver side of that propagation, continue with outbound webhook delivery contract for retries, duplicate handling, and acknowledgement patterns. If you are debugging why state changed, compare this matrix with refund and dispute lifecycle and manual portal operations.