API Docs
Subscriptions
API ReferenceSubscriptions

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.

FlowCallsUse it when
One stepPOST /subscriptionsYour server has the card details, or a saved payment_method_id. The subscription is created and charged in one call.
Two stepPOST /subscriptions/create, then POST /subscriptions/:id/confirmYou 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 active and the charge is retried 1 day later, then twice more 2 days apart. You receive invoice_payment_failed for every declined attempt. If the last retry also fails, the subscription becomes unpaid and you receive subscription_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 unpaid straight 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 stays active until the period the customer paid for ends, then it is cancelled without charging again.
  • Fixed number of payments: set total_billing_cycles at 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 unpaid again.
  • 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

StatusMeaning
createdWaiting for the first payment: a two-step signup not yet confirmed, or a first payment waiting for 3D Secure.
activePaid up and renewing. Also the status while a declined renewal is being retried.
unpaidA renewal could not be collected. Billing has stopped.
pausedBilling is stopped until you resume.
cancelledEnded. Nothing more is charged.
failedThe first payment failed. Final; create a new subscription to try again. The same merchant_reference_id can be reused.

Webhooks

EventSent when
invoice_paidA payment for the subscription succeeded, at signup or on renewal.
invoice_payment_failedA renewal payment was declined, one event per attempt. Also sent when a first payment fails after 3D Secure.
subscription_unpaidBilling stopped because a renewal could not be collected.
subscription_cancelledThe 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

MethodEndpointDescription
POST/subscriptionsCreate and Confirm Subscription
POST/subscriptions/createCreate Subscription
POST/subscriptions/:subscription_id/confirmConfirm Subscription
GET/subscriptions/estimateGet Subscription Price
GET/subscriptions/:subscription_idRetrieve Subscription
GET/subscriptions/listList Subscriptions
PUT/subscriptions/:subscription_id/updateUpdate Subscription
POST/subscriptions/:subscription_id/pausePause Subscription
POST/subscriptions/:subscription_id/resumeResume Subscription
POST/subscriptions/:subscription_id/cancelCancel 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.