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:
| Parameter | Type | Required | Description |
|---|---|---|---|
recurring_init | boolean | optional | Set 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_id | string | optional | Schedule the later charges follow. Without it, you charge by request instead. |
schedule_start_date | string (YYYY-MM-DD) | optional | Date of the first scheduled charge, for a trial period. Requires schedule_id. |
payment_schedule_amount | string | optional | Amount of the later scheduled charges when it differs from this payment. Requires schedule_id. |
recurring_consent_required | boolean | optional | Shows 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_idandrecurring_tokenthe 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_idin 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.
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.
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_tokenand 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.
Consent on the payment page
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_initand the other recurring parameters are ignored, the payment is processed as a one-time purchase, and no consent is created.
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.
Showing the consent checkbox on the Checkout page
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_requiredentirely 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 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 requiredrecurring_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.
Consent states
A consent exists only when the payer confirmed it. consent_state reports the state of that consent:
| Value | Meaning |
|---|---|
active | The payer confirmed and the consent is in force. |
cancelled | The consent was cancelled in the admin panel. The schedule is deactivated, so subsequent scheduled charges stop. |
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 alwaysignored; - 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_dataobject.
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 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.
| Callback | Payer confirmed | Payer did not confirm |
|---|---|---|
recurring_token | present | absent |
consent_id, consent_state, consent_assign_date | present, consent_state is active | absent |
extended_data[consent_state] | absent | ignored |
| Subscription created | yes | no |
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.