Set up a subscription
Create a recurring billing agreement with one API call. MintCash handles renewals, retries, dunning emails, and cancellation.
A subscription bills a customer on a fixed cadence using a saved card. You create it; we run the billing cycle, retry failures on a sensible schedule, and email the customer at each state transition.
What you decide
- Amount and currency — the recurring price, in decimal major units (e.g.
19.99). - Billing interval —
billingIntervalDays. Common values: 7, 14, 30, 90, 365. - First-charge flow — HPP (customer enters card on first sign-up) or token (you already have a saved card).
- Introductory pricing (optional) — a
phasesarray billed before the recurring terms kick in. See introductory and phased pricing.
Creating a subscription
First sign-up (HPP variant)
If the customer doesn't have a saved card yet, send them through the hosted page on creation:
const r = await fetch("https://sandbox.mintcash.me/subscriptions", {
method: "POST",
headers: { Authorization: ..., "Content-Type": "application/json" },
body: JSON.stringify({
externalId: `sub_${customerId}_${planId}`,
amount: 19.99,
currency: "USD",
billingIntervalDays: 30,
returnUrl: `${baseUrl}/billing/welcome`,
customer: {
externalId: customerId,
email: customer.email,
name: customer.name,
},
}),
});
const { subscription, redirectUrl } = await r.json();
return Response.redirect(redirectUrl, 302);The customer pays the first invoice on the hosted page. On success, the subscription becomes active and the card token is saved for future renewals.
Returning customer (token variant)
If you already have a cardToken for this customer, skip the hosted page:
const r = await fetch("https://sandbox.mintcash.me/subscriptions", {
method: "POST",
headers: { Authorization: ..., "Content-Type": "application/json" },
body: JSON.stringify({
externalId: `sub_${customerId}_${planId}`,
amount: 19.99,
currency: "USD",
billingIntervalDays: 30,
cardToken: savedCardToken,
customer: { externalId: customerId },
}),
});No redirect. The first charge runs server-to-server. You'll receive subscription.succeeded (or .failed) on the webhook.
Listen for renewals
Every renewal fires a webhook. Track the events to keep your own state in sync:
| Event | Subscription state | What to do |
|---|---|---|
subscription.succeeded | active | Extend the customer's access |
subscription.failed | past_due | Surface a banner; we'll auto-retry |
subscription.cancelled | cancelled (terminal) | Revoke access, archive the agreement |
You can also fetch the current state any time with GET /subscriptions/{id}.
Cancel when needed
await fetch(`https://sandbox.mintcash.me/subscriptions/${subscriptionId}`, {
method: "DELETE",
headers: { Authorization: ... },
});Cancellation is immediate and irreversible. No further renewals or retries. Pending invoices are not charged. To start charging again, create a new subscription.
Introductory pricing (optional)
To bill a discounted or ramped intro before the recurring rate, add a phases array. Each phase runs for iterations cycles in order; the top-level amount / billingIntervalDays stay the recurring terms, which MintCash bills forever once the phases finish.
const r = await fetch("https://sandbox.mintcash.me/subscriptions", {
method: "POST",
headers: { Authorization: ..., "Content-Type": "application/json" },
body: JSON.stringify({
externalId: `sub_${customerId}_${planId}`,
amount: 19.99, // recurring price
currency: "USD",
billingIntervalDays: 30,
phases: [
{ name: "intro", amount: 9.99, billingIntervalDays: 30, iterations: 3 },
],
cardToken: savedCardToken,
customer: { externalId: customerId },
}),
});This charges $9.99/month for 3 months, then $19.99/month thereafter. Phase amounts must be above 0 — no $0 trials. The response's phases array shows the full schedule; the recurring phase is the one with iterations: null.
What to test
- Token-flow creation + happy-path renewal
- HPP creation, complete on hosted page, observe
subscription.succeeded - Force first-charge failure (use a failing test card) — subscription should land in
failed - Force renewal failure mid-cycle — observe retries and eventual
cancelled - Customer updates payment method — verify retry recovers the subscription
DELETEan active subscription — observesubscription.cancelled