Skip to main content
Subscriptions let you charge a customer repeatedly on a fixed schedule. SouthPay generates an invoice at the start of every cycle and collects it through the same crypto checkout used for one-off payments, so a subscription is really an automatic invoice generator.

Building blocks

You compose a subscription from four resources. See the Recurring API reference for full field shapes, and Invoicing for customers. A price sets interval (daily, weekly, monthly, or yearly) and interval_count. Set interval_count: 3 on a monthly price for quarterly billing. Money fields are immutable once a price exists; archive and create a new one to change them.

Items

A subscription is billed as one or more items, each pairing a price with a quantity. The first item is the anchor: its price sets the interval and currency for the whole subscription. Add more items for a base plan plus add-ons, and every item becomes a line on the same invoice.
All items must share the same interval, interval count, and currency.

Create a subscription

Pick a customer and one or more { price_id, quantity } items.
Every id is a bare UUID. For a single price, use the shorthand "price_id" (with an optional "quantity") instead of items.
Billing endpoints ignore the Idempotency-Key header entirely. Retrying a subscription or customer create after a timeout can produce a duplicate. Deduplicate on your side, or check for an existing record before retrying. See Idempotency.
To subscribe several customers to the same plan, create one subscription per customer with the same items. A price is shared, a subscription is per-customer.

Trials

Set trial_period_days to start the subscription in a trialing status. No invoice is issued during the trial; when it ends, the subscription becomes active and its first cycle is billed.

The billing cycle

At the start of each cycle SouthPay creates and finalizes an invoice for every item, then advances the period. The customer pays the invoice on-chain, exactly like a one-off payment. Listen for invoice.finalized (a new cycle was billed) and invoice.paid (the customer paid) rather than polling. You can list a subscription’s invoices with GET /billing/invoices?subscription_id=.... That endpoint is paginated inside a meta envelope.
GET /billing/subscriptions is not paginated. It returns the whole filtered collection as a bare array, with no meta and no pagination key. Filters are status and customer_id. Do not write a pager against it, and do not assume the response is an object.

Manage the lifecycle

  • Change the plan with PATCH /billing/subscriptions/:id and a new items set. The change applies from the next cycle; there is no mid-cycle proration.
  • Cancel with POST .../cancel. It ends immediately, or pass { "at_period_end": true } to let the current cycle finish first. Undo a scheduled cancellation with POST .../uncancel.
  • Pause and resume. POST .../pause suspends billing; POST .../resume restarts it from a fresh period.
If a cycle goes unpaid, the subscription moves to past_due and SouthPay emits subscription.past_due. Once the grace window (about grace_cycles × the interval) is exhausted, the invoice is marked uncollectible and the subscription is canceled for non-payment.

Webhooks

Subscribe to the billing webhook events: subscription.created, subscription.updated, subscription.past_due, subscription.canceled, plus the invoice.* events that carry each renewal and payment.

Next steps

Recurring API reference

Full resource shapes and every operation for products, prices, and subscriptions.
Last modified on August 21, 2026