Collection details

This document lists the required details that need to be sent for each of our collection corridors.

GHS mobile collections

To initiate a GHS mobile collection, please use the following details (phone_number and mobile_provider used below are examples):

"input_currency": "GHS",
"payin_methods": [
  {
    "type": "GHS::Mobile",
    "ux_flow": "ussd_popup",
    "in_details": {
      "phone_number": "+2339999999", // E.164 international format
      "mobile_provider": "vodafone" // Mandatory. One of 'airtel', 'tigo', 'mtn', 'vodafone'
    }
  }
],

For Collection transactions with mtn as mobile_provider and ussd_menu_approval as ux_flow, the out_details will be:

"out_details": {
  "style": "ussd_menu_approval",
  "menu_option": "6",
  "requires_pin": true,
  "dialing_number": "*170#"
}

And human readable instructions can be found in the payin_methods[0].instructions hash in the following format:

(example instructions for GHS Mobile payments)

"instructions": {
  'ussd_menu_approval': '\\nDial *170# to access mobile money menu.\\nSelect option 6 (My Wallet) and send.\\nChoose option 3 to check "my approvals".\\nChoose the transaction to approve and send.\\nConfirm transaction by choosing option1 (Yes) and send.\\nEnter mobile money pin and send.\\nYou will receive a new message on your mobile phone about the transaction.\\n'
}

Once the transaction is created, instructions for completing payment will be sent to the specified phone number.

Once the funds have been successfully received from the sender, payin_method.paid_in and transaction.paid_in webhooks will be sent out.

Collections requiring OTPs

Collections with ux_flow: otp_verified_ussd_popup require that the sender validate an OTP sent to their phone number when the transaction is created. The collection process is handled asynchronously. For such transactions, the details would look like:

"input_currency": "GHS",
"payin_methods": [
  {
    "type": "GHS::Mobile",
    "ux_flow": "otp_verified_ussd_popup",
    "in_details": {
      "phone_number": "+233548689440" // E.164 international format
      "mobile_provider": "mtn"
    }
  }
]

Once the transaction is created, an OTP will be sent to the phone_number specified in the payload. The response would look like:

