Mintcash
Concepts

Subscriptions

Recurring billing — the state machine, the retry schedule, and what happens between renewals.

A Subscription represents a recurring agreement: charge a customer a fixed amount on a fixed interval. MintCash handles billing, retries on failure, and emails the customer at each state change.

The state machine

Rendering diagram…

Terminal states: failed, cancelled. Once either is reached, no more billing happens.

Allowed transitions

FromAllowed to
createdpending, active, failed
pendingactive, failed
activepast_due, cancelled
past_dueactive, cancelled
failed(terminal)
cancelled(terminal)

Full lifecycle

Rendering diagram…

Renewal logic

When a subscription reaches its billingIntervalDays since the last successful charge, MintCash:

  1. Charges the saved payment method using the stored card token.
  2. On success: subscription stays active, fires subscription.succeeded.
  3. On failure: subscription moves to past_due, fires subscription.failed, and schedules the next retry.

Introductory and phased pricing

By default a subscription bills the same amount every billingIntervalDays — a single recurring price. To run an introductory offer or a ramp — a discounted first few months before the standard rate — pass an optional phases array when you create the subscription.

Each phase bills its own amount on its own billingIntervalDays for a fixed number of iterations, in the order you list them. The top-level amount and billingIntervalDays always describe the recurring steady state — MintCash appends that as the final, open-ended phase automatically. A subscription with no phases is simply that single recurring phase.

{
  "amount": 9.99,
  "billingIntervalDays": 30,
  "phases": [
    {
      "name": "intro",
      "amount": 4.99,
      "billingIntervalDays": 30,
      "iterations": 3
    }
  ]
}

This bills $4.99/month for 3 months, then $9.99/month indefinitely. The first invoice always charges the first phase, so the initial period length follows that phase's interval — not necessarily the recurring one.

Phase fieldMeaning
amountPrice for this phase, in decimal major units (e.g. 4.99). Must be above 0.
billingIntervalDaysWhole days between charges during this phase.
iterationsHow many times this phase bills before advancing to the next phase.
nameOptional label (e.g. intro, ramp) echoed back on the response.

The subscription response carries a phases array — the full ordered schedule, intro phases first and the recurring phase last. The recurring phase has iterations: null, meaning it repeats indefinitely. Each phase also has an id and order assigned by MintCash. Renewals follow this schedule in order, then bill the recurring phase from then on.

Retry schedule

A failed renewal isn't the end. MintCash retries on a backoff schedule:

AttemptWhen (from first failure)Status
1Day 0 (renewal due date)First charge attempt
2Day +1Retry 1
3Day +3Retry 2
4Day +5Retry 3
5Day +7Retry 4
After all retries failSubscription cancelled

Retry offsets are cumulative from the first failed charge (day 0) — days 1, 3, 5, 7 — not gaps between attempts.

The first failure itself is silent — no customer email. See Emails for when the first email actually fires and the full sequence after that.

Why this schedule

The 1→3→5→7-day cadence is calibrated against industry decline-recovery patterns. Most recovered subscriptions come back in the first two attempts; the longer tail catches cards reissued mid-month.

Keep your records consistent

Always use the webhook as the source of truth for subscription state. A successful response to POST /subscriptions means the agreement was created — not that the first charge succeeded. Wait for subscription.succeeded before granting access.

Cancellation

Send DELETE /subscriptions/{id} to cancel immediately. Pending invoices are not charged. The subscription's status becomes cancelled — terminal, no further renewals or retries.

Cancellation does not refund prior payments. To refund a customer who cancels mid-cycle, issue a refund against the most recent payment with POST /payments/{id}/refund.

What fires when

TransitionWebhookCustomer email
created → activesubscription.succeeded"Payment confirmation"
active → past_duesubscription.failedNone — silent
past_due → activesubscription.succeeded"Payment confirmation"
* → cancelledsubscription.cancelled"Subscription cancelled"

See Emails for every subscription email — what each contains, the dunning order, and how to turn them off.