Pricing Phases

Breeze's pricing phases let a single subscription bill through an ordered list of prices before settling on its default price — the top-level priceId on the subscription. Each phase bills its own amount and interval for a fixed number of billing cycles; once every phase is exhausted, billing continues at that default price.

Phases cover introductory pricing, step-up (or step-down) pricing, and multi-stage promotions. The whole schedule is declared once, at creation — a live subscription cannot be re-priced — and Breeze advances to the next phase as it generates each invoice.


How It Works

A phase is a cycleCount plus a price. The price is either a reference to an existing recurring price on the same product (priceId) or an inline price defined in the request (price) — exactly one of the two per phase.

Prices are snapshotted at creation: the amount and billing cycle stored on the subscription are the ones used for billing, so later edits to a referenced price do not change an existing subscription.

Billing walks the phases in order:

StepBehavior
First chargeThe invoice created with the subscription is the first phase's invoice, so the customer's first charge is phase 1's amount.
Within phasesEach invoice is priced by the phase that owns that cycle, and the next bill date uses that phase's billingCycleConfig.
Phase advanceOnce a phase has billed cycleCount cycles, the next invoice uses the next phase.
Phases exhaustedBilling falls back to the subscription's default price and its billing cycle, indefinitely.

Phases do not introduce a new subscription status. A phases-only subscription becomes ACTIVE on the first successful payment and stays ACTIVE through every phase.

Request shape

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": "cus_123xyz"
   },
   "phases": [
     { "cycleCount": 2, "priceId": "prc_intro123xyz" }
   ],
   "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": "cus_123xyz"
   },
   "phases": [
     {
       "cycleCount": 2,
       "price": {
         "unitAmount": 90,
         "currency": "USD",
         "billingCycleConfig": { "interval": "day", "frequency": 1 }
       }
     }
   ]
 }'
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": "cus_123xyz"
   },
   "phases": [
     {
       "cycleCount": 3,
       "price": {
         "unitAmount": 100,
         "currency": "USD",
         "billingCycleConfig": { "interval": "month", "frequency": 1 }
       }
     },
     {
       "cycleCount": 3,
       "price": {
         "unitAmount": 500,
         "currency": "USD",
         "billingCycleConfig": { "interval": "month", "frequency": 1 }
       }
     }
   ]
 }'
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": "cus_123xyz"
   },
   "startAt": 1759950506000,
   "phases": [
     { "cycleCount": 2, "priceId": "prc_intro123xyz" }
   ]
 }'
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": "cus_123xyz"
   },
   "trial": {
     "duration": 7,
     "durationType": "day"
   },
   "phases": [
     { "cycleCount": 2, "priceId": "prc_intro123xyz" }
   ]
 }'
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": "cus_123xyz"
   },
   "startAt": 1759950506000,
   "trial": {
     "duration": 7,
     "durationType": "day"
   },
   "phases": [
     { "cycleCount": 2, "priceId": "prc_intro123xyz" }
   ]
 }'
  • priceId (top level) is still required — it is the default price billed once all phases are exhausted.
  • phases[].cycleCount: number of billing cycles this phase bills before advancing. Minimum 1.
  • phases[].priceId: an existing price to bill during this phase. Mutually exclusive with phases[].price.
  • phases[].price.unitAmount: amount in minor units / cents (e.g. 10000 = USD 100.00).
  • phases[].price.billingCycleConfig.interval: hour, day, week, month, or year. hour is sandbox-only.
  • Inline phase prices are not persisted as reusable Price entities; they exist only on the subscription.

Validation rules

RuleDetail
Phase count1–10 phases per subscription.
Price sourceEach phase defines exactly one of priceId or inline price.
Referenced priceMust be ACTIVE, of type RECURRING, belong to the same product as the subscription, and use the subscription's currency.
CurrencyEvery phase currency must match the subscription's currency.
Intervalhour billing is rejected in live mode (sandbox only).
Mutual exclusivityphases and discountedTrial cannot be sent together.

Sample Scenarios

Scenario 1: Introductory pricing

Today: 2025-05-01

Merchant: Creates a subscription with:

  • Default price: $9/month (priceId)
  • Phase 1: $0.90/day × 2 cycles

Flow:

  • 2025-05-01: Customer completes the payment page → charged $0.90 (phase 1, cycle 1)
  • 2025-05-02: Breeze charges $0.90 (phase 1, cycle 2)
  • 2025-05-03: Breeze charges $9 (phases exhausted → default price, first monthly cycle)
  • 2025-06-03: Breeze charges $9

Behavior: the subscription is ACTIVE from the first successful payment onward. No status change happens when the phase is exhausted.

Scenario 2: Multi-phase step-up

Today: 2025-05-01

Merchant: Creates a subscription with:

  • Default price: $9/month (priceId)
  • Phase 1: $1/month × 3 cycles
  • Phase 2: $5/month × 3 cycles

