Quick Start (Subscription)

Breeze's Subscription product lets you offer recurring payments, free trials, and subscription entitlements with minimal integration. This guide will help you set up and test a subscription flow end-to-end—from creation to webhook handling.

Conceptually:

  • Scheduled Subscriptions are used when the subscription is set to begin at a future date, and the customer is not yet entitled to the service until that date.
  • Free Trials are used when the subscription is immediately started, granting the customer access to the service during the trial period, but no charges are made until the trial ends.
  • Discounted Trials are used when the subscription includes a discounted introductory period, during which the customer is charged a reduced amount for each trial cycle before transitioning to the standard recurring price.

Before Going Live 🚀

Before launching your subscription flow in production, make sure the following is complete:

  1. Product & Price Setup
    • Share your product and price configuration with the Breeze team for initial setup.
    • You may share with us about the information using this csv template
      • Sample given is for a monthly recurring plan
      • billing_cycle_frequency: day, week, month or year
    • Once we have set it up, we will return you the details in this format
      • this file will include the Breeze's product_id and price_id that you can use for creating a Subscription
    • Note: Self-serve product creation is coming soon!
  2. Grace Period
    • Share your grace period configuration with Breeze
    • The default grace period is set to 60 days
  3. Webhook Endpoint
    • Ensure your webhook server is ready to receive SUBSCRIPTION_STATUS_UPDATEDevents

Integration Flow

1. Create a Customer (If you haven't)

Send a POST request to the Breeze API with the most basic parameters. For quick testing, you can use a command-line tool like cURL:

curl -X POST 'https://api.breeze.cash/v1/customers' \
  -u "YOUR_API_KEY:" \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "referenceId": "<your-unique-user-id>",
    "email": "[email protected]",
    "signupAt": 1710000000000, // 2024-03-08T12:00:00.000Z, UTC+0 timestamp in milliseconds
  }'

A successful response will look like:

{
  "status": "SUCCEEDED",
  "data": {
    "id": "cus_123abc456", // The customer ID generated by Breeze
    "referenceId": "<your-unique-user-id>",
    "email": "[email protected]",
    "signupAt": 1710000000000,
    ...
  }
}

2. Create a Subscription Request

Send a POST request to Breeze’s subscription API with the required parameters. You can quickly test this using a command-line tool like curl:

curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "customer": {
      "id": "cust_123xyz"
   },
   "successReturnUrl": "<optional:the-redirect-url-after-the-1st-payment-is-done>"
 }'
curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "trial": { 
     "duration": 7,
     "durationType": "day"
   },
   "customer": {
      "id": "cust_123xyz"
   }
 }'
curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "startAt": 1759950506000,
   "customer": {
      "id": "cust_123xyz"
   }
 }'
curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "trial": { 
     "duration": 7,
     "durationType": "day"
   },
   "startAt": 1759950506000,
   "customer": {
      "id": "cust_123xyz"
   }
 }'
curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "customer": {
      "id": "cust_123xyz"
   },
   "discountedTrial": {
        "cycleCount": 3,
        "billingCycleConfig": {
            "interval": "hour",
            "frequency": 2
        },
        "price": {
            "amountStr": "1.05",
            "currency": "USD"
        }
   },
   "successReturnUrl": "<optional:the-redirect-url-after-the-1st-payment-is-done>"
 }'
curl -X POST 'https://api.breeze.cash/v1/subscriptions' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json' \
 --data-raw '{
   "clientReferenceId": "your-unique-subscription-reference-id",
   "productId": "prd_abc123xyz",
   "priceId": "prc_abc123xyz",
   "customer": {
      "id": "cust_123xyz"
   },
   "startAt": 1759950506000,
   "discountedTrial": {
        "cycleCount": 3,
        "billingCycleConfig": {
            "interval": "hour",
            "frequency": 2
        },
        "price": {
            "amountStr": "1.05",
            "currency": "USD"
        }
   },
   "successReturnUrl": "<optional:the-redirect-url-after-the-1st-payment-is-done>"
 }'
  • customer.id is the id you get when creating your Breeze customer in step 1
  • clientReferenceId : this will be used as the idempotency id to make sure there is no duplicate creation of Subscription
  • trial.durationType: hour,day, week, month, or year
  • discountedTrial.billingCycleConfig.interval: hour,day, week, month, or year
  • discountedTrial.price: the discounted price to be charged to customer during the discounted trial billing period
  • startAt: the UTC timestamp (in milliseconds) when billing is scheduled to begin. It must be at least 24 hours in the future.

