Skip to main content

Recurring

Recurring payments

Recurring is for regular charges, a subscription or any repeat billing where the payer makes the first payment and the later ones are initiated without them. That first payment has to be an initial recurring payment: send recurring_init: true with a purchase, and the callback returns a recurring_token for the stored card.

Starting a subscription

Send these in the session request alongside the usual purchase parameters:

ParameterTypeRequiredDescription
recurring_initbooleanoptionalSet to true to make this payment an initial recurring payment, which stores the card and returns a recurring_token. Defaults to false. Valid only for purchase.
schedule_idstringoptionalSchedule the later charges follow. Without it, you charge by request instead.
schedule_start_datestring (YYYY-MM-DD)optionalDate of the first scheduled charge, for a trial period. Requires schedule_id.
payment_schedule_amountstringoptionalAmount of the later scheduled charges when it differs from this payment. Requires schedule_id.
recurring_consent_requiredbooleanoptionalShows the consent element on the payment page, see Consent on the payment page. Requires schedule_id. Default false.

The relevant part of the session request:

{
"operation": "purchase",
"order": {
"number": "order-1786008484205",
"amount": "10.00",
"currency": "USD",
"description": "Monthly plan"
},
"recurring_init": true,
"recurring_consent_required": true,
"schedule_id": "9d0f5cc4-f07b-11ec-abf4-0242ac120006",
"schedule_start_date": "2026-09-01",
"payment_schedule_amount": "19.99"
}

Charging after the first payment

  • By request. Charge with Recurring Sale, passing the recurring_init_trans_id and recurring_token the initial payment returned. If a charge comes back as a soft decline, Retry attempts it again on the same payment.
  • By schedule. Send a schedule_id in the initial request and the platform runs the later charges on that schedule, with no further calls from you. Schedules are set up by the system admin in the admin panel, who gives you the identifier to use.

Each later charge produces its own callback, with type set to recurring. See Callbacks.

A declined scheduled charge can end the subscription

What happens next depends on whether a retry schedule is configured for you.

  • With a retry schedule, the subscription pauses and the retry schedule takes over, using its own intervals and number of attempts. If one attempt succeeds, the subscription resumes on its normal interval. If all of them fail, it stays stopped.
  • Without one, the platform retries the charge up to three times, about 10 hours apart. If one succeeds, the subscription continues. If all three fail, it stops.

Either way nothing notifies you that the subscription itself stopped, so watch the callbacks of the scheduled charges or poll the status. A subscription stopped this way needs a new initial recurring payment to start again.

Stopping a subscription

The Checkout protocol has no request for this. A subscription is stopped from the admin panel, on the transaction that started it, in one of two ways:

  • Deschedule stops the remaining scheduled charges for that payment and leaves the consent, if there is one, in place.
  • Cancel consent stops the schedule as well and marks the consent cancelled, so it can no longer be used. See Consent states.

A subscription also ends by itself once it has made the number of payments its schedule defines.

Two things that do not stop it: a chargeback and a refund. The later charges continue, so stop the subscription yourself if a dispute means it should not run again.

None of this sends you a callback, so poll the status if you need to detect it. If you also work over the S2S Card protocol, the same schedule can be stopped there with DESCHEDULE.

Recurring has to be enabled for you first

It is not available by default, and the two things that can be missing fail in different ways.

  • Recurring is not enabled on the MID. The payment still goes through, but as an ordinary one, with no recurring_token and no subscription. This is the one to check first when a request looks accepted and the token is simply absent.
  • No limit exists for the recurring payment method, on the MID or on your merchant mapping. The charge is declined.

The connector also has to support recurring, and the acquirer has to allow it for that MID, so ask your account manager to confirm all of this before you integrate.

Checkout can show a consent element that lets the payer decide, on the payment page, whether this payment starts a subscription.

The element never blocks the payment. It only controls how the payment is processed:

  • Payer confirms it - the payment is processed as an initial recurring payment, a consent is created, and the callback carries a recurring_token.
  • Payer leaves it unconfirmed - the Pay button still works. recurring_init and the other recurring parameters are ignored, the payment is processed as a one-time purchase, and no consent is created.
note

Consent applies to the purchase operation paid by card, including payment with a saved card_token. recurring_init is rejected for debit, so consent cannot be used there, and the element plays no part in credit, transfer, crypto or APM payments.

How it works

You ask for the element in the session request, the payer decides on the payment page, and the callback tells you which way it went. The states a consent can be in are described in Consent states, the refusal case in If the payer ignores the checkbox, and the callback fields in Telling the two outcomes apart.

Send a normal purchase request with recurring_init: true and a schedule_id. On top of that, the element appears when either of these is true:

  • the request contains recurring_consent_required: true; or
  • the request omits recurring_consent_required entirely and the merchant-level setting Recurring Consent Required is enabled for you.

