Utopia PaymentsDocs

Subscriptions

Charge customers automatically, with retries when a renewal fails.

Create a recurring product, then create a checkout session with exactly that product. The first payment starts the subscription and saves the customer's card, so renewals are charged automatically on schedule.

curl https://utopia-payments.com/api/v1/products \
  -H "Authorization: Bearer $UTOPIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Pro", "price": 9900, "currency": "AED",
        "billing": "recurring", "billing_interval": "month" }'

No code needed

You can also create a recurring product in the dashboard and share a payment link for it. Customers who pay through the link are subscribed the same way.

Before paying, the checkout tells the customer the subscription renews automatically, at what amount and how often.

Who charges the renewals

A subscription renews in one of two ways, fixed when it starts:

  • Utopia charges each renewal with the card saved at the first payment.
  • The card processor takes the first payment inside a subscription of its own, and charges each renewal itself on its own schedule. Its payment page tells the customer that upcoming payments will be charged automatically. New subscriptions renew this way once it is enabled for your account; when the processor can't start one (for example, when it already knows the customer), that checkout falls back to Utopia's way without the customer noticing.

Either way you receive the same events and see the same payments: each renewal is a payment with billing_reason: "subscription_cycle" that sends payment.succeeded and subscription.renewed. Dashboard → Subscriptions shows which way each subscription renews.

Renewals and failed payments

When Utopia renews a subscription and the renewal is declined:

  1. The subscription moves to on_hold and you receive subscription.on_hold.
  2. The customer is emailed a secure link to pay the renewal, in English and Arabic.
  3. The card is retried after 1, 3 and 5 days. Paying the link at any point renews the subscription and saves the new card.
  4. If the fourth attempt also fails, the subscription is cancelled with cancellation_reason: "payment_failed".

If a card couldn't be saved for a subscription, the customer gets the payment link at each renewal instead of an automatic charge; everything else works the same way.

When the card processor renews a subscription and the renewal is declined:

  1. The subscription moves to on_hold and you receive subscription.on_hold and payment.failed. next_retry_at stays null: the processor decides when to retry.
  2. The processor retries the payment twice on its own schedule. No payment link is emailed, since paying one as well could charge the customer twice.
  3. A retry that goes through renews the subscription as usual. If the last one fails, the processor ends the subscription: it is cancelled with cancellation_reason: "payment_failed" and the customer is emailed that it was cancelled.

A subscription the processor ends for any other reason is cancelled with cancellation_reason: "gateway_canceled".

Cancelling

# Stop renewing when the paid period ends
curl -X PATCH https://utopia-payments.com/api/v1/subscriptions/sub_… \
  -H "Authorization: Bearer $UTOPIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "cancel_at_period_end": true }'

# Or cancel right away
curl -X PATCH https://utopia-payments.com/api/v1/subscriptions/sub_… \
  -H "Authorization: Bearer $UTOPIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "cancelled" }'

For a subscription the card processor renews, the processor is told to stop first. If it doesn't confirm, nothing changes and the API answers 502 with the code CANCELLATION_FAILED: try again. Ending it at the end of the period stops the processor's renewals at once (the current period is already paid) and keeps the subscription active until next_billing_date. That can't be undone, so sending cancel_at_period_end: false afterwards answers 409 with the code CANCELLATION_FINAL.

cancellation_reason says why a subscription ended: requested (you cancelled it), payment_failed (its renewal payments failed), gateway_canceled (the card processor ended it) or merchant_rejected (the merchant account was rejected).

Grant access while a subscription is active or on_hold, and use next_billing_date to show when it renews.

Managing subscriptions in the dashboard

Dashboard → Subscriptions shows monthly recurring revenue, every subscription and its payments. From there you can cancel now or at the end of the period, keep a subscription that was set to end, and copy or re-send the payment link for one that is on hold. For a subscription the card processor renews there is no payment link, and ending it at the end of the period can't be undone.

On this page