Skip to main content

Subscriptions

Beta

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​

  • subscription in billingModes of your payment account.
  • A token with the carts (create the subscription) and subscriptions (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" }
}'
subscriptionValues
intervalday, week, month, year
interval_count1 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.

statusMeaning
incompletefirst period not paid yet
activeup to date
past_duea period failed; retries are in progress
unpaidretries exhausted with dunning.finalAction: unpaid: the subscription stays, unpaid
canceledcancelled (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, subscription past_due in the meantime, then unpaid or canceled depending on dunning.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 seeCauseFix
422 on subscriptionsubscription missing or invalid intervalgive interval (and interval_count between 1 and 36)
403 on creationsubscription not in billingModes, or carts scope missingfix the BillingAccount
409 on PUT …/lines or cancelsubscription already cancelledcreate a new subscription
Subscription stuck in incompletethe first period was not paidsend a new cart
Subscription past_duecharge failed at the periodportal link to the customer to change payment method

See also Payments troubleshooting.

See also​