Skip to main content
This guide walks through setting up recurring payments using the Payment Sessions API. The first charge uses a first_in_series session to collect payment and save the customer’s payment method under a mandate. From there, subsequent charges are either triggered manually with a next_in_series session, or collected automatically by adding subscription_options to the mandate.

Prerequisites

  • A test API key. See Authentication.
  • A registered webhook endpoint. See Webhook Setup to register your URL and obtain your signing key.

Mandate types

A mandate is the customer’s consent to authorise future charges on their payment method. Creating a first_in_series session establishes a mandate that defines the boundaries and constraints for all subsequent payments, whether triggered manually or collected automatically via a subscription. By default, omitting mandate_options creates an unconstrained mandate, equivalent to on_demand with no declared intent. See Mandate Type for the full semantics of scheduled, on_demand, and installment, and which to use for merchant-triggered vs automated collection.

Supported payment methods

The following payment methods support recurring payments: See Supported Payment Methods for mandate type eligibility and requirements per payment method.

Part 1: Set up the mandate

Step 1: Create a first_in_series session

Create the session server-side. The customer must be present to complete this step. They will authorise their payment method for future charges via the hosted checkout.
amount is always specified in minor units. See Monetary Amounts for details.
To automate collection instead of triggering each payment manually, include subscription_options alongside mandate_options in this same request.See Part 2 below, and Subscriptions for the full reference.
The response includes a session_url for the customer to complete checkout, and a customer_id that was created for this customer.

Step 2: Launch the checkout

Redirect your customer to the session_url. During checkout, the customer completes their payment and authorises future charges to their payment method under the mandate.

Step 3: Capture the customer and payment method IDs

When the customer completes checkout, a payment_session.completed event is sent. The data object includes both a customer_id and a payment_method_id. Store both, as you will need them for every subsequent charge.
Verify the event signature before processing. See Webhook Verification.

Part 2: Collect subsequent payments

If you included subscription_options in Part 1, each subsequent payment is collected automatically on the schedule you defined; no further action is needed beyond listening for the subscription webhooks below. Otherwise, trigger each payment manually as follows:

Step 4: Create a next_in_series session

Use the customer_id and payment_method_id from Part 1. The customer is not present and the payment is processed immediately without any checkout step.
There is no session_url in the response. The payment processes automatically and a payment_id is returned immediately.

Step 5: Handle the completion webhook

A payment_session.completed event is sent once the payment is processed, with the same structure as in Part 1. Repeat Step 4 for each subsequent charge on the schedule your application manages.
If you’re using subscription_options instead, listen for subscription.created (fired once, after the first payment succeeds), and later subscription.cancelled or subscription.ended. See Subscription Webhooks.

Testing

Use test card 4242 4242 4242 4242 with any future expiry date and any 3-digit CVC for the first_in_series checkout. See Integration Testing for the full list of test cards and error scenarios.

Next steps

Mandates

Configure consent ceilings, recurrence rules, and validity periods for mandates.

Subscriptions

Automate the recurring schedule with subscription options.

Payment Method Verification

Set up a mandate without charging the customer upfront.

Authorisation and Capture

Reserve funds at checkout and capture or void them later.