Skip to main content

Overview

Payment methods are stored Paystack authorizations (cards) or direct debit mandates (bank accounts) that Surge uses to collect installment payments automatically.
Who calls these endpoints?Most merchant integrations do not call these endpoints directly. The Surge widget and the Surge consumer app handle payment method collection during checkout.These endpoints are relevant to you only if you are:
  • Building a custom consumer-facing experience (e.g. a white-label app where customers manage their Surge wallet)
  • Building the Surge consumer app itself
All endpoints require a customer JWT (the token for the shopper, not your merchant token). Customers may only access their own payment methods.

List Payment Methods

GET /api/v1/payment-methods/customers/{customer_id}
Authorization: Bearer <CUSTOMER_JWT>
Returns all saved payment methods for the given customer. Response
{
  "ok": true,
  "data": [
    {
      "id": "pm_abc123",
      "customer_id": "cust_xyz",
      "type": "card",
      "label": "Visa Card",
      "last4": "4081",
      "is_default": true,
      "created_at": "2026-03-16T10:00:00Z"
    }
  ],
  "total": 1
}

List Supported Banks

GET /api/v1/payment-methods/banks
Authorization: Bearer <CUSTOMER_JWT>
Returns the list of Nigerian banks supported by Paystack for direct debit mandates. Response
{
  "ok": true,
  "data": [
    { "name": "Access Bank", "code": "044" },
    { "name": "GTBank", "code": "058" }
  ]
}

Add Card — Initialize (Redirect Flow)

POST /api/v1/payment-methods/initialize-card
Authorization: Bearer <CUSTOMER_JWT>
Initializes a Paystack transaction for card tokenization. Returns an authorization_url to redirect the customer to. On completion, Paystack redirects to callback_url?reference=xxx and the frontend calls /verify-card. A ₦50 verification charge (5000 kobo) is applied to confirm the card is active. This amount is refunded after successful verification. Request
{
  "customer_id": "cust_xyz",
  "callback_url": "https://yourapp.com/payment-return",
  "is_default": true
}
Response
{
  "ok": true,
  "authorization_url": "https://checkout.paystack.com/...",
  "reference": "txn_abc123"
}

Add Card — Verify and Save

POST /api/v1/payment-methods/verify-card
Authorization: Bearer <CUSTOMER_JWT>
After the customer returns from the Paystack redirect, verify the transaction reference and save the card as a payment method. Request
{
  "customer_id": "cust_xyz",
  "reference": "txn_abc123",
  "is_default": true
}
Response
{
  "ok": true,
  "data": {
    "id": "pm_abc123",
    "customer_id": "cust_xyz",
    "type": "card",
    "label": "Visa Card",
    "last4": "4081",
    "is_default": true,
    "created_at": "2026-03-16T10:00:00Z"
  }
}

Add Bank — Initiate Direct Debit Mandate

POST /api/v1/payment-methods/customers/{customer_id}/initiate-bank-mandate
Authorization: Bearer <CUSTOMER_JWT>
Starts the Paystack direct debit mandate flow. Paystack sends an OTP to the phone number registered to the bank account (via BVN). Request
{
  "bank_code": "058",
  "account_number": "0123456789",
  "is_default": true
}
Response — OTP required
{
  "ok": true,
  "next_action": "submit_otp",
  "reference": "txn_abc123",
  "display_text": "Enter the OTP sent to your phone ending in 1234."
}
Response — Web authorization required (open_url)
{
  "ok": true,
  "next_action": "open_url",
  "reference": "txn_abc123",
  "display_text": "Authorize in the popup window.",
  "url": "https://standard.paystack.co/..."
}
Possible next_action values: submit_otp, submit_birthday, submit_phone, open_url, success.

Add Bank — Submit OTP

POST /api/v1/payment-methods/bank-mandate/submit-otp
Authorization: Bearer <CUSTOMER_JWT>
Request
{
  "customer_id": "cust_xyz",
  "reference": "txn_abc123",
  "otp": "123456",
  "bank_code": "058",
  "bank_name": "GTBank",
  "account_number": "0123456789",
  "is_default": true
}
Response — success
{
  "ok": true,
  "next_action": "success",
  "data": { "id": "pm_abc123", "type": "bank", "label": "GTBank •••• 6789", ... }
}
Response — additional step required
{
  "ok": true,
  "next_action": "submit_birthday",
  "display_text": "Enter your date of birth to complete verification."
}

Add Bank — Submit Birthday

POST /api/v1/payment-methods/bank-mandate/submit-birthday
Authorization: Bearer <CUSTOMER_JWT>
Request
{
  "customer_id": "cust_xyz",
  "reference": "txn_abc123",
  "birthday": "1990-05-15",
  "bank_code": "058",
  "bank_name": "GTBank",
  "account_number": "0123456789",
  "is_default": true
}

Add Bank — Submit Phone

POST /api/v1/payment-methods/bank-mandate/submit-phone
Authorization: Bearer <CUSTOMER_JWT>
Request
{
  "customer_id": "cust_xyz",
  "reference": "txn_abc123",
  "phone": "08012345678",
  "bank_code": "058",
  "bank_name": "GTBank",
  "account_number": "0123456789",
  "is_default": true
}

Add Bank — Verify Open URL Mandate

POST /api/v1/payment-methods/bank-mandate/verify
Authorization: Bearer <CUSTOMER_JWT>
Used after the customer completes the Paystack open_url popup flow. Verifies the transaction reference and saves the bank as a payment method. Request
{
  "customer_id": "cust_xyz",
  "reference": "txn_abc123",
  "bank_code": "058",
  "bank_name": "GTBank",
  "account_number": "0123456789",
  "is_default": true
}
Response
{
  "ok": true,
  "next_action": "success",
  "data": { "id": "pm_abc123", "type": "bank", "label": "GTBank •••• 6789", ... }
}

Set Default Payment Method

PUT /api/v1/payment-methods/{method_id}/default
Authorization: Bearer <CUSTOMER_JWT>
Marks the given method as the customer’s default, clearing the default flag from all other methods. Response
{ "ok": true, "message": "Default payment method updated." }

Delete Payment Method

DELETE /api/v1/payment-methods/{method_id}
Authorization: Bearer <CUSTOMER_JWT>
Removes a saved payment method. Response
{ "ok": true, "message": "Payment method removed." }