Subscription Events

Breeze sends webhook events of type "SUBSCRIPTION_STATUS_UPDATED" whenever a subscription’s status changes. These events help you track lifecycle transitions like creation, payment success/failure, cancellations, and overdue states.

Each subscription event includes a JSON payload structured in the following manner:

{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "INCOMPLETE",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "INCOMPLETE_EXPIRED",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "TRIALING",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "ACTIVE",
    "amount": 199, // in minor unit
    "billingCycleAnchor": 1755836495645,
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "lastInvoiceId": "invc_1234asdf",
    "lastSuccessfulInvoiceId": "invc_2345qwert",
    "lastSuccessfulPaymentId": "py_3456zxcv",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "GRACE_PERIOD",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "SUSPENDED",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "CANCELED",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "canceledAt": 1755936495645,
    "canceledBy": "CUSTOMER",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "SCHEDULED",
    "amount": 199, // in minor unit
    "billingCycleConfig": {
      "frequency": 1,
      "interval": "day"
    },
    "clientReferenceId": "your-sub-unique-id",
    "createdAt": 1755836495645,
    "currency": "USD",
    "customerId": "cus_asdf1234",
    "priceId": "prc_qwert3456",
    "productId": "prd_zxcv4567",
    "updatedAt": 1755936495645
  },
  "signature": "webhook_signature"
}
📘

Note that ACTIVE and CANCELED states are the key states that have additional fields in the data object.

Use these to update your internal system or notify users.

Webhook payloads always include:

  • type – Event type
  • data – Subscription object
  • signature – HMAC signature for verification

📘 Core Subscription Statuses

StatusDescription
INCOMPLETEThe subscription was created but no payment has been made yet, or no payment method has been added yet for subscription with trial.
INCOMPLETE_EXPIREDThe subscription was created but no payment has been made until the expiration time.
TRIALINGThe customer has added their payment method successfully for subscription with trial. First payment will be charged at the end of the trial.
SCHEDULEDThe customer has added their payment method successfully, and the subscription is scheduled to start at a future date. Billing has not yet begun, and no charges yet until the scheduled start time (or the end of a trial if one is configured).
ACTIVEThe customer has made a successful payment. Recurring charges are enabled.
GRACE_PERIODA recurring charge failed. The subscription is in the grace period and awaiting resolution
SUSPENDEDGrace period expired without successful payment. Merchant should revoke the service access.
CANCELEDThe subscription has been canceled by the customer or merchant

⚠️ Breeze emits webhook events at each of these state transitions

♻️ Subscription Lifecycle Diagram

stateDiagram-v2
    [*] --> INCOMPLETE: Create subscription
    
		INCOMPLETE --> INCOMPLETE_EXPIRED: Customer did not make any successful first payment attempt (default after 60 days)
    INCOMPLETE --> TRIALING: Payment method added successfully for free trial only subscription
    INCOMPLETE --> ACTIVE: First payment completed successfully
    
		TRIALING --> CANCELED: Customers cancelled subscription during trial period
    TRIALING --> ACTIVE: First payment successfully charged after the trial 
		TRIALING --> GRACE_PERIOD:  First payment failed to be charged after the trial 

    GRACE_PERIOD --> ACTIVE: Payment successful
    GRACE_PERIOD --> SUSPENDED: Grace period expired, no payment


    ACTIVE --> GRACE_PERIOD: Payment fails (grace period)
    ACTIVE --> CANCELED: Customer cancels
    
    GRACE_PERIOD --> CANCELED: Customer cancels

    INCOMPLETE --> SCHEDULED: Payment method added successfully for scheduled subscription
		SCHEDULED --> TRIALING: Trial started for a scheduled subscription with free trial
    SCHEDULED --> ACTIVE: First payment successfully charged


    CANCELED --> [*]
    SUSPENDED --> [*]

Sample Scenario

You want to create a a monthly Subscription with a 7 days trial period (merchant grace period config: 3 days), starting July 1st:

  1. On July 1st, you call POST /v1/subscription with the customer data and subscription setup and we will return you a checkout_url to redirect the users to proceed with adding their payment method
  2. After user successfully added their payment method, we save the payment method on customer's profile for future payment, and Subscription becomes TRIALING and the 7 day trial period starts.
  3. On July 8th, when the trial period end, we automatically charge the customer's saved payment method.
    1. If the off-session payment on July 8th is successful, the Subscription becomes ACTIVE. The customer receives an email confirming the success payment. The customer is billed subsequently on August 8th, then on September 8th, and so on.
    2. If the off-session payment on July 8th is failed , the Subscription becomes GRACE_PERIOD
      1. If this off-session payment still failed to be charged on July 11th (e.g. customer did not respond to payment method change request, etc), the Subscription becomes SUSPENDED
  4. On August 8th, if the Subscription is ACTIVE, we will automatically charge the customer's saved payment method. If this attempt to charge fails, customer will receive an email containing a link to complete the payment online, along with the final deadline to retry by August 11th (reflecting a 3-day grace period). During this time, the Subscription status transitions to GRACE_PERIOD. If no successful payment is made by August 11th, the Subscription status will automatically transition to SUSPENDED.
sequenceDiagram
  participant Merchant
  participant BreezeAPI as Breeze Backend
  participant PaymentPage as Hosted Payment Page
  participant Customer

  Note over Merchant, BreezeAPI: Merchant initiates a subscription
  Merchant->>BreezeAPI: POST /subscriptions (productId, priceId, customerReference, trialDuration)
  BreezeAPI-->>Merchant: checkout_url

  Note over Merchant, Customer: Customer completing a subscription
  Merchant-->>Customer: Send checkout link
  Customer->>PaymentPage: Open hosted payment page
  PaymentPage-->>Customer: Render card form
  Customer->>PaymentPage: Enter card
	PaymentPage->>PaymentPage: Verify payment method

  Note over PaymentPage, BreezeAPI: Payment method is saved
  PaymentPage->>BreezeAPI: Save Payment Method
  BreezeAPI->>BreezeAPI: Mark Subscription as TRIALING
  BreezeAPI-->>Merchant: SUBSCRIPTION_STATUS_UPDATED webhook (status=TRIALING)

  Note over BreezeAPI: 7 days later (trial ends)
  BreezeAPI->>BreezeAPI: Attempt first charge
  BreezeAPI-->>BreezeAPI: Payment success or failure

	alt Payment Succeeds
  	BreezeAPI->>BreezeAPI: Mark Subscription as ACTIVE
  	BreezeAPI-->>Merchant: SUBSCRIPTION_STATUS_UPDATED webhook (status=ACTIVE)
  else Payment Fails
		BreezeAPI->>BreezeAPI: Mark Subscription as GRACE_PERIOD
    BreezeAPI->>Merchant: SUBSCRIPTION_STATUS_UPDATED webhook (status=GRACE_PERIOD)
  end
  
	Note over BreezeAPI: 3 days later (grace period duration)
  alt A successful payment made within 3 days
  	BreezeAPI->>BreezeAPI: Mark Subscription as ACTIVE
  	BreezeAPI-->>Merchant: SUBSCRIPTION_STATUS_UPDATED webhook (status=ACTIVE)
  else No successful payment made
		BreezeAPI->>BreezeAPI: Mark Subscription as SUSPENDED
    BreezeAPI->>Merchant: SUBSCRIPTION_STATUS_UPDATED webhook (status=SUSPENDED)
  end