OPay

Collect payments from OPay wallets

The payment with OPay provides a seamless way to accept payments from customers with OPay wallets. Customers can securely authorize transactions directly from their OPay wallets, and funds are deposited into your Flutterwave account.

Whether you're a merchant expanding your payment options or an OPay customer seeking convenience and security, this method simplifies the overall payment experience.

🚧

Feature Availability

This payment method is only available for NGN (Nigerian Naira) transactions.

Requirements

Before you begin, ensure the following prerequisites are met:

  1. Read the introduction section of this documentation.
  2. Retrieve your API keys from the Flutterwave dashboard.

👍

Customer Experience Tip

OPay customers must log into their wallets to authorize payments. Inform users in-app when they select this payment method to avoid confusion.


How OPay Payments Work

When a customer chooses OPay, they are redirected to the OPay platform to log in and authorize the transaction.

After authorization, the customer's wallet is debited, and Flutterwave sends a webhook notification to your server confirming the successful transaction.


Payment Flow

To collect payments using OPay, follow these key steps:

  1. Initiate Transaction: Collect the customer’s details and define the transaction parameters (amount, currency, tx_ref, etc.).
  2. Redirect to OPay: Send the customer to the OPay authorization page to log in and complete the transaction.
  3. Verify Payment: After receiving the webhook or polling the transaction endpoint, confirm:
    1. status = "successful"
    2. Correct amount
    3. Matching customer_id
    4. Valid transaction_id

Only provide value after successful verification.

Steps to Collecting OPay Payments with Flutterwave

🚧

Integration Method

This guide follows the general integration flow. Please refer to the orchestrator flow for the alternative integration method.

Step 1: Create a Customer

To create a new customer, send a request to the create customer endpoint with relevant fields such as name, email, phone, and address.

While only the email field is required, we recommend collecting as much customer information as possible to support robust transaction records and future payments.

To retrieve existing customer details, use the retrieve customer endpoint. This is useful when initiating payments for returning users.

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}}' \
--header 'X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}' \
--data '{
   "address":{
      "city":"Shirley",
      "country":"US",
      "line1":"175 E Parkview Dr",
      "line2":"",
      "postal_code":"11967",
      "state":"New York"
   },
   "name":{
      "first":"John",
      "middle":"Agba",
      "last":"Doe"
   },
   "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_dc0FUyBpd0",
      "address":{
         "city":"Shirley",
         "country":"US",
         "line1":"175 E Parkview Dr",
         "line2":"",
         "postal_code":"11967",
         "state":"New York"
      },
      "email":"[email protected]",
      "name":{
         "first":"John",
         "middle":"Agba",
         "last":"Doe"
      },
      "phone":{
         "country_code":"1",
         "number":"6313958745"
      },
      "meta":{
         
      },
      "created_datetime":"2024-12-25T20:16:38.246410457Z"
   }
}

Step 2: Create an OPay Payment Method

To create an OPay payment method, send a request to the create payment method endpoint and set the type to 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":"opay"
}'

You'll see a response similar to this:

{
  "status": "success",
  "message": "Payment method created",
  "data": {
    "type": "opay",
    "opay": {},
    "id": "pmd_uF9ADr9LvH",
    "meta": {},
    "created_datetime": "2024-12-26T14:38:25.179075400Z"
  }
}

Step 3: Create the Charge

To initiate an OPay charge, send a request to the create charge endpoint with the following parameters:

  • customer_id: The ID returned from Step 1 (customer creation).
  • payment_method_id: The ID returned from step 2 (payment method creation).
  • Transaction details including: amount, currency, and a unique reference for the transaction.
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 '{
   "currency":"NGN",
   "customer_id":"cus_dc0FUyBpd0",
   "payment_method_id":"pmd_uF9ADr9LvH",
   "amount":200,
   "reference":"ex61m23j6a3y0k34o9ilrri"
}'

You'll get a response similar to this:

{
   "status":"success",
   "message":"Charge created",
   "data":{
      "id":"chg_nONgeAGY97",
      "amount":200,
      "fees":[
         {
            "type":"vat",
            "amount":0
         },
         {
            "type":"app",
            "amount":0
         },
         {
            "type":"merchant",
            "amount":0
         },
         {
            "type":"stamp_duty",
            "amount":0
         }
      ],
      "currency":"NGN",
      "customer_id":"cus_dc0FUyBpd0",
      "settled":false,
      "settlement_id":[],
      "meta":{},
      "next_action":{
         "type":"redirect_url",
         "redirect_url":{
            "url":"https://developer-sandbox-ui-sit.flutterwave.cloud/redirects?opay&token=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6ImNiYThhMTkwLTE2OGUtNGNmZS05NmY5LTE2NDZhYjFhOWNkYiIsImNoYXJnZUlkIjoiY2hnX25PTmdlQUdZOTciLCJzdWIiOiJjYmE4YTE5MC0xNjhlLTRjZmUtOTZmOS0xNjQ2YWIxYTljZGIiLCJpYXQiOjE3MzgzMTc3MTAsImV4cCI6MTczODMxODAxMH0.QgLoZYfNhHJOJJvOsLA9eLoxOjGF0qnuehPMgMP4zD4"
         }
      },
      "payment_method_details":{
         "type":"opay",
         "opay":{},
         "id":"pmd_uF9ADr9LvH",
         "meta":{},
         "created_datetime":"2024-12-26T14:38:25.179Z"
      },
      "reference":"ex61m23j6a3y0k34o9ilrri",
      "status":"pending",
      "processor_response":{
         "type":"pending",
         "code":"02"
      },
      "created_datetime":"2025-01-31T10:01:50.209460744Z"
   }
}