Billing Behavior:

  • For free trial subscriptions:
    • A $0 invoice is generated with a billing period matching the trial duration.
    • The first real charge occurs after the trial ends.
  • For scheduled subscriptions:
    • An invoice with identical start and end timestamps (startAt) is created to mark verification.
    • Actual billing starts on the specified date.
  • For combined scheduled + trial subscriptions:
    • Billing starts after the trial duration elapses following the scheduled start.
  • For combined scheduled + discounted trial subscriptions:
    • Discounted billing starts at the scheduled start date and continues for the configured discounted trial cycles before transitioning to standard billing.

A successful response will look like this:

{
  "status": "SUCCEEDED",
  "data": {
    "id": "subs_abc123xyz",
    "url": "https://invoice.breeze.cash/invc_abc123xyz"
  }
}
  • data.id: Unique identifier for the subscription.
  • data.url: Hosted payment page for the customer to complete the first payment.

3. Redirect the User

After receiving the data.url, redirect your customer to the Breeze-hosted page. Breeze will:

  • Collect card details securely
  • Initiate the first payment (or start the trial if configured)
  • Send confirmation and receipts via email

4. Handle Webhooks

Breeze will notify your backend of changes via webhook events. Example webhook payload:

{
  "type": "SUBSCRIPTION_STATUS_UPDATED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "ACTIVE",
    "clientReferenceId": "your-unique-subs-id",
    ...
  },
  "signature": "webhook_signature"
}
{
  "type": "INVOICE_STATUS_UPDATED",
  "data": {
    "id": "invc_abc123xyz",
    "status": "PAID",
		"subscriptionId": "subs_abc123xyz",
    "clientReferenceId": "your-unique-subs-id",
		"billingPeriod": {
      "start": 1758703144521, 
      "end": 1763887106025
		},
    ...
  },
  "signature": "webhook_signature"
}

🔧 Set up a POST endpoint (e.g., /webhook) to process these events and keep your system in sync.

5. Cancel Subscription


curl -X POST 'https://api.breeze.cash/v1/subscriptions/:id/cancel' \
 -u "YOUR_API_KEY:" \
 --header 'Content-Type: application/json'

6. Get Subscription

curl 'https://api.breeze.cash/v1/subscriptions/:subscriptionId' \
 -u "<YOUR_API_KEY>:" \
 --header 'Content-Type: application/json' \
curl 'https://api.breeze.cash/v1/subscriptions/?limit=5&offset=0' \
 -u "<YOUR_API_KEY>:" \
 --header 'Content-Type: application/json' \

Sample Response

{
    "status": "SUCCEEDED",
    "data": {
        "id": "subs_1b252358e0ed0b61",
        "clientReferenceId": "ref-id",
        "status": "CANCELED",
        "priceId": "prc_19092bf033b0292d",
        "productId": "prd_73062347e36944fe",
        "customerId": "cus_9147c9be8f25092c",
        "amountStr": "3.01",
        "currency": "USD",
        "billingCycleConfig": {
            "interval": "hour",
            "frequency": 1
        },
        "merchantId": "mch_cd239603802d7b4e",
        "livemode": false,
        "defaultPaymentMethodId": "card_a6a9ffd09d085ada",
        "defaultPaymentMethodType": "CARD",
        "billingCycleAnchor": 1761215553301,
        "canceledAt": 1761702869623,
        "lastSuccessfulPaymentId": "py_c686c5fa1f66de6e",
        "lastSuccessfulInvoiceId": "invc_404f2a7ed01d2232",
        "firstSuccessfulPaymentId": "py_cb8413d10f6ce144",
        "fallbackBillingEmail": "[email protected]"
    }
}
{
    "status": "SUCCEEDED",
    "data": [
        {
            "id": "subs_6e3e046369d0d475",
            "clientReferenceId": "ref-id",
            "status": "CANCELED",
            "priceId": "prc_19092bf033b0292d",
            "productId": "prd_73062347e36944fe",
            "customerId": "cus_9147c9be8f25092c",
            "amountStr": "3.01",
            "currency": "USD",
            "billingCycleConfig": {
                "interval": "hour",
                "frequency": 1
            },
            "merchantId": "mch_cd239603802d7b4e",
            "livemode": false,
            "defaultPaymentMethodId": "card_df86d6c567bebc67",
            "defaultPaymentMethodType": "CARD",
            "billingCycleAnchor": 1761222789969,
            "canceledAt": 1761222833269,
            "lastSuccessfulPaymentId": "py_1e76276486a61867",
            "lastSuccessfulInvoiceId": "invc_100d5770eea566b7",
            "firstSuccessfulPaymentId": "py_1e76276486a61867",
            "fallbackBillingEmail": "[email protected]"
        }
    ],
    "hasMore": true
}

📺 Demo Video

  • You may find the demo video here
  • For Sandbox test cards, you may use the cards here

Next Steps

  • Secure Your Webhook: Validate webhook signatures to ensure they come from Breeze.
  • Go Live: After thorough testing, switch to production credentials to process real-world subscription


What’s Next