Recurring Charges

In A Nutshell
In a nutshell

Once a customer has made the first successful payment with their card, you can store the customer's card authorization and use it for subsequent transactions. This currently only works for card!

Charge the first transaction

You can initialize this first charge from web or your mobile app. Check out the different integration methods for web and mobile.

Why do I need to charge the user to add their cards?

  1. Local regulations require that users authenticate the card through 2FA in an initial transaction before we can charge the card subsequently.
  2. It allows us to ensure that the card is valid and can be charged for subsequent transactions.
Minimum charge amount

The minimum amount we recommend for the first charge is NGN 50.00, GHS 0.10, ZAR 1.00, or USD 0.20. Lower amounts are not guaranteed to work on all card brands or banks.

It is standard practice to credit the user back with value (in your app) worth the tokenization amount, or simply refund the money back.

Get the Card authorization

If the first transaction is successful, you can listen to events on your webhook endpoint. Alternatively, you can use the Verify TransactionAPI endpoint to confirm the status of the transaction. In either case, the response looks like the sample below:

2 "data": {
3 "authorization": {
4 "authorization_code": "AUTH_8dfhjjdt",
5 "card_type": "visa",
6 "last4": "1381",
7 "exp_month": "08",
8 "exp_year": "2018",
9 "bin": "412345",
10 "bank": "TEST BANK",
11 "channel": "card",
12 "signature": "SIG_idyuhgd87dUYSHO92D",
13 "reusable": true,
14 "country_code": "NG",
15 "account_name": "BoJack Horseman"
16 }
17 }

You'll notice that the data object in the response contains an authorization object within it, which contains the details of the payment instrument (card in this case) that the user paid with.

authorization_codeThis is the code that is used to charge the card subsequently
card_typeThis tells you the card brand - Visa, Mastercard, etc
last4The last 4 digits of the card. This is one of the details you can use to help the user identify the card
exp_month The expiry month of the card in digits. Eg. "01" means January
exp_yearThe expiry year of the card
binThe first 6 digits of the card. This and the last 4 digits constitute the masked pan
bankThe customer's bank, the bank that issued the card
channelWhat payment channel this is. In this case, it is a card payment
signatureA unique identifier for the card being used. While new authorization codes are created each time a card is used, the card's signature will remain the same.
reusableA boolean flag that tells you if an authorization can be used for a recurring charge. You should only attempt to use the authorization_code if this flag returns as true.
country_codeA two-letter country code (ISO 3166-1 alpha-2) representing the country of the bank where the card was issued

Store the authorization

Next, you need to store the authorization and the email used for the transaction. These details can be used to charge the card subsequently. Every payment instrument that is used on your site/app has a unique signature . The signature can be used to ensure that you do not save an authorization multiple times.


It is important to store the entire authorization object in order not to lose any context regarding the card.

It is also important to store the email used to create an authorization because only the email used to create an authorization can be used to charge it. If you rely on the user's email stored on your system and the user changes it, the authorization can no longer be charged.

When you have the whole authorization object saved, you can display customer payment details at the point of payment to charge recurrently. For example, when the user wants to pay again, you can display the card for the user as Access Bank Visa card ending with 1234.

Charge the authorization

When the user selects the card for a new transaction or when you want to charge them subsequently, you send the authorization_code, user's email and the amount you want to charge to the charge authorizationAPI.

Show Response
2-H "Authorization: Bearer YOUR_SECRET_KEY"
3-H "Content-Type: application/json"
4-d '{ "authorization_code" : "AUTH_pmx3mgawyd",
5 email: "",
6 amount: "300000"
7 }'
2 "status": true,
3 "message": "Charge attempted",
4 "data": {
5 "amount": 300000,
6 "currency": "NGN",
7 "transaction_date": "2020-05-27T11:45:03.000Z",
8 "status": "success",
9 "reference": "cn65lf4ixmkzvda",
10 "domain": "test",
11 "metadata": "",
12 "gateway_response": "Approved",
13 "message": null,
14 "channel": "card",
15 "ip_address": null,
16 "log": null,
17 "fees": 14500,
18 "authorization": {
19 "authorization_code": "AUTH_pmx3mgawyd",
20 "bin": "408408",
21 "last4": "4081",
22 "exp_month": "12",
23 "exp_year": "2020",
24 "channel": "card",
25 "card_type": "visa DEBIT",
26 "bank": "Test Bank",
27 "country_code": "NG",
28 "brand": "visa",
29 "reusable": true,
30 "signature": "SIG_2Gvc6pNuzJmj4TCchXfp",
31 "account_name": null
32 },
33 "customer": {
34 "id": 23215815,
35 "first_name": null,
36 "last_name": null,
37 "email": "",
38 "customer_code": "CUS_wt0zmhzb0xqd4nr",
39 "phone": null,
40 "metadata": null,
41 "risk_action": "default"
42 },
43 "plan": null,
44 "id": 696105928
45 }
Charging at intervals

If your application needs to charge the authorizations at certain intervals, it means your server needs to have a cron job that runs at particular intervals and picks all the authorizations that needs to be charged.

Two Factor Authentication

Feature Availability

By default, this feature is available to betting merchants with a Nigerian integration and specific to cards issued by Guaranty Trust Bank (GTB), Access Bank, United Bank for Africa (UBA), Zenith Bank & First Bank of Nigeria. If you have a Nigerian integration and would like to get this feature, kindly send an email to

Two Factor Authentication (2FA) is an extra security step taken to confirm that you aren’t processing the request of a malicious actor. The user making the request is generally asked to provide some form of information that is unique to them.

In order to ensure a user’s card isn’t being used by a malicious actor, we challenge the user by asking the user to authorize the transaction. Authorization can be done by using a hardware token, OTP, PIN + OTP, or 3DS.

The request to charge the card remains the same. However, the response is different for cards that will be challenged:

2 "status": true,
3 "message": "Please, redirect your customer to the authorization url provided",
4 "data": {
5 "authorization_url": "",
6 "reference": "jvx2o36ghlvrgtt",
7 "access_code": "0744ub5o065nwyz",
8 "paused": true
9 }

When a card is challenged, the response will contain two distinct parameters among others:

pausedbooleanReturns true when a card is being challenged
authorization_urlstringA checkout URL for authorization of the transaction

You should check the value of the data.paused parameter to confirm if a card is being challenged. If it’s being challenged, you should redirect the user to the data.authorization_url to complete the authorization.

Image of the checkout page for user authorization

On completion of the authorization, we proceed to charge the user's card. You should save the data.reference value to verify the status of the transaction either via webhooks or the verify transactionAPI.

Handling redirect

When the user completes the authorization process, we typically redirect the user back to the callback URL you’ve set on your Paystack Dashboard. If you want us to redirect to a different URL, you can add the URL to the callback_url parameter of your request:

2 "authorization_code": "AUTH_ibegucp8kk",
3 "email": "",
4 "amount": 3000,
5 "callback_url": ""

The user might also cancel the authorization process. You can add a URL that the user should be redirected to when they cancel in the metadata object:

2 "authorization_code": "AUTH_ibegucp8kk",
3 "email": "",
4 "amount": 3000,
5 "metadata": {
6 "cancel_action": ""
7 }