Step 4: Authorize the Payment

The response from the charge initiation contains the next_action object with a redirect URL. This URL routes the customer to the OPay interface to authorise and complete the payment.

{
   "status":"success",
   "message":"Charge created",
   "data":{
      "id":"chg_nONgeAGY97",
      "amount":200,
      "fees":[
         {
            "type":"vat",
            "amount":0
         },
         {
            "type":"app",
            "amount":0
         },
         {
            "type":"merchant",
            "amount":0
         },
         {
            "type":"stamp_duty",
            "amount":0
         }
      ],
      "currency":"NGN",
      "customer_id":"cus_dc0FUyBpd0",
      "settled":false,
      "settlement_id":[],
      "meta":{},
      "next_action":{
         "type":"redirect_url",
         "redirect_url":{
            "url":"https://developer-sandbox-ui-sit.flutterwave.cloud/redirects?opay&token=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6ImNiYThhMTkwLTE2OGUtNGNmZS05NmY5LTE2NDZhYjFhOWNkYiIsImNoYXJnZUlkIjoiY2hnX25PTmdlQUdZOTciLCJzdWIiOiJjYmE4YTE5MC0xNjhlLTRjZmUtOTZmOS0xNjQ2YWIxYTljZGIiLCJpYXQiOjE3MzgzMTc3MTAsImV4cCI6MTczODMxODAxMH0.QgLoZYfNhHJOJJvOsLA9eLoxOjGF0qnuehPMgMP4zD4"
         }
      },
      "payment_method_details":{
         "type":"opay",
         "opay":{},
         "id":"pmd_uF9ADr9LvH",
         "meta":{},
         "created_datetime":"2024-12-26T14:38:25.179Z"
      },
      "reference":"ex61m23j6a3y0k34o9ilrri",
      "status":"pending",
      "processor_response":{
         "type":"pending",
         "code":"02"
      },
      "created_datetime":"2025-01-31T10:01:50.209460744Z"
   }
}



Flutterwave will then send a webhook notification with the final transaction status once the payment is completed and funds are received.

Refer to the next section to learn how to verify the transaction.

Step 5: Verifying the Payment

Before you provide value to the customer, confirm the transaction's final status and amount. You can verify the transaction information either using webhooks or by retrieving the charge details:

  • Webhooks: It is important to have webhooks enabled on your Flutterwave dashboard. If you have webhooks enabled, we'll call your webhook URL with the payment details when the transaction is completed or fails. Below is a sample webhook payload;
{
  "webhook_id": "wbk_z8BBd4nvlPxrg0GGTEFw",
  "timestamp": 1738317739798,
  "type": "charge.completed",
  "data": {
    "id": "chg_nONgeAGY97",
    "amount": 200,
    "currency": "NGN",
    "customer": {
      "id": "cus_dc0FUyBpd0",
      "address": {
        "city": "Shirley",
        "country": "US",
        "line1": "175 E Parkview Dr",
        "line2": "",
        "postal_code": "11967",
        "state": "New York"
      },
      "email": "[email protected]",
      "name": {
        "first": "John",
        "middle": "Agba",
        "last": "Doe"
      },
      "phone": {
        "country_code": "1",
        "number": "6313958745"
      },
      "meta": {},
      "created_datetime": "2024-12-25T20:16:38.246Z"
    },
    "description": null,
    "meta": {},
    "payment_method": {
      "type": "opay",
      "opay": {},
      "id": "pmd_uF9ADr9LvH",
      "customer_id": null,
      "meta": {},
      "device_fingerprint": null,
      "client_ip": null,
      "created_datetime": "2024-12-26T14:38:25.179Z"
    },
    "redirect_url": null,
    "reference": "ex61m23j6a3y0k34o9ilrri",
    "status": "succeeded",
    "processor_response": {
      "type": "approved",
      "code": "00"
    },
    "created_datetime": "2025-01-31T10:01:50.209Z"
  }
}
  • Retrieve the Charge: You can manually check the status of a charge by calling the retrieve a charge endpoint using the charge ID, which is returned in the data.id field of the response after successfully initiating a charge.
curl --request GET \
--url 'https://api.flutterwave.cloud/developersandbox/charges/id' \
--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>' \

You'll get a response similar to this:

{
  "status": "success",
  "message": "Charge fetched",
  "data": {
    "id": "chg_LgTqLXDGXq",
    "amount": 200,
    "currency": "NGN",
    "customer_id": "cus_dc0FUyBpd0",
    "settled": false,
    "settlement_id": [],
    "meta": {},
    "payment_method_details": {
      "type": "opay",
      "opay": {},
      "id": "pmd_uF9ADr9LvH",
      "meta": {},
      "created_datetime": "2024-12-26T14:38:25.179Z"
    },
    "reference": "ex61m23j6a3y0kk4o8ilrri",
    "status": "succeeded",
    "processor_response": {
      "type": "approved",
      "code": "00"
    },
    "created_datetime": "2024-12-27T08:52:18.128Z"
  }
}

Testing your integration

Testing your integration requires no extra configuration or special data. Initiate the OPay charge, and we'll return a redirect link to our mock page, where you can simulate both successful and failed customer attempts.


Next Steps

That’s it! You’ve successfully integrated the OPay payment method. It doesn't end there, there is more:

  • Learn about settlements of successful payments into your Flutterwave balance.
  • For cases where refunds are necessary, see the refunds guide for more information on how to process transaction refunds.