Event Architecture

Runtime state propagation

See how billing signals become entitlement transitions, access decisions, runtime reads, and customer-facing propagation.

Start free in test mode. Go live when you're ready.

Category: Event Architecture4 sections

Stripe signal to runtime state

Runtime state in Licenzy is a propagation model, not a direct mirror of Stripe objects:

  1. Stripe emits a billing event.
  2. Licenzy processes it into entitlement state.
  3. Your backend reads that state through runtime access and entitlement endpoints.
  4. Licenzy 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.

TriggerSourceEntitlement effectRuntime access effectOutbound event(s)Important payload fields
checkout.session.completedstripeCreates or finalizes the entitlement for the purchased product.Access can become available once entitlement state is active.purchase.finalizedattempt_id, entitlement_id, amount_total, stripe_checkout_session_id
checkout.session.expiredstripeMarks 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 grantportalCreates or activates entitlement state manually.Access can become available immediately from runtime reads.entitlement.updatedentitlement_id, actor_user_id, reason
Manual revokeportalCancels or deactivates entitlement state manually.Access can be denied immediately from runtime reads.entitlement.updatedentitlement_id, actor_user_id, reason, canceled_at
Usage consumeruntimeReduces usage_remaining on the active usage-pack entitlement.Access remains available until usage is exhausted.usage.consumedentitlement_id, units, usage_remaining, reason
Full refundstripeCancels the entitlement for time_pass or usage_pack. Usage packs also move usage_remaining to 0.Access is revoked for the refunded entitlement.entitlement.updatedentitlement_id, status, reason, canceled_at, usage_remaining
Partial refundstripeRecorded 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_failedstripeMoves 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_failedentitlement_id, stripe_subscription_id, current_period_end, reason
customer.subscription.deletedstripeCancels the subscription-backed entitlement.Access becomes unavailable when the canceled state takes effect.subscription.deletedentitlement_id, stripe_subscription_id, canceled_at, reason
Dispute createdstripeSuspends 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 closedstripeAllows 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/check gives your backend the smallest runtime decision.
  • GET /v1/customer/access/:subject_ref gives a richer runtime customer view.
  • GET /v1/entitlements/:subject_ref exposes 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.