Subscriptions
Bill the same customer the same amount, on a schedule.
Each cycle opens a payment page and emails your customer a link to it. They pay
it the way they would pay anything else, and you get invoice.paid.
What this is not
It does not charge a card on file, because there is no card on file. Every rail we reach is the payer pushing money to us — a bank transfer they make, mobile money they send, crypto they transfer. None of them hands us a credential to pull with, and we would rather say so than ship a subscription that quietly fails to collect.
So this is recurring invoicing. That is a weaker promise than the one you are used to, and it is the true one for these corridors. What you get in exchange is a customer in Lagos, Nairobi or Kampala who can actually pay you every month.
If your customer wants it to feel automatic, give them a virtual account and have them set a standing order into it at their own bank. The money then arrives on schedule with nobody touching anything.
Start one
POST /v1/subscriptions
{
"customer_id": "cus_84a1",
"reference": "acme-pro-annual",
"amount": 49.0,
"interval": "monthly",
"title": "Acme Pro — monthly"
}
The customer must already exist and must have an email address — that is where each invoice goes, and a subscription with nowhere to send them is refused at creation rather than discovered a month later when nobody has paid.
reference is yours and unique among your subscriptions. Each invoice is
referenced <reference>-<n>, so it reconciles against your books without a
lookup.
The first invoice goes out immediately unless you set start_at.
| Field | |
|---|---|
interval |
weekly, monthly, quarterly, yearly |
cycles |
how many to bill, then stop. Omit to run until you cancel |
due_days |
how long they get to pay before we chase. Default 7 |
allowed_rails |
restrict how each invoice may be paid |
The billing day
A subscription started on the 31st bills on the 31st. February clamps to the 28th — or the 29th — and March goes back to the 31st. The date is always measured from the day the subscription started, never from the previous invoice, so a short month does not shift every cycle after it.
What happens each cycle
- An invoice row is created and
invoice.createdfires, carrying theurl - Your customer is emailed that link
- They pay it — any rail you allowed
invoice.paidfires
invoice.paid is the one to fulfil on. The others describe the agreement, not
money arriving.
When they don't pay
We email a reminder 1, 5 and 12 days after the due date. At 14 days the
subscription becomes past_due and subscription.past_due fires.
It keeps billing. We do not cancel it for you — an unpaid month is a
conversation between you and your customer, and ending the agreement on your
behalf is not our call. The moment they pay the outstanding invoice it returns
to active by itself.
Stopping and starting
POST /v1/subscriptions/{id}/pause
POST /v1/subscriptions/{id}/resume
POST /v1/subscriptions/{id}/cancel
Pause stops the next invoice. Invoices already issued stay payable — pausing is about what happens next, not about forgiving what is owed. Resuming rejoins the original billing day and does not catch up on cycles missed while paused.
Cancel ends it, and voids what was still unpaid: chasing somebody for a month they will not receive is not something we will do on your behalf. Cancelling twice is not an error.
Anywhere {id} appears you can use your own reference instead.
Reading it back
GET /v1/subscriptions
GET /v1/subscriptions/{id}
GET /v1/subscriptions/{id}/invoices
status |
|
|---|---|
active |
billing on schedule |
past_due |
an invoice went unpaid past its grace. Still billing |
paused |
you stopped it. Resumable |
canceled |
ended by you. Terminal |
completed |
ran its agreed cycles. Terminal, and not a failure |
Invoices come back newest first, each with the page your customer pays it on.
Events
| Event | |
|---|---|
subscription.created |
|
invoice.created |
carries the url your customer was emailed |
invoice.paid |
fulfil on this one |
subscription.past_due |
14 days unpaid |
subscription.paused / .resumed / .canceled / .completed |