Skip to content
Products & subscriptionsWebhooks

Subscription webhooks

Subscriptions send webhook events for every lifecycle transition, so your backend can stay in sync without polling. This page lists the subscription-specific events and their payload shape.

For how to register webhook endpoints, verify signatures, and handle live/test mode, see Webhooks and Get started with webhooks — subscription events use the exact same Event envelope and delivery mechanism as order, refund, dispute, and redemption events.

Amount format: Monetary values in webhook payloads are expressed in the smallest minor unit of each currency. See Supported currencies.

Example event payload

The following example shows the event sent when a subscription successfully renews.

json
{
  "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
  "object": "subscription.renewed",
  "createdAt": "2026-07-01T00:00:00Z",
  "test": false,
  "eventData": {
    "type": "subscription",
    "version": "v2",
    "data": {
      "subscription": {
        "id": "subscription_1p4LS47fB1h",
        "object": "subscription",
        "status": "active",
        "test": false,
        "items": [
          {
            "id": "item_1p4LS47fB1i",
            "detail": {
              "product": {
                "price": { "amount": 1000, "currency": "USD" },
                "quantity": 1,
                "label": "Pro Plan (Monthly)",
                "images": ["https://example.com/pro-plan.png"]
              }
            }
          }
        ],
        "interval": { "unit": "MONTH", "count": 1 },
        "currentBillingPeriodEnd": "2026-08-01T00:00:00Z",
        "createdAt": "2026-06-01T00:00:00Z",
        "updatedAt": "2026-07-01T00:00:00Z"
      }
    }
  }
}

The payload always contains the full, current state of the subscription at the time of the event (not a diff). Use the top-level id for delivery tracing and idempotency, and eventData.data.subscription.id to correlate the event with your own records.

Types of events

subscription.trial_started
The consumer provided a card and started the subscription's trial period. The subscription is now trialing.
subscription.activated
The subscription's first charge succeeded (either at checkout with no trial, or at trial end). The subscription is now active.
subscription.renewed
A recurring renewal charge succeeded and the subscription moved into its next billing period.
subscription.unpaid
A recurring (or initial) charge failed or requires payment. The subscription is now unpaid and dunning has started.
subscription.payment_method_updated
The subscription's payment method was successfully updated (consent was granted for the new card).
subscription.plan_change_scheduled
A deferred plan change was approved by the consumer and will be applied at the start of the next billing period.
subscription.plan_change_canceled
A previously scheduled deferred plan change was canceled before it was applied.
subscription.plan_changed
A plan change (immediate or deferred) was applied to the subscription. The items and/or interval in the payload reflect the new plan.
subscription.canceled
The subscription was canceled by the merchant on the consumer's behalf. No further charges will occur.
subscription.expired
The subscription ended because payment could not be collected (dunning exhausted, or the initial charge never succeeded).
  • subscription.activated and subscription.renewed: Grant or extend access to your product for the current billing period.
  • subscription.unpaid: Optionally warn the consumer in your own product UI that a payment issue needs attention; Tokenz already handles retries and consumer emails automatically.
  • subscription.payment_method_updated: Update your own records if you cache payment method metadata; no action needed to keep the subscription billing correctly.
  • subscription.plan_changed: Update entitlements to match the new plan's item.
  • subscription.canceled and subscription.expired: Revoke access at the end of the current billing period (or immediately, depending on your product's policy) and update your own subscription status to reflect the terminal state.