Subscriptions
Being rolled out. The interface described here is the one of the next release: it may still change, and may not be enabled on your tenant yet.
What it is for
For a subscription, your customer pays the first period on the payment page. Their payment method is then saved, and the platform charges every following period itself, then issues the matching invoice. You have nothing to trigger.
Prerequisites
subscriptioninbillingModesof your payment account.- A token with the
carts(create the subscription) andsubscriptions(manage it) scopes.
1. Create the subscription cart
Same call as for a one-off payment, with
"mode": "subscription" and the billing period:
curl -s -X POST https://billing-api.dev.stackngo.fr/v1/carts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "subscription",
"currency": "EUR",
"subscription": { "interval": "month", "interval_count": 1 },
"customer": {
"external_ref": "user-381",
"name": "Dupont Conseil",
"email": "compta@dupont.example",
"address": { "line1": "3 place Bellecour", "postal_code": "69002", "city": "Lyon", "country": "FR" }
},
"lines": [
{ "label": "Offre Pro", "quantity": "1", "unit_amount": "49.00", "tax_category": "S", "tax_rate": "20.00" }
],
"success_url": "https://shop.acme.example/bienvenue",
"tags": { "shop": "saas", "plan": "pro" }
}'
subscription | Values |
|---|---|
interval | day, week, month, year |
interval_count | 1 to 36 (default 1): "interval": "month", "interval_count": 3 = every quarter |
The response is a cart with its payment_url, as for a one-off payment. Once paid, the cart
carries subscription_id.
What you get
curl -s https://billing-api.dev.stackngo.fr/v1/subscriptions/sub_01J9ZR2B6C7D8E9F0G1H \
-H "Authorization: Bearer $TOKEN"
{
"id": "sub_01J9ZR2B6C7D8E9F0G1H",
"customer_id": "cus_01J9ZR1A2B3C4D5E6F7G",
"status": "active",
"currency": "EUR",
"lines": [
{ "label": "Offre Pro", "quantity": "1", "unit_amount": "49.00", "tax_category": "S", "tax_rate": "20.00", "amount": "49.00" }
],
"interval": "month",
"interval_count": 1,
"current_period_start": "2026-10-08T10:20:00Z",
"current_period_end": "2026-11-08T10:20:00Z",
"next_charge_at": "2026-11-08T10:20:00Z",
"cancel_at_period_end": false,
"created_at": "2026-10-08T10:20:00Z",
"tags": { "shop": "saas", "plan": "pro" }
}
At every period, the platform charges the saved payment method, issues an invoice and sends
you subscription.renewed and invoice.finalized.
status | Meaning |
|---|---|
incomplete | first period not paid yet |
active | up to date |
past_due | a period failed; retries are in progress |
unpaid | retries exhausted with dunning.finalAction: unpaid: the subscription stays, unpaid |
canceled | cancelled (by you, or after the retries with finalAction: cancel) |
2. Change plan
The new lines apply from the next period (no proration in this version):
curl -s -X PUT https://billing-api.dev.stackngo.fr/v1/subscriptions/sub_01J9ZR2B6C7D8E9F0G1H/lines \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "lines": [ { "label": "Offre Business", "quantity": "1", "unit_amount": "99.00", "tax_category": "S", "tax_rate": "20.00" } ] }'
Until the next period, they appear in pending_lines.
3. Cancel
curl -s -X POST https://billing-api.dev.stackngo.fr/v1/subscriptions/sub_01J9ZR2B6C7D8E9F0G1H/cancel \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "at_period_end": true }'
at_period_end: true (default): the subscription runs until current_period_end, then
becomes canceled. false: immediate cancellation, without automatic refund (see
Refunds and credit notes if you want to refund).
4. List subscriptions
curl -s "https://billing-api.dev.stackngo.fr/v1/subscriptions?customer_id=cus_01J9ZR1A2B3C4D5E6F7G&status=past_due" \
-H "Authorization: Bearer $TOKEN"
What you can expect
- One invoice per period, never two for the same period, even if a charge is retried.
- Dunning follows your account: after a failure, new attempts at the delays of
dunning.retryDelays, subscriptionpast_duein the meantime, thenunpaidorcanceleddepending ondunning.finalAction. Each step is notified to you (subscription.past_due,subscription.unpaid,subscription.canceled). - If your customer's bank requires strong authentication at a period, the charge fails and follows dunning; send them a portal link so they update their payment method.
- You inform your customer (renewal, failure, cancellation e-mails), based on the webhooks.
If it does not work
| What you see | Cause | Fix |
|---|---|---|
422 on subscription | subscription missing or invalid interval | give interval (and interval_count between 1 and 36) |
403 on creation | subscription not in billingModes, or carts scope missing | fix the BillingAccount |
409 on PUT …/lines or cancel | subscription already cancelled | create a new subscription |
Subscription stuck in incomplete | the first period was not paid | send a new cart |
Subscription past_due | charge failed at the period | portal link to the customer to change payment method |
See also Payments troubleshooting.