Subscriptions

Recurring billing on Inkress — plans, trials, renewals, card updates, and the webhooks that tell you what happened.

How it fits together

Plan

What you sell: a name, an amount, a currency, and a billing cycle. Created once and shared with many customers.

Subscriber

A customer attached to a plan, with their own status, start date, and next billing date.

Charge

Each successful renewal creates an order, so subscription revenue shows up alongside everything else.

Plan options

OptionWhat it does
Billing cycleDaily, weekly, monthly, or yearly.
Trial periodA number of days before the first charge. Cancel during the trial and the customer is never charged.
Auto-chargeWhether renewals charge the stored card automatically, or the customer is emailed a payment link each cycle.
Usage-based billingDefine custom metrics and price per unit, on top of or instead of a flat rate.
Redirect URLWhere the customer lands after subscribing.
Public / privateWhether the plan is openly subscribable via its link.

Auto-charge changes behaviour elsewhere. With it off, actions that would charge the stored card instead email the customer a payment link. Worth knowing before you assume a charge was taken.

Subscription webhooks

Recurring billing happens without a browser in the loop, so webhooks are the only way to know what happened. Subscribe to the subscriptions wildcard to receive all of them.

subscriptions.created

A new subscription was created.

subscriptions.trial_started

A trial began. No charge taken yet.

subscriptions.trial_ending

The trial is nearly over — a good prompt point.

subscriptions.trial_ended

The trial finished and billing begins.

subscriptions.activated

The subscription became active.

subscriptions.payment_success

A renewal charge succeeded.

subscriptions.payment_failed

A renewal charge failed — usually a dead card.

subscriptions.adhoc_charge

A one-off charge was raised outside the cycle.

subscriptions.cancelled

The subscription was cancelled.

Handling a failed renewal
app.post("/webhooks/inkress", async (req, res) => {
  const { event, subscription } = req.body;

  if (event === "subscriptions.payment_failed") {
    // Almost always an expired or replaced card.
    // Prompt the customer to update it rather than cancelling —
    // the subscription and its billing date survive a card change.
    await emailCardUpdatePrompt(subscription.customer_id);
  }

  res.sendStatus(200);
});

Full reference: Webhook Events.

Self-serve

When a customer's card stops working

Customers can replace the card on a subscription themselves. Previously this meant cancelling and re-subscribing, which lost the billing date and the subscription history.

1

Send the update link

The merchant sends the customer their update payment method link.

2

Customer enters a new card

On a secure page, with the usual card protections.

3

A small authorisation verifies it

A temporary authorisation of about one dollar confirms the card is good. It is not a charge and it drops off — but customers do ask about it, so say so up front in your own messaging.

4

Future renewals use the new card

The subscription, its status, and its next billing date are all preserved.

One-off charges outside the cycle

An active subscriber can be charged an extra amount — an add-on, an overage, a one-time fee — without disturbing their schedule.

With auto-charge on

The stored card is charged immediately.

With auto-charge off

The customer is emailed a payment link for the amount.

In both cases the next billing date does not move, and a subscriptions.adhoc_charge event is emitted. Only active subscribers can be charged this way.

3-D Secure and recurring charges

The customer completes 3-D Secure once, when they set the subscription up. Later renewals charge the stored credential without asking them to verify again — if every renewal needed a live challenge, renewals would fail whenever the customer was asleep or away from their phone.

See 3-D Secure.

Cancellation

Customers cancel from their subscription page. The subscription stops at the end of the current billing period, so the customer keeps access for what they have already paid for. A subscriptions.cancelled event is emitted.

Pausing is not currently supported — cancelling and re-subscribing is the workaround.