Subscriptions
Recurring billing through payments.subscriptions — create, retrieve, and cancel plans on providers that support them.
Recurring billing lives under payments.subscriptions. It's available on
providers that support it (Stripe, Paystack, Razorpay, Mercado Pago, Bachs and
others); providers without recurring billing throw a typed
UnsupportedOperationError rather than failing quietly.
Create a subscription
const sub = await payments.subscriptions.create({
planId: "price_123", // the provider's plan/price id
customer: { email: "ada@example.com" },
});
sub.id; // subscription id
sub.status; // "active" | "trialing" | "past_due" | "canceled" | ...planId is the provider's own id
planId is created in the provider's dashboard/API, not by Radon. For Stripe
it's a Price id (price_…); the adapter auto-creates a Customer object if
customer.id isn't already a cus_….
The input
planIdstringrequiredThe recurring plan/price identifier in the provider.
customer{ email?: string; id?: string; name?: string }requiredWho to bill. Requirements vary by provider (email is commonly required).
metadataRecord<string, string>Stored on the subscription and echoed in webhooks.
Retrieve and cancel
const current = await payments.subscriptions.retrieve(sub.id);
await payments.subscriptions.cancel(sub.id, {
atPeriodEnd: true, // stop at the end of the paid period instead of immediately
});atPeriodEndbooleandefault: falseCancel at the end of the current billing period rather than right away. Applied where the provider supports scheduled cancellation.
Keep state in sync with webhooks
Subscriptions change on the provider's clock — renewals, failed payments,
dunning. Listen for webhook events like
subscription.updated, subscription.canceled, and invoice.payment_failed
to keep your database accurate. Don't rely on polling.