General flow
Get started with Flutterwave payments.
The general payment flow gives you more control over how payments are handled. It lets you to customize the experience to fit your product. In this flow, you’ll manage the customer, payment method, and charge information on your server.
This flow has five key steps:
- Create and manage the
customer
entity. - Create a
payment_method
for the customer. Some methods, like USSD and bank transfers, can be reused across customers. - Initiate the charge using
customer_id
andpayment_method_id
. - Authorize the payment, based on the method’s requirements.
- Verify the payment status. This is especially important for asynchronous methods like mobile money, USSD, and bank transfers.
Requirements
Before you start, go through our quickstart section. It covers essential setup steps for using our APIs.
You need the following setup to follow this guide:
- Test account
- API credentials (client ID and client secret) for authenticating your requests.
- A webhook URL to receive payment status updates.
- Feature approvals
- Some payment methods require additional approval. See the payment methods section for more details.
Step 1: Create a Customer
To create a customer, collect their information like name
, email
, mobile_number
, and address
. Only the email
is required, but we recommend collecting as much information as possible. This helps you:
- Enhance user experience: Autofill forms using saved customer details, making the checkout process smoother.
- Personalize interactions: Use customer data for targeted promotions and retention strategies.
- Improve security and compliance: Reduce fraud, chargebacks, and ensure regulatory compliance with comprehensive customer information.
A sample request looks like this:
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/customers' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--data '{
"address": {
"city": "Gotham",
"country": "US",
"line1": "221B Baker Street",
"line2": "",
"postal_code": "94105",
"state": "Colorado"
},
"name": {
"first": "King",
"middle": "Leo",
"last": "James"
},
"phone": {
"country_code": "1",
"number": "6313958745"
},
"email": "[email protected]"
}'
You'll get a response similar to this:
{
"status": "success",
"message": "Customer created",
"data": {
"id": "cus_J0PvwvJB2n",
"address": {
"city": "Gotham",
"country": "US",
"line1": "221B Baker Street",
"line2": "",
"postal_code": "94105",
"state": "Colorado"
},
"email": "[email protected]",
"name": {
"first": "King",
"middle": "Leo",
"last": "James"
},
"phone": {
"country_code": "1",
"number": "6313958745"
},
"meta": {},
"created_datetime": "2024-12-03T13:54:21.546559974Z"
}
}
Step 2: Create a Payment Method
Once you’ve created the customer, the next step is to collect their payment details. Flutterwave allows you to choose from different payment methods, such as cards, mobile money, wallets, and other APMs.
To create a payment method, send a request to the create payment method endpoint with the required details.
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/payment-methods' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
"type": "card",
"card": {
"nonce": "w2zQDGCf1QXA",
"encrypted_card_number": "Li/5y8DsxwD/FrDZgAS4AmFQDE8Pn1ed1BvjY3j0QoY=",
"encrypted_expiry_month": "LyWZtiCL4oU7K65fWsOoA9B3",
"encrypted_expiry_year": "LC8FYIrkmK6oMULiBskRx9L3",
"encrypted_cvv": "Kiv9mwKcebmwbjWEN0Fd/ZBK2A=="
}
}'
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/payment-methods' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
"type": "mobile_money",
"mobile_money": {
"country_code": "233",
"network": "MTN",
"phone_number": "9012345678"
}
}'
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/payment-methods' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
"type":"opay"
}'
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/payment-methods' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
"type":"googlepay",
"googlepay":{
"card_holder_name":"John Doe"
}
}'
You'll get a response similar to this:
{
"status": "success",
"message": "Payment method created",
"data": {
"type": "card",
"card": {
"expiry_month": 8,
"expiry_year": 32,
"first6": "123412",
"last4": "2222",
"network": "mastercard"
},
"id": "pmd_wlVhaYmkl2",
"meta": {},
"created_datetime": "2024-12-03T14:29:26.650973145Z"
}
}
Step 3: Initiate a Charge
To charge a customer, use their customer_id
and payment_method_id
. You’ll also need to specify the transaction amount, currency, and a unique reference.
curl --request POST \
--url 'https://api.flutterwave.cloud/developersandbox/charges' \
--header 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
"reference": "cedfa85a-a803-4a06-a586-0f81fb9b9f22",
"currency": "USD",
"customer_id": "cus_IpH7CKCUtD",
"payment_method_id": "pmd_wlVhaYmkl2",
"redirect_url":"https://google.com",
"amount": 1234.56,
"meta":{
"person_name": "King James",
"role": "Developer"
}
}
'
Step 4: Authorize a Charge
After initiating the charge, the API will return a data.next_action
object in the response. This tells you what’s needed to complete the payment.
There are five kinds of next_action
results:
requires_pin
requires_otp
redirect_url
requires_additional_fields
payment_Instructions
requires_pin
, requires_otp
, and requires_additional_fields
are customer inputs for authorizing card transactions with their banks. Actions like entering pins, soft tokens (OTPs), and billing addresses all fall under this category.
For these types of authorization, update the transaction with the authorization object to complete them.
{
"authorization": {
"type": "pin",
"pin": {
"nonce": "w2zQDGCf1QXA",
"encrypted_pin": "LC8FYIrkmK6oMULiBskRx9L3"
}
}
}
{
"authorization": {
"type": "otp",
"otp": {
"code": "123456"
}
}
}
ADD_AVS_SAMPLE_HERE
Redirects contain instructions for the merchant to redirect their customers to. These are typically used to complete 3DS card payments and mobile money transactions. In this scenario, the customer's transactions remain pending until redirection is completed.
In some cases, you would be required to perform some action offline. We communicate these actions as payment_instructions
. This class of next_action
is used mostly in USSD and pay with bank transfer payments.
{
"status": "success",
"message": "Charge created",
"data": {
"id": "chg_RCDsCBDyaV",
...
"next_action": {
"type": "redirect_url",
"redirect_url": {
"url": "https://developer-sandbox-ui-sit.flutterwave.cloud/redirects?card&token=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6ImFjODMxOTNlLWFhMmItNDc2ZS1hZTNjLTMxYmVmMTc4NDUxZCIsImNoYXJnZUlkIjoiY2hnX1JDRHNDQkR5YVYiLCJzdWIiOiJhYzgzMTkzZS1hYTJiLTQ3NmUtYWUzYy0zMWJlZjE3ODQ1MWQiLCJpYXQiOjE3MzA5NjQ1MTIsImV4cCI6MTczMDk2NDgxMn0.tMv1VZ4WevvZ_dg37AzYnhj0Z1YtXK_tQIOJcErNscI"
}
},
"payment_method_details": {},
"status": "pending",
...
}
}
{
"status": "success",
"message": "Charge created",
"data": {
"id": "chg_RCDsCBDyaV",
...
"next_action": {
"type": "payment_instruction",
"payment_instruction": {
"note": "Please authorise this payment on your mobile number: 2339012345678. It may take a few minutes to confirm this payment."
}
},
"payment_method_details": {},
"status": "pending",
...
}
}
Step 5: Verify the Payment Status
This final step is important to close out the payment. Query the transaction information and verify the transaction's reference
, amount
and status
before giving value to the customer.
You can either:
- Use your webhook to listen for payment status updates.
- Call the verify transaction endpoint to confirm the status manually.
You'll get a response similar to this:
{
"status": "success",
"message": "Charge updated",
"data": {
"id": "chg_VoUhmFMhmF",
"amount": 1500.25,
"currency": "NGN",
"customer": "cus_EFE4TQhBSf",
"meta": {},
"next_action": {
"type": "requires_pin"
},
"payment_method_details": {
"type": "card",
"card": {
"expiry_month": 8,
"expiry_year": 2024,
"first6": "123412",
"last4": "4444",
"network": "mastercard"
},
"id": "pmd_NkWibrRJIy",
"customer": "cus_EFE4TQhBSf",
"meta": {}
},
"redirect_url": "https://google.com",
"reference": "XYZ123",
"status": "succeeded",
"issuer_response": {
"type": "approved",
"code": "00"
}
}
}
Updated about 16 hours ago