Introduction
NIBSS E-Mandate allows merchants to debit customers' Nigerian bank accounts repeatedly. This service helps you to support direct debit as a payment option for subscription and recurring payments.
Merchants can collect payments for loans, package subscriptions and other recurring payment use cases using this payment method.
This method is available for only Naira (NGN) Payments.
How does E-Mandate work?
This payment method enables businesses to securely tokenize a customer's bank account after the customer has given consent, allowing for future debits directly from the account.
Just like card tokenization, the merchant needs to first generate a token for the customer's account. This token maps the customer's account details and authorization to a token, allowing the merchant to charge the customer.
A customer can tokenize their account multiple times with different merchants that use Flutterwave.
Once the customer's account is tokenized, the merchant can charge it until the token expires. For details on token expiry, refer to the token generation section.
Requirements
You need to meet the following requirements before integrating this payment method:
- Account status: Your account needs to be approved for live payments.
- Request payment method: You'll need to request access to this payment method from our support team. Send us an email to hi@flutterwavego.com.
- Set up transaction webhooks on your account to receive the token after authorizing the mandate.
Payment flow
Follow these steps to complete a direct debit:
- Initiate token generation: Send the customer's bank details along with other necessary information to create a mandate.
- Authorize the mandate: This process requires the customer to give consent for their bank account to be tokenized by the merchant.
- Query the token status: Merchants can query the
get account token
endpoint to confirm the current status of the token. Verifying the token's status before initiating a charge ensures it’s active and ready for use. - Charge a customer using the token: Once the token is active, proceed to charge the customer's bank account directly using the token.
Token generation
To generate a token for the customer, You need to collect the customer's details (email
, address
, account_bank
and account_number
). From your server, send a request to create account token endpoint with the customer information, transaction amount and token expiry date (end_date
).
{
"email": "user@example.com",
"amount": "100",
"address": "XYZ Example Street, Example City.",
"phone_number": "08081806271",
"account_bank": "058",
"account_number": "0002093777",
"start_date": "2024-06-22T01:28:00.000Z", # optional
"end_date": "2025-04-04T01:28:00.000Z",
"narration": "e-Mandate token for tester", # optional
}
Important notes
- The
start_date
andnarration
are optional. - The specified
start_date
must be at least one day after the current date. - The maximum value for
end_date
is 365 days (one year) from thestart_date
. - Not all NG banks are supported on this feature, Here is a comprehensive list of supported banks.
{
{
"id": 5,
"code": "011",
"name": "First Bank PLC"
},
{
"id": 2,
"code": "023",
"name": "Citi Bank"
},
{
"id": 14,
"code": "032",
"name": "Union Bank PLC"
},
{
"id": 13,
"code": "035",
"name": "United Bank for Africa"
},
{
"id": 15,
"code": "032",
"name": "Wema Bank PLC"
},
{
"id": 1,
"code": "044",
"name": "Access Bank"
},
{
"id": 14,
"code": "032",
"name": "Union Bank PLC"
},
{
"id": 4,
"code": "050",
"name": "EcoBank PLC"
},
{
"id": 16,
"code": "057",
"name": "Zenith bank PLC"
},
{
"id": 8,
"code": "058",
"name": "Guaranty Trust Bank"
},
{
"id": 11,
"code": "068",
"name": "Standard Chaterted bank PLC"
},
{
"id": 7,
"code": "078",
"name": "Fidelity Bank"
},
{
"id": 9,
"code": "076",
"name": "Polaris bank"
},
{
"id": 183,
"code": "082",
"name": "Keystone Bank"
},
{
"id": 231,
"code": "100",
"name": "Suntrust Bank"
},
{
"id": 18,
"code": "101",
"name": "ProvidusBank PLC"
},
{
"id": 6,
"code": "214",
"name": "First City Monument Bank"
},
{
"id": 17,
"code": "215",
"name": "Unity Bank PLC"
},
{
"id": 10,
"code": "221",
"name": "Stanbic IBTC Bank"
},
{
"id": 12,
"code": "232",
"name": "Sterling Bank PLC"
},
{
"id": 184,
"code": "301",
"name": "Jaiz Bank"
},
{
"id": 964,
"code": "000025",
"name": "Titan Trust Bank"
},
{
"id": 300,
"code": "000027",
"name": "Globus Bank"
},
{
"id": 1318,
"code": "000031",
"name": "PremiumTrust Bank"
},
}
After sending the token generation request, you'll get a response like this:
{
"status": "success",
"message": "Account tokenization successful.",
"data": {
"status": "PENDING",
"amount": 100,
"address": "09797 Volkman Place",
"narration": "e-Mandate token for tester",
"account_id": 188360,
"currency": "NGN",
"end_date": "2025-10-10T01:28:00.000Z",
"customer_id": 295028522,
"start_date": "2024-10-22T12:46:47.108Z",
"reference": "URF_EMANDATE_1729601207335_39068",
"updated_at": "2024-10-22T12:46:51.000Z",
"created_at": "2024-10-22T12:46:47.000Z",
"processor_code": "02",
"processor_response": "Welcome to NIBSS e-mandate authentication service, a seamless and convenient authentication experience. Kindly proceed with a token payment of N100:00 into account number 9020025928 with Fidelity Bank {Account name : NIBSS MANDATE ACTIVATION}. This payment will trigger the authentication of your mandate. Note: You have 10 minutes to complete this payment. Thank You",
"mandate_consent": {
"bank_name": "Fidelity Bank",
"account_name": "NIBSS MANDATE ACTIVATION",
"account_number": "9020025928",
"amount": "N100:00"
}
}
}
{
"status": "error",
"message": "Account details could not be resolved.",
"data": null
}
Authorizing a mandate
When you get a successful response after initiating a token generation, you will need to prompt the customer to make a transfer to the specified account in order to authorize the mandate. The authorization fee must be paid from the bank account on which the authorization is requested.
This transfer is a fee (NGN 100) to trigger your customer's authorization and it must be completed within 10 minutes of the token generation.
Before authorizing a mandate, the status of your generated token is pending. After the mandate is authorized, the status moves to approved and we'll send you a webhook with the token information.
{
"data": {
"token": "flw-1bt-XXXXXX-k3n",
"status": "APPROVED",
"start_date": "2024-09-29T17:01:03.000Z",
"end_date": "2025-09-27T01:28:00.000Z",
"amount": 500,
"currency": "NGN",
"address": "3843 Kub Square",
"narration": "e-Mandate Firstbank again",
"response_code": "00",
"response_message": "Approved Or Completed Successfully",
"active_on": "2024-09-29T20:04:15.755Z",
"reference": "URF_EMANDATE_1727629264278_59850",
"created_at": "2024-09-29T17:01:04.000Z",
"account_id": 188360,
"customer_id": 295028841,
"bank_account_id": 467038
},
"event": "account.tokenize"
}
For a new customer, after the mandate has been authorized, the wait period for activating the token is returned as the active_on
in the response. This wait period is usually less than three hours after token authorization. With a returning customer, the token is activated immediately.
active_on
field in the response specifies the exact time at which the token's status will transition to
Active
When waiting for activation, the token’s status will be Approved
. This gets updated to Active
after activation. Only active tokens can be used to debit the customer’s account.
Querying a token's status
Only active tokens can be used to recurrently debit your customers. After you generate the token, it's important to query its status before attempting to charge the customer. A generated token can have multiple statuses. The statuses to keep an eye out for include:
- Pending - This status indicates that the customer is yet to give their consent for the mandate.
- Approved - An approved status means that the customer has granted consent, but the bank is yet to activate the mandate for the transaction.
- Active - The token is now active and ready for recurring charges.
- Suspended - This status shows that a token is suspended by the merchant. Subsequent transactions for suspended tokens would fail automatically.
- Deleted - The merchant has permanently deleted the token.
Send the token reference to the Get token endpoint to confirm the token's current status.
curl --request GET \
--url 'https://api.flutterwave.com/v3/accounts/token/:reference' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--header 'Content-Type: application/json' \
{
"status": "success",
"message": "Account token fetched successfully.",
"data": {
"token": "flw-1bt-5e1ba73fff7f1aa9642606d4d82a45d3-k3n",
"reference": "URF_EMANDATE_1728385553726_55174",
"status": "APPROVED",
"start_date": "2024-10-08T11:05:52.000Z",
"end_date": "2024-10-10T01:28:56.000Z",
"amount": 100,
"currency": "NGN",
"address": "06548 Clay Path",
"narration": "eMandate test on F4B flow for an nigerian merchant",
"processor_code": "00",
"processor_response": "Approved Or Completed Successfully",
"active_on": "2024-10-08T11:36:26.724Z",
"created_at": "2024-10-08T11:05:53.000Z",
"updated_at": "2024-10-08T11:06:26.000Z",
"account_id": 1091430,
"customer_id": 585229978
}
}
{
"status": "error",
"message": "No mandate token found for reference.",
"data": null
}
Charging a customer using your token
After a customer authorizes a mandate and the status of the token is active, you can initiate the charge using the generated token. Send the token
, email
, amount
, transaction reference (tx_ref
) and the transaction type
to the Tokenized-charge endpoint to initiate the payment.
The transaction amount should not exceed the amount specified when generating the token.
curl --request POST \
--url 'https://api.flutterwave.com/v3/tokenized-charge' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"token": "flw-1bt-xxxxxxxxxxxxxxxxxxx-k3n",
"email": "user@example.com",
"amount": "100",
"tx_ref": "YOUR_TRANSACTION_REFERENCE",
"type": "account"
}
'
{
"status": "success",
"message": "Charge successful",
"data": {
"id": 510991384,
"tx_ref": "QA/ADD/1727792865",
"flw_ref": "NKHIFRQWFPLETELPMT",
"redirect_url": "N/A",
"device_fingerprint": "N/A",
"amount": 50,
"charged_amount": 50.7,
"app_fee": 0.7,
"merchant_fee": 0,
"processor_response": "Approved Or Completed Successfully",
"auth_model": "EMANDATE",
"currency": "NGN",
"ip": "85.255.21.158",
"narration": "TOKENIZED ACCOUNT CHARGE FOR Fumz Enterprise",
"status": "successful",
"payment_type": "account",
"created_at": "2024-10-01T14:27:46.000Z",
"account_id": 188360,
"customer": {
"id": 295028841,
"phone_number": "07000000000",
"name": "JOSHUA WISDOM",
"email": "wisdom@flutterwavego.com",
"created_at": "2024-09-27T15:01:22.000Z"
},
"account": {
"account_number": "3000040010",
"bank_code": "011",
"first_name": "WISDOM EFFIONG",
"last_name": "JOSHUA"
}
}
}
{
"status": "error",
"message": "Wrong account token or customer email passed in.",
"data": null
}
{
"event": "charge.completed",
"data": {
"id": 510991224,
"tx_ref": "PERF123456",
"flw_ref": "YAUXQHMWOJETXEGYMT",
"device_fingerprint": "N/A",
"amount": 50,
"currency": "NGN",
"charged_amount": 50.7,
"app_fee": 0.7,
"merchant_fee": 0,
"processor_response": "Approved Or Completed Successfully",
"auth_model": "EMANDATE",
"ip": "34.251.145.60",
"narration": "TOKENIZED ACCOUNT CHARGE FOR Fumz Enterprise",
"status": "successful",
"payment_type": "account",
"created_at": "2024-09-30T15:20:58.000Z",
"account_id": 188360,
"customer": {
"id": 295028841,
"name": "JOSHUA WISDOM EFFIONG",
"phone_number": "07000000000",
"email": "wisdom@flutterwavego.com",
"created_at": "2024-09-27T15:01:22.000Z"
},
"account": {
"account_name": "WISDOM EFFIONG JOSHUA",
"account_number": "3000040010",
"bank_code": "011"
}
},
"meta_data": {},
"event.type": "ACCOUNT_TRANSACTION"
}
Testing your integration
Here's how you test your integration, most data we'd use in the examples are custom and can be replaced easily.
- Generate a token for your customer.
- Mandate authorization occurs automatically after a successful token generation.
- Retrieve the token from your webhook server.
- Verify the token's status by querying the Get Token endpoint.
- Charge the demo customer using the generated token.
{
"status": "success",
"message": "Account tokenization successful.",
"data": {
"status": "PENDING",
"amount": 100,
"address": "540 Bayer Highway",
"narration": "eMandate test on F4B flow for an nigerian merchant",
"account_id": 1090457,
"currency": "NGN",
"end_date": "2024-10-10T01:28:56.000Z",
"customer_id": 585216092,
"start_date": "2024-10-08T10:18:56.036Z",
"reference": "URF_EMANDATE_1728382736750_24889",
"updated_at": "2024-10-08T10:18:56.000Z",
"created_at": "2024-10-08T10:18:56.000Z",
"processor_code": "02",
"processor_response": "Welcome to Flutterwave e-mandate authentication service, a seamless and convenient authentication experience. Kindly proceed with a token payment of N100:00 into account number 3662146895 with Mock Bank {Account name : FLUTTERWAVE MANDATE ACTIVATION}. This payment will trigger the authentication of your mandate. Note: You have 10 minutes to complete this payment. Thank You",
"mandate_consent": {
"bank_name": "Mock Bank",
"account_name": "FLUTTERWAVE MANDATE ACTIVATION",
"account_number": "3662146895",
"amount": "N100:00",
}
}
}
Updating an Account Token
You can enhance your customers' experience by properly managing tokens. In the event that your customer opts out of a payment plan or you suspect some foul play, We offer the flexibility of suspending or even deleting the token. This helps you to provide a secure and seamless payment experience in your solution.
Deleting a token is an irreversible action, Please consider this careful before you delete your customer’s token. If you need to debit a previous customer whose token has been deleted, you would need to generate and authorize a new token.
curl --request PUT \
--url 'https://api.flutterwave.com/v3/accounts/token/:reference' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"status": "SUSPENDED" // supported statuses also include ACTIVE and DELETED
}
'
{
"status": "success",
"message": "Account token updated successfully.",
"data": {
"token": "flw-1bt-XXXXXXXX-k3n",
"reference": "URF_EMANDATE_1726257451101_39351",
"status": "SUSPENDED",
"start_date": "2024-09-13T19:57:30.000Z",
"end_date": "2025-09-13T01:28:56.000Z",
"amount": 100,
"currency": "NGN",
"address": "8463 Elouise Valley",
"narration": "eMandate test on F4B flow for an nigerian merchant",
"response_code": "00",
"response_message": "Approved Or Completed Successfully",
"active_on": "2024-09-13T23:02:55.000Z",
"created_at": "2024-09-13T19:57:31.000Z",
"updated_at": "2024-10-01T14:24:02.000Z",
"account_id": 188360,
"customer_id": 295028780
}
}