Subscriptions
Charge a customer a fixed amount on a recurring schedule.
Overview
A subscription charges a saved card at a fixed price every billing period: daily, weekly, monthly or yearly. The customer pays the first period at signup. MoonlinkPay saves the card during that payment and charges it automatically at the start of each later period, with nobody present.
You set the price on the subscription itself. There is no product catalogue to set up.
Before you start. Recurring charges need a connector that can store a card for later payments. If renewals are not enabled for your connector, the signup still succeeds but the first renewal fails, so contact support to confirm your connector is enabled before going live.
How signup works
Choose one of two ways to take the first payment.
| Flow | Calls | Use it when |
|---|---|---|
| One step | POST /subscriptions | Your server has the card details, or a saved payment_method_id. The subscription is created and charged in one call. |
| Two step | POST /subscriptions/create, then POST /subscriptions/:id/confirm | You collect the card on a checkout page. Your server creates the subscription and gets a client_secret; the checkout page uses it to confirm with the card. Nothing is charged until confirm. |
Both flows need:
- An existing customer, or customer details in the request. See Customer.
- A
merchant_reference_id, your own unique order reference. It protects against charging twice: a retried create with the same reference is refused instead of creating a second subscription. setup_future_usage: "off_session", so the card is saved for renewals.
3D Secure on the first payment
If the first payment needs 3D Secure, the response has status: "created" and the payment has a next_action with a redirect URL. Send the customer there. When they return, the payment completes and the subscription becomes active within a few seconds. Renewals are charged off-session and do not ask the customer to authenticate again.
Customer
customer_id must belong to an existing customer, unless the request also includes a customer object with at least one of name, email, phone or phone_country_code. In that case a missing customer is created first. An existing customer is never changed by a subscription request. A customer_id that does not exist, sent without details, is refused, so a mistyped ID fails instead of creating a new customer.
Renewals
At the start of each period MoonlinkPay creates an invoice and charges the saved card.
- Paid: the subscription moves to the next period and the next renewal is scheduled. You receive
invoice_paid. - Declined: the subscription stays
activeand the charge is retried 1 day later, then twice more 2 days apart. You receiveinvoice_payment_failedfor every declined attempt. If the last retry also fails, the subscription becomesunpaidand you receivesubscription_unpaid. - Hard decline or removed card: if the decline means retrying cannot help, for example a closed card, or the saved card was deleted, there are no retries. The subscription becomes
unpaidstraight away. - Pending: if the payment is still processing, MoonlinkPay checks it again later and never charges a second time while it is unresolved.
A new price set with Update applies from the next period. Retries of a declined invoice charge the amount that was invoiced.
Ending a subscription
- Cancel now: cancel with
cancel_option: "immediately". No further charges. - Cancel at period end:
cancel_option: "end_of_term". The subscription staysactiveuntil the period the customer paid for ends, then it is cancelled without charging again. - Fixed number of payments: set
total_billing_cyclesat signup. After the last paid period, the subscription ends by itself.
You receive subscription_cancelled when a subscription ends in any of these ways. Cancelling never refunds a payment that was already taken.
Pause and resume
Pause stops billing: nothing is charged while a subscription is paused. Resume starts it again:
- If a period is still unpaid, it is charged straight away. If that charge declines, the subscription is
unpaidagain. - Otherwise the next charge is one billing period after you resume.
To restart billing on an unpaid subscription after the customer has fixed their card, pause it and then resume it.
Statuses
| Status | Meaning |
|---|---|
created | Waiting for the first payment: a two-step signup not yet confirmed, or a first payment waiting for 3D Secure. |
active | Paid up and renewing. Also the status while a declined renewal is being retried. |
unpaid | A renewal could not be collected. Billing has stopped. |
paused | Billing is stopped until you resume. |
cancelled | Ended. Nothing more is charged. |
failed | The first payment failed. Final; create a new subscription to try again. The same merchant_reference_id can be reused. |
Webhooks
| Event | Sent when |
|---|---|
invoice_paid | A payment for the subscription succeeded, at signup or on renewal. |
invoice_payment_failed | A renewal payment was declined, one event per attempt. Also sent when a first payment fails after 3D Secure. |
subscription_unpaid | Billing stopped because a renewal could not be collected. |
subscription_cancelled | The subscription ended: cancelled now, at period end, or after its last paid period. |
The payload contains the subscription, its latest invoice and, when there is one, the payment. See Webhook event types.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /subscriptions | Create and Confirm Subscription |
POST | /subscriptions/create | Create Subscription |
POST | /subscriptions/:subscription_id/confirm | Confirm Subscription |
GET | /subscriptions/estimate | Get Subscription Price |
GET | /subscriptions/:subscription_id | Retrieve Subscription |
GET | /subscriptions/list | List Subscriptions |
PUT | /subscriptions/:subscription_id/update | Update Subscription |
POST | /subscriptions/:subscription_id/pause | Pause Subscription |
POST | /subscriptions/:subscription_id/resume | Resume Subscription |
POST | /subscriptions/:subscription_id/cancel | Cancel Subscription |
Every subscription request needs the api-key header. The business profile works as it does for payments: send profile_id when you create a subscription, or leave it out to use your default profile. Calls on an existing subscription use that subscription's profile, so they need no profile at all. The X-Profile-Id header is still accepted, but not required. The confirm and price endpoints can also be called from a browser with your publishable key and the subscription's client_secret.