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
andCANCELED
states are the key states that have additional fields in thedata
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
Status | Description |
---|---|
INCOMPLETE | The subscription was created but no payment has been made yet, or no payment method has been added yet for subscription with trial. |
INCOMPLETE_EXPIRED | The subscription was created but no payment has been made until the expiration time. |
TRIALING | The customer has added their payment method successfully for subscription with trial. First payment will be charged at the end of the trial. |
SCHEDULED | The 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). |
ACTIVE | The customer has made a successful payment. Recurring charges are enabled. |
GRACE_PERIOD | A recurring charge failed. The subscription is in the grace period and awaiting resolution |
SUSPENDED | Grace period expired without successful payment. Merchant should revoke the service access. |
CANCELED | The 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:
- 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 - After user successfully added their payment method, we save the payment method on customer's profile for future payment, and
Subscription
becomesTRIALING
and the 7 day trial period starts. - On July 8th, when the trial period end, we automatically charge the customer's saved payment method.
- If the off-session payment on July 8th is successful, the
Subscription
becomesACTIVE
. The customer receives an email confirming the success payment. The customer is billed subsequently on August 8th, then on September 8th, and so on. - If the off-session payment on July 8th is failed , the
Subscription
becomesGRACE_PERIOD
- 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
becomesSUSPENDED
- 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
- If the off-session payment on July 8th is successful, the
- On August 8th, if the
Subscription
isACTIVE
, 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, theSubscription
status transitions toGRACE_PERIOD
. If no successful payment is made by August 11th, theSubscription
status will automatically transition toSUSPENDED
.
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
Updated 16 days ago