Flow:

  • 2025-05-01 → 2025-07-01: charged $1/month (3 cycles)
  • 2025-08-01 → 2025-10-01: charged $5/month (3 cycles)
  • 2025-11-01 onward: charged $9/month (default price)
ℹ️

Phases can be combined with trial, startAt, or both. The verification invoice created for those does not consume a phase — phase 1 prices the first real charge, and the phases after it follow from there. For when that first charge falls, see Scheduled & Free Trial.

Scenario 3: Phases + scheduled start

Today: 2025-04-01

Merchant: Creates a subscription with:

  • Default price: $9/month (priceId)
  • Phase 1: $0.90/day × 2 cycles
  • Scheduled start: 2025-05-01

Flow:

  • 2025-04-01: Customer completes card verification (no phase charge yet)
  • 2025-05-01: Breeze charges $0.90 (phase 1, cycle 1)
  • 2025-05-02: Breeze charges $0.90 (phase 1, cycle 2)
  • 2025-05-03: Breeze charges $9 (default price)

Behavior:

  • 2025-04-01 → 2025-05-01: subscription is SCHEDULED
  • 2025-05-01 onward: subscription is ACTIVE

Scenario 4: Phases + free trial

Today: 2025-05-01

Merchant: Creates a subscription with:

  • Default price: $9/month (priceId)
  • Phase 1: $0.90/day × 2 cycles
  • Free trial: 7 days

Flow:

  • 2025-05-01: Customer completes the payment page — no charge; the trial starts
  • 2025-05-08: Trial ends → charged $0.90 (phase 1, cycle 1)
  • 2025-05-09: Breeze charges $0.90 (phase 1, cycle 2)
  • 2025-05-10: Breeze charges $9 (phases exhausted → default price)

Behavior:

  • 2025-05-01 → 2025-05-08: subscription is TRIALING
  • 2025-05-08 onward: subscription is ACTIVE

Scenario 5: Phases + scheduled start + free trial

Today: 2025-04-01

Merchant: Creates a subscription with:

  • Default price: $9/month (priceId)
  • Phase 1: $0.90/day × 2 cycles
  • Scheduled start: 2025-05-01
  • Free trial: 7 days

Flow:

  • 2025-04-01: Customer completes card verification (no charge)
  • 2025-05-01: Trial starts — still no charge
  • 2025-05-08: Trial ends → charged $0.90 (phase 1, cycle 1)
  • 2025-05-09: Breeze charges $0.90 (phase 1, cycle 2)
  • 2025-05-10: Breeze charges $9 (phases exhausted → default price)

Behavior:

  • 2025-04-01 → 2025-05-01: subscription is SCHEDULED
  • 2025-05-01 → 2025-05-08: subscription is TRIALING
  • 2025-05-08 onward: subscription is ACTIVE

Reading Phases Back

GET /v1/subscriptions/{subscriptionId} returns the snapshotted phases, in order. price.id is present only for phases that referenced an existing price.

billingCycleAnchor is the Unix timestamp (ms) the subscription's billing cycles are anchored to — the time of the first payment, or startAt for a scheduled subscription. It is absent until the first payment completes.

{
  "status": "SUCCEEDED",
  "data": {
    "id": "subs_abc123xyz",
    "status": "ACTIVE",
    "priceId": "prc_abc123xyz",
    "amountStr": "9",
    "currency": "USD",
    "billingCycleConfig": { "interval": "month", "frequency": 1 },
    "billingCycleAnchor": 1746057600000,
    "phases": [
      {
        "cycleCount": 2,
        "price": {
          "id": "prc_intro123xyz",
          "unitAmount": 90,
          "currency": "USD",
          "billingCycleConfig": { "interval": "day", "frequency": 1 }
        }
      }
    ]
  }
}

Migrating from discountedTrial

A discountedTrial is a single phase. Map it directly:

discountedTrialphases equivalent
cycleCountphases[0].cycleCount
billingCycleConfigphases[0].price.billingCycleConfig
price.unitAmount / price.currencyphases[0].price.unitAmount / phases[0].price.currency

Two behavioral differences to expect:

  • A phases subscription reports ACTIVE during its introductory cycles, not DISCOUNTED_TRIALING.
  • Phases support up to 10 stages, so an introductory period no longer has to be a single price.

Existing discountedTrial subscriptions are unaffected and continue to bill and report DISCOUNTED_TRIALING as before.


Key Takeaways

  • phases is the supported way to bill introductory, promotional, or stepped pricing; discountedTrial is deprecated.
  • Phases are ordered, snapshotted at creation, and fall back to the subscription's default price once exhausted.
  • Each phase can reference an existing recurring price or define an inline one, but not both.
  • Phases add no new subscription status — billing runs in ACTIVE.

Did this page help you?