"payin_methods": [
  {
  "id": "7334d150-41f8-4710-858b-e16a96df0c71",
  "type": "GHS::Mobile",
  "ux_flow": "otp_verified_ussd_popup",
  "state": "initial",
  "in_details": {
    "phone_number": "+233548689440", // E.164 international format
    "mobile_provider": "mtn"
  },
}

When the OTP is sent, a payin_method.incomplete webhook is sent out:

{
  "webhook": "ddef6199-6171-43ba-bbb5-29fb06c9df9f",
  "event": "payin_method.incomplete",
  "object": {
    "id": "7334d150-41f8-4710-858b-e16a96df0c71",
    "type": "GHS::Mobile",
    "ux_flow": "otp_verified_ussd_popup",
    "state": "incomplete",
    "state_reason_details": {
      "code": "23",
      "category": "user_action_required",
      "messages": [
        "User action required",
        "OTP verification required",
        "OTP verification required"
      ],
      "description": "This transaction is awaiting OTP verification by the user."
    },
    "in_details": {
      "phone_number": "+233548689440", // E.164 international format
      "mobile_provider": "mtn",
      "otp": "170270"
    },
    "transaction_id": "8421a8b4-0107-4d54-85bc-e0c2747b68b8",
    "transaction_external_id": "TRANSACTION-d68069bc-898f-45f5-88cf-5e7d8e537c70"
  }
}

In order to validate the OTP, send a PATCH request for the PayinMethod with the OTP in the payload:

PATCH /v1/payin_methods/9b25ca43-1812-46b2-ae0c-57acefec0a34
{
  "in_details": {
    "phone_number": "+233123456789" // E.164 international format
    "mobile_provider": "mtn",
    "otp": "123456"
  }
}

If the OTP matches the one sent to the sender’s phone number, the collection process starts, otherwise you get a validation error:

{
  "id": "9b25ca43-1812-46b2-ae0c-57acefec0a34",
  "type": "GHS::Mobile",
  "ux_flow": "otp_verified_ussd_popup",
  "in_details": {
    "phone_number": "+233123456789" // E.164 international format
    "mobile_provider": "mtn",
    "otp": "123456"
  },
  "errors": {
    "otp": [
      {
        "error": "invalid"
      }
    ]
  }
}

When the collection process starts, a payin_method.pending webhook is sent out:

{
  "webhook": "ddef6199-6171-43ba-bbb5-29fb06c9df9f",
  "event": "payin_method.pending",
  "object": {
    "id": "7334d150-41f8-4710-858b-e16a96df0c71",
    "type": "GHS::Mobile",
    "ux_flow": "otp_verified_ussd_popup",
    "state": "pending",
    "state_reason_details": {
      "code": "14",
      "category": "pending",
      "messages": [
        "Pending",
        "Pending status update",
        "Pending status update"
      ],
      "description": "This transaction is awaiting a status update from the provider."
    },
    "in_details": {
      "otp": "170270",
      "type": "payin",
      "app_id": "898e347d-9391-4180-b0ef-3c67df0d8e50",
      "method": "mobile",

      "ux_flow": "otp_verified_ussd_popup",
      "currency": "GHS",
      "nth_provider": 0,
      "phone_number": "+233548689440", // E.164 international format
      "mobile_provider": "mtn"
    },
    "transaction_id": "8421a8b4-0107-4d54-85bc-e0c2747b68b8",
    "transaction_external_id": "TRANSACTION-d68069bc-898f-45f5-88cf-5e7d8e537c70"
  }
}

XOF mobile collections

To initiate a XOF mobile collection, please use the following details (phone_number used below are examples): At the moment, we only support collections in:

  • Senegal(Orange) - this requires the sender to request an OTP auth code via USSD #144#391*ORANGE_MONEY_PIN_CODE# . The auth code retrieved should be included in the otp parameter in in_details. Uses ussd_voucher in ux_flow parameter.
  • Ivory Coast(Orange) - this requires the sender to request an OTP auth code via USSD #144*82#. The auth code retrieved should be included in the otp parameter in in_details. Uses ussd_voucher in ux_flow parameter.
  • Ivory Coast(MTN) - On receipt of collection request, Sender dials a USSD code *133# & selects option 1 (Validate withdrawal & payment) 2. Sender selects option to confirm 3. Sender enters secret code to confirm withdrawal 4. Sender receives sms that confirms debit is completed. Uses ussd_popup in ux_flow parameter
"input_currency": "XOF",
"payin_methods": [
  {
    "type": "XOF::Mobile",
    "ux_flow": "ussd_voucher",
    "in_details": {
      "phone_number": "+221123456700", // E.164 international format
      "mobile_provider": "orange",
      "country": "SN", // "SN" for Senegal, "CI" for Ivory Coast
      "otp": "123456"
    }
  }
],

Or in MTN

"input_currency": "XOF",
"payin_methods": [
  {
    "type": "XOF::Mobile",
    "ux_flow": "ussd_popup",
    "in_details": {
      "phone_number": "+2250506369100", // E.164 international format
      "mobile_provider": "mtn",
      "country": "CI", // "SN" for Senegal, "CI" for Ivory Coast
    }
  }
],

If the payin method details are valid, you get back an initial response.

{
  "id": "1625c534-6db4-4f3a-adf2-62a8bec89080",
  "type": "XOF::Mobile",
  "ux_flow": "ussd_voucher",
  "state": "initial",
  "in_details": {
    "otp": "1234",
    "phone_number": "+221771234700", // E.164 international format
    "mobile_provider": "orange",
    "country": "SN"
  },
  "out_details": {
    "style": "info"
  },
  "instructions": {}
}

The collection process is handled asynchronously.

When the collection process starts, a payin_method.pending webhook is sent:

{
  "webhook": "ddef6199-6171-43ba-bbb5-29fb06c9df9f",
  "event": "payin_method.pending",
  "object": {
    "id": "1625c534-6db4-4f3a-adf2-62a8bec89080",
    "type": "XOF::Mobile",
    "ux_flow": "ussd_voucher",
    "state": "pending",
    "state_reason_details": {
      "code": "14",
      "category": "pending",
      "messages": [
        "Pending",
        "Pending status update",
        "Pending status update"
      ],
      "description": "This transaction is awaiting a status update from the provider."
    },
    "in_details": {
      "otp": "1234",
      "ux_flow": "ussd_voucher",
      "phone_number": "+221771234700", // E.164 international format
      "mobile_provider": "orange",
      "country": "SN"
    },
    "out_details": {
      "style": "info"
    },
    "instructions": {
    },
    "transaction_id": "0d59466a-dc2f-4aca-bad1-d4a98da37697",
    "transaction_external_id": "510c4e28-fe33-4c06-bd79-49d52d5b3094"
  }
}

Once the funds have been successfully received from the sender, a payin_method.paid_in webhook is sent:

{
  "webhook": "ddef6199-6171-43ba-bbb5-29fb06c9df9f",
  "event": "payin_method.paid_in",
  "object": {
    "id": "1625c534-6db4-4f3a-adf2-62a8bec89080",
    "type": "XOF::Mobile",
    "ux_flow": "ussd_voucher",
    "state": "success",
    "state_reason_details": {
      "code": "0",
      "category": "paid",
      "messages": [
        "Success",
        "Success",
        "Success"
      ],
      "description": "The transaction was successfully completed."
    },
    "in_details": {
      "otp": "1234",
      "ux_flow": "ussd_voucher",
      "phone_number": "+221771234700", // E.164 international format
      "mobile_provider": "orange",
      "country": "SN"
    },
    "out_details": {
      "style": "info"
    },
    "instructions": {
    },
    "transaction_id": "0d59466a-dc2f-4aca-bad1-d4a98da37697",
    "transaction_external_id": "510c4e28-fe33-4c06-bd79-49d52d5b3094"
  }
}

If there was an issue with the collection, a payin_method.error webhook is sent:

{
  "webhook": "ddef6199-6171-43ba-bbb5-29fb06c9df9f",
  "event": "payin_method.error",
  "object": {
    "id": "10bcee73-2c39-4c0d-9e00-7540c4d34a91",
    "type": "XOF::Mobile",
    "ux_flow": "ussd_voucher",
    "state": "error",
    "state_reason_details": {
      "code": "412",
      "category": "invalid_user_data_error",
      "messages": [
        "User Error",
        "Invalid user details",
        "Invalid mobile number"
      ],
      "description": "Mobile details are invalid. Please update the mobile details. You can also cancel this transaction."
    },
    "in_details": {
      "otp": "1234",
      "ux_flow": "ussd_voucher",
      "phone_number": "+221771234709", // E.164 international format
      "mobile_provider": "orange",
      "country": "SN"
    },
    "out_details": {
      "style": "info"
    },
    "instructions": {
    },
    "transaction_id": "b83f38d6-fc4c-49de-b512-f45ac914bbea",
    "transaction_external_id": "9b5f3c64-9b6b-41b8-9658-168999961b70"
  }
}

NGN Bank collections

To initiate NGN bank collection, please use the following details (phone_number used below is an example):

"input_currency": "NGN",
"payin_methods": [
  {
    "type": "NGN::Bank",
    "ux_flow": "bank_transfer",
    "in_details": {
      "phone_number": "+234787221236", // E.164 international format
    }
  }
],

You will receive bank transfer information in the out_details:

"out_details": {
  "style": "bank_transfer",
  "amount": 0,
  "currency": "NGN",
  "bank_code": "bank code",
  "bank_name": "bank name",
  "created_at": "created at",
  "account_name": "account name",
  "account_number": "account number",
  "account_reference": "account reference"
}

And human readable instructions can be found in the payin_methods[0].instructions hash in the following format:

(instructions for NGN Bank payment)

"instructions": {
  "bank_transfer": "\\nTransfer the exact amount specified to the provided virtual account number.\\nMake sure to complete the payment within one day from the time you receive these instructions.\\n"
}

Once the funds have been successfully received from the sender, payin_method.paid_in and transaction.paid_in webhooks will be sent out.


Improve this page