The request parameter wins whenever it is present: sending recurring_consent_required: false suppresses the element even if the merchant-level setting is on. The merchant-level setting is consulted only when the parameter is absent.

recurring_init: true is a precondition - without it the element is never shown, whatever the parameter and the merchant setting say.

The element is headed Customer consent and the checkbox is unticked by default. Next to it the payer sees a statement with the charge amount, how often the charges repeat according to the schedule, and the date of the next charge. The Pay button stays enabled whether or not the box is ticked.

The amount in the statement is the amount of this payment

The statement shows order.amount of this request. If you send payment_schedule_amount because the later charges differ, for example a trial price followed by the full price, the statement still shows this payment's amount, so the figure the payer sees will not match the charges that follow.

schedule_id is required

recurring_consent_required: true without a schedule_id is rejected at validation with Consent requires scheduled recurring payments (schedule_id). - the session is not created at all.

If the schedule_id passes validation but the schedule cannot be resolved, the element is not shown and the payment proceeds as an ordinary initial recurring, with no error. So if you expect the consent element and the session was created without complaint, check that the schedule still exists.

The parameters that start the subscription are listed under Starting a subscription; recurring_consent_required is the one that adds the consent element on top of them.

A consent exists only when the payer confirmed it. consent_state reports the state of that consent:

ValueMeaning
activeThe payer confirmed and the consent is in force.
cancelledThe consent was cancelled in the admin panel. The schedule is deactivated, so subsequent scheduled charges stop.
Cancellation is not pushed to you

Cancelling a consent sends no callback. If you need to know that a subscription was stopped, poll the status - the consent fields, including consent_state and consent_cancellation_date, are returned there.

The consent belongs to the whole recurring chain, not just to the payment that created it. Every later scheduled charge returns the same consent_id and its current state, so you can tell at any point whether the subscription behind a charge is still authorized.

The same consent fields are also returned by the status lookups - by payment_id and by order_id - and by the S2S Card GET_TRANS_STATUS, GET_TRANS_DETAILS and GET_TRANS_STATUS_BY_ORDER responses, so a subscription started through Checkout can be inspected from either protocol.

If the payer ignores the checkbox

If the payer leaves the checkbox unticked and pays, the payment goes through as a one-time Sale. The recurring parameters you sent are skipped, no subscription is created, and no consent object exists.

The refusal is reported in the callback as extended_data[consent_state] with the value ignored:

  • it is the only consent-related key delivered in extended_data, and its value is always ignored;
  • none of the other consent fields are sent, because there is no consent to describe;
  • it arrives only when extended data is enabled for you under Protocol Mapping (admin panel -> Configuration -> Protocol Mappings -> Add Data to);
  • it is stored on the payment, not just sent once, so the status lookups return it in the same extended_data object.

ignored is not a third value of the consent_state described above. That one reports the state of a consent that exists; this one records a decision that prevented a consent from being created at all. They are two different parameters that happen to share a name, which is why this one travels inside extended_data.

If the payer abandons the page

If the payer closes Checkout without confirming and without paying, no payment is created, so no callback is sent.

Telling the two outcomes apart

Check whether the callback contains recurring_token.

CallbackPayer confirmedPayer did not confirm
recurring_tokenpresentabsent
consent_id, consent_state, consent_assign_datepresent, consent_state is activeabsent
extended_data[consent_state]absentignored
Subscription createdyesno

Both are callbacks for the payment the payer just made, so type is sale and order_status reflects the payment result either way - settled, decline, and so on. A payment where the payer declined the subscription is still a normal, successful payment, and type alone will not tell you which of the two happened. Use recurring_token.

See Callbacks for the full parameter list.

Callback when the payer confirmed

id=2de54f5e-9179-11f1-8f8b-4a53226d1518
order_number=1786008484205
order_amount=10.00
order_currency=USD
order_status=settled
type=sale
status=success
card=411111******1111
recurring_token=9a2f-0242c0a87002
consent_id=214702fa-8757-11f1-a356-6ab755d0181b
consent_state=active
consent_assign_date=2026-08-06 09:28:28
hash=eba55b2e0ebea511d3c174c1de08f6bbde873828

recurring_token is the value you store and send in later recurring requests.

Callback when the payer did not confirm

id=2de54f5e-9179-11f1-8f8b-4a53226d1518
order_number=1786008484205
order_amount=10.00
order_currency=USD
order_status=settled
type=sale
status=success
card=411111******1111
extended_data[consent_state]=ignored
hash=eba55b2e0ebea511d3c174c1de08f6bbde873828

There is no recurring_token and no consent_id, because no consent and no subscription were created.