Mintcash
Guides

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 — fixed per subscription.
  • Billing intervalbillingIntervalDays. 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).

Creating a subscription

Rendering diagram…

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: 1999,
    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: 1999,
    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:

EventSubscription stateWhat to do
subscription.succeededactiveExtend the customer's access
subscription.failedpast_dueSurface a banner; we'll auto-retry
subscription.cancelledcancelled (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.

Retry schedule on failure

When a renewal fails, MintCash automatically retries on this cadence:

AttemptWhen
1Due date
2+1 day
3+3 days
4+5 days
5+7 days
All exhausted → cancelled

After the first failure, the customer gets an email prompting them to update their payment method. If they update it, the next renewal cycle starts fresh.

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.

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
  • DELETE an active subscription — observe subscription.cancelled