Skip to main content
Payment method verification allows merchants to confirm that a payment method is valid and vault it for future use without charging the customer. It is initiated by creating a session with amount: 0. Two session types are supported depending on the intended future payment flow:
  • one_time with save_payment_method: always: verifies and saves the payment method for future customer-initiated payments such as repeat purchases
  • first_in_series: verifies the payment method and creates a mandate for future merchant-initiated payments such as subscriptions and recurring charges
This is commonly used for:
  • Card on file setup where the customer saves a payment method for future purchases without being charged immediately
  • Free trials where the first charge happens after the trial period ends
  • Subscription sign-ups with a deferred first billing cycle

Card on File

Use one_time with amount: 0 and save_payment_method: always to verify and save a payment method for future customer-initiated purchases. save_payment_method: always is required. Omitting it or using any other value when amount: 0 is an API error.
POST /collect/payment_sessions

{
  "amount": 0,
  "currency": "ZAR",
  "type": "one_time",
  "options": {
    "checkout_options": { "return_url": "https://merchant.example/return" },
    "payment_method_options": {
      "card": {
        "save_payment_method": "always"
      }
    }
  }
}
No mandate is created. The payment method is saved and available for future customer-present payments.
1. Customer creates an account on an e-commerce platform
2. Create one_time session with amount: 0 and save_payment_method: always
3. Payment method is verified and saved
4. Webhook: payment.succeeded (authorised_amount: 0)
5. Customer makes a purchase later → new one_time session using the saved payment method

Recurring Setup

Use first_in_series with amount: 0 to verify the payment method and create a mandate in a single step. No initial payment is taken. For full details on configuring the mandate created at this step, see Mandates.
POST /collect/payment_sessions

{
  "amount": 0,
  "currency": "ZAR",
  "type": "first_in_series",
  "options": {
    "customer": {
      "name": "Jane",
      "email": "jane@example.com"
    },
    "checkout_options": { "return_url": "https://merchant.example/return" },
    "mandate_options": {
      "type": "scheduled",
      "recurrence": {
        "type": "monthly",
        "interval_count": 1
      }
    }
  }
}
On completion, the mandate is created and available for future next_in_series payments. No capture or void is needed.
1. Customer signs up for a 14-day free trial
2. Create first_in_series session with amount: 0
3. Payment method is verified, mandate created
4. Webhook: payment.succeeded (authorised_amount: 0)
5. After trial ends → create next_in_series session to charge the first billing cycle

Payment Object on Success

On successful verification, the payment object reflects zero amounts. The intent field is set to payment_method_verification to make the nature of the payment explicit:
{
  "id": "pay_Vn8kLmQ2rTwX4y",
  "status": "succeeded",
  "intent": "payment_method_verification",
  "amount": 0,
  "currency": "ZAR",
  "authorised_amount": 0,
  "paid_amount": 0,
  "voided_amount": 0,
  "country": "ZA",
  "payment_method_details": {
    "type": "card",
    "card": {
      "type": "CREDIT",
      "scheme": "VISA",
      "bin": "411111",
      "last4": "1234"
    }
  }
}
No capture or void is required after verification.

Webhooks

  • payment.succeeded: fired when verification succeeds. intent is payment_method_verification and authorised_amount is 0.
See the Payments API Overview for the full list of webhook events.