# Monnify Documentation > Monnify is a payment gateway for businesses to accept payments from customers, either on a recurring or one-time basis. Monnify offers an easier, faster and cheaper way for businesses to get paid on their web and mobile applications using convenient payment methods for customers with the highest success rates obtainable in Nigeria. --- ## [Bills Payments](https://developers.monnify.com/docs/bills-payment) > Learn how to receive payments from your customers using the Monnify APIs, List of Pricing / Fees - Local Card Payments, Transfers (Dynamic), Transfers (Customer Reserved Account), USSD, Phone, Bank, Offline Collections > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ### Seamless Bill Vending for Your Platform The Monnify Bills Payment feature is a robust solution that empowers Monnify Merchants to seamlessly integrate bill processing and vending directly into their applications or platforms. This allows you to offer essential services such as Utility Bills, Airtime Topup, Data Bundles, and Cable TV subscriptions, using your existing Monnify account and infrastructure. The Biller Service provides a single, unified API to access and facilitate bill payments across multiple service categories. This singular integration replaces the need for Merchants to manage individual connections with numerous Billers, simplifying operations and accelerating time-to-market. It transforms your platform into a comprehensive service center, driving customer engagement and providing a new stream of transactions. ### Key Benefits - Expanded Services: Instantly offer a wide range of bill payment options to your users. - Unified Account: Process bills using the same Monnify account you use for collections and disbursements. - Guaranteed Validation: Mandatory pre-payment validation ensures that every transaction is correctly directed to the intended customer and product. ### Service Categories - Electricity - Betting - Cable TV - Airtime - Data - Education ## Getting Started For a step-by-step guide on how to implement the feature and for full details on all endpoints, please refer to: > ### API references For detailed information on URLs, HTTP methods, and data fields, see the Bill Payment API Reference } --- ## [Process a bill](https://developers.monnify.com/docs/bills-payment/process-a-bill) > You can accept cash payments from your customers offline through Moniepoint Agents. Moniepoint is an agency banking platform with a wide reach, having agents in every local government in Nigeria. ## Process a Bill The Monnify Bills Payment feature allows all Monnify merchants to Vend and Process Bills using their existing Monnify account. This includes services like Utility Bills, Airtime Topup, and other essential bills. > > **Info:** Activation: The Bills Payment service is not active for all Monnify Merchants by default. To enable it for your account, you must send an activation request via email to: integration-support@monnify.com. ### Authentication Access to the Bills Payment product is secured using Bearer Token authentication. To use the service, first obtain an Access Token by authenticating with your API Key and Client Secret , which you can find on your Monnify dashboard. Include this token in the Authorization: Bearer `token` header of all requests. ### Bill Payment Workflow Integrating the Bill Payment product involves a high-level sequence of steps to ensure customers select the correct service and that their details are validated before any funds are debited. Step Action Description Key Requirement 1 Get Categories Display a list of general bill types (e.g., ELECTRICITY, CABLE_TV) for the user to select from. None 2 List Billers Show all available service providers (e.g., specific electricity companies) that fall under the selected category. Category Code 3 List Products Fetch the specific products offered by the selected biller (e.g., Prepaid Meter, Postpaid Meter, various Data Bundles). Biller Code 4 Validate Customer Required Step. The customer enters their unique identifier (e.g., meter number, phone number). The system validates these details before payment can proceed. Product Code & Customer ID 5 Vend Bill (Process Payment) Once validation is successful, initiate the actual payment transaction by sending the amount and the unique validation reference. Validation Reference 6 Check Transaction Status (Requery) Check the current status of a vend request (e.g., if it is still IN_PROGRESS, SUCCESS, or FAILED). Note: This is not used to initiate a new payment. It is only for status verification. Transaction Reference ### How it works Consuming the Monnify Bills Payment service generally involves three primary phases: Discovery, Validation, and Vending. - **Discovery (Finding Billers and Products)** Before a payment can be processed, you must identify the relevant biller and product using the following endpoints: **Retrieve Biller Categories:** Use the GET Biller Categories endpoint to list all available categories (e.g., ELECTRICITY, DATA, CABLE_TV). - **Retrieve List of Billers:** Use the GET Billers endpoint to retrieve all active billers available for payment. This list can be filtered using the categoryCode . - **Retrieve Available Products:** Use the GET Billers product endpoint to fetch a list of available products offered by different billers. This list must be filtered using the specific billerCode . - **Validation (Verifying Customer Details)** Validation is an important step performed before attempting a final payment. It confirms customer information (e.g., meter number, phone number) and tells you whether a validationReference is required for the product. **Endpoint:** Perform customer validation using the POST method on validate customer . - **Request Payload:** Requires productCode and customerId . - **Successful Response:** The response includes a vendInstruction object. - This object indicates whether the product requires a validation reference: requireValidationRef: true → a validationReference will be included and must be used in the vend request. - requireValidationRef: false → no validation reference is required, and you should not send one during the vend request. - **Vending (Executing Payment)** This step executes the actual bill payment and charges the customer. **Endpoint:** Process payments using the POST method on vend . - **Required Inputs:** productCode - customerId - vendAmount - A merchant-supplied vendReference (could be random but should be unique for you per transaction) - If required: include validationReference only when requireValidationRef was true in the validation response. - **Validation Reference Requirement:** Include the validationReference when the product requires it. - Exclude the validationReference when requireValidationRef is false. - **Successful Vend:** A successful response returns: Monnify-generated transactionReference - Your (merchant) supplied vendReference - vendStatus (which will be SUCCESS when the payment is completed) - **Status Check/Requery:** If a vend initially returns "IN_PROGRESS" or its final status is uncertain: Use the GET Bills payment requery endpoint to check the updated status. This endpoint does not re-charge or re-initiate payment. It only confirms the final status (SUCCESS, FAILED, or still IN_PROGRESS). ### Key Concept: Pre-Validation The Validation step (Step 4) is critical. Before you can process a bill (Step 5), you must successfully validate the customer's ID against the chosen product. A successful validation generates a unique Validation Reference, which acts as a secure key required to successfully complete the final Vend request. This ensures that the payment is directed to the correct customer account. ### Error Handling / Validation Failure If the validation step fails (e.g. invalid customerId), the API will return an error response, and you should handle this by showing an appropriate error message to the user and not calling the vend endpoint. In case the vend call returns an IN_PROGRESS status, you should poll the “Check Transaction Status” endpoint until you receive a terminal status (SUCCESS or FAILED) or until a timeout / retry limit is reached. ### Next Steps For detailed information on URLs, HTTP methods, and data fields for each step above, see the Bill Payment API Reference } --- ## [Process a bill](https://developers.monnify.com/docs/bills-payment/settlement-process) > You can accept cash payments from your customers offline through Moniepoint Agents. Moniepoint is an agency banking platform with a wide reach, having agents in every local government in Nigeria. ## Settlement Process: Instant Commission Payout The Biller Aggregation Service uses a commercial model where merchants pay a service fee. A cashback system is used to pay out commissions. Once a transaction is successful, the system instantly settles the commission. This is done by first debiting the full amount (gross debit) and then crediting the commission back, so the merchant quickly sees the final net cost of the service. > ### Calculation of Merchant Payable The required funds for the transaction are defined by several terms: - **Vend Amount:** This is the base amount of the transaction, representing the gross value of the service being purchased by the customer. - **Merchant Fee:** A fee charged by the Aggregator to the Merchant, applicable only for certain products (otherwise set to zero). - **Merchant Payable Amount:** This figure represents the total amount the Merchant must pay the Aggregation Service, equaling the Vend Amount plus the Merchant Fee. ### The Settlement Flow The process achieves an instant net settlement position through two specific account movements: Step Action Account Movement 1 Gross Debit The Merchant's Account is debited for the full payable amount. This step signifies that the Merchant pays the full payable amount of the service. 2 Commission Credit The Merchant's Account is immediately credited with the applicable Cashback/Commission. This represents the Merchant's profit, which is instantly paid out. The Cashback/Commission varies depending on the specific Billers and Products involved. The Final Net Settlement ensures that the Merchant's true cost is immediately calculated as the Merchant payable amount minus the Commission. ### Example: For a transaction where the payable amount is 1000 naira and the applicable Cashback is 20 naira: - The Merchant is Debited 1000. - The Merchant is simultaneously Credited 20. - The resulting Net Cost to the Merchant is 980. } --- ## [International Payment](https://developers.monnify.com/docs/collections/international-payment) > Monnify allows you to receive international payments from your customers. You can receive payments from customers in over 150 countries across the world. ## International Payment Accept international payments in USD with Monnify. Enable customers from over 150 countries to make seamless payments on your platform using our secure payment infrastructure. > > **Feature Activation Required** International Payment is not enabled by default on any account. To request access, navigate to your dashboard, go to Settings > Contract Setup , and toggle on International Payments. The Monnify team will review your request and activate the feature on your account if approved. Note: International USD payments currently support Mastercard only. - The Web SDK : A drop-in checkout modal that you can embed directly onto your website. - The Direct API : A server-side integration that generates a checkout URL for you to redirect your customers to. - Currency : USD (United States Dollar). - Card Networks : Mastercard is the only supported card network for international payments at this time. Parameter Type Required Description amount Number Yes The amount to be paid by the customer. customerName String No The full name of the customer. customerEmail String Yes The email address of the customer. paymentReference String Yes A unique string to identify this specific payment on your system. paymentDescription String No A short description of the item or service being paid for. currencyCode String Yes The currency code for the transaction (Must be "USD"). contractCode String Yes Your unique Monnify contract code. redirectUrl String No The URL to redirect the user to after they complete the payment. paymentMethods Array of Strings No Allowed payment methods. For international payments, use ["CARD"]. - Business days exclude weekends and public holidays. - Express Settlement Please note that Express Settlement is only supported for local payments and is not available for international transactions. - Default Settlement: By default, all successful international payment settlements are credited directly to your Monnify USD wallet after the T+3 period. - Custom Settlement: If you prefer, you can configure a dedicated domiciliary bank account as your primary settlement destination. This can be managed directly from your dashboard under your Contract Settings. - 85% of each successful settlement is made available to your wallet or bank account based on the standard T+3 settlement schedule. - The remaining 15% is temporarily withheld for a period of 90 days. After the 90-day holding period elapses, the withheld reserve is automatically released to your standard settlement destination, provided there are no unresolved disputes or chargebacks associated with those specific transactions. > **Important Notes** USD settlements are processed into your provisioned USD wallet by default. Merchants may configure a domiciliary account as an alternative settlement destination. The rolling reserve applies only to international USD transactions. Reserved funds are automatically released after 90 days if no disputes are recorded. } --- ## [Reconciliation](https://developers.monnify.com/docs/collections/manage-payments/reconciliation) > Build a reconciliation workflow using Monnify transaction query APIs and settlement data to keep your internal records in sync. ## Reconciliation Reconciliation is the process of matching your internal payment records against the authoritative data from Monnify. A good reconciliation workflow catches discrepancies early, such as missed payments, duplicate records, or settlement shortfalls, before they become accounting problems. > ### What You Are Reconciling There are two layers of reconciliation for most merchants: - **Transaction-level**: Every payment your customers made. Does your database record match what Monnify recorded? - **Settlement-level**: The net amount credited to your wallet or bank account. Does it match the sum of your transaction fees and settlement amounts? ### Step 1 – Pull Your Transactions from Monnify Use the transaction search API to fetch all transactions for a given period. Paginate through the results to ensure you capture everything. > **Include all statuses:** For a complete reconciliation, also fetch PARTIALLY_PAID , OVERPAID , and REVERSED transactions separately, not just PAID . Each status may require a different accounting treatment. ### Step 2 – Compare Against Your Internal Records For each Monnify transaction, look up the corresponding record in your own database using the paymentReference (your own order/reference ID). Discrepancy Type Meaning Action MISSING_IN_DB Monnify recorded a payment but your DB has no matching order. Investigate: the webhook may have been missed. Fulfill or refund as appropriate. AMOUNT_MISMATCH Payment amount differs from your expected order amount. Check for overpayment or partial payment. Refund the excess or chase the balance. STATUS_MISMATCH Monnify shows PAID but your DB shows PENDING (webhook missed or duplicate). Update your DB and fulfill the order. ### Step 3 – Reconcile Settlement Amounts To verify that the amount credited to your Monnify wallet matches what you expect, sum the settlementAmount field across all paid transactions for a settlement period and compare it against your wallet credit. ### Automating Reconciliation Run reconciliation as a scheduled job. Daily is the most common cadence, aligned with the 10 PM settlement cycle. A typical setup: - Schedule a job at **11 PM daily** (after settlement). - Fetch all Monnify transactions for the day. - Compare against your internal database. - Log or alert on any discrepancies for manual review. - Auto-resolve clear cases (e.g. status mismatches from missed webhooks). > **Keep a recon audit log:** Store every reconciliation run and its results. This gives you an audit trail for finance reviews and makes it much easier to spot patterns in discrepancies over time. ### Key API Endpoints for Reconciliation - **Search Transactions**: GET /api/v1/merchant/transactions/search . Filter by status, date range, or payment method. The from and to parameters accept **Unix timestamps in milliseconds**. - **Verify Single Transaction**: GET /api/v2/merchant/transactions/query . Look up a specific transaction by reference. See the full API Reference for query parameters and response schemas. --- ## [Transaction Refunds](https://developers.monnify.com/docs/collections/manage-payments/refunds) > This feature allows you to return a payment to a customer. An example of a transaction refund scenario is when an e-commerce customer picks five items and makes a payment for the five of them. On arrival of the products, the customer could decide to only keep three of the items and return the rest. Upon return, the customer would have to be refunded for the two returned products by the merchant. See Transaction Refund API for more information on implementing it on your platform. ## Transaction Refunds This feature allows you to return a payment to a customer. An example of a transaction refund scenario is when an e-commerce customer picks five items and makes a payment for the five of them. On arrival of the products, the customer could decide to only keep three of the items and return the rest. Upon return, the customer would have to be refunded for the two returned products by the merchant. > See Transaction Refund API for more information on implementing it on your platform. ### Types of Refunds - Partial Refund: A part of the total transaction amount is to be refunded. The customer will be refunded a part of the initial full payment. - Full Refund: The total transaction amount is to be refunded. ### Charges For payments made via transfers, you will be charged a refund fee of N10 and this will be deducted from your wallet. You are required to have your wallet funded before refunds can be processed. > **Virtual account payments:** Monnify does not refund to virtual account numbers . If the original payment was made via a virtual account, refunding to that same account will fail. In such cases, the merchant must collect a regular bank account number from the customer and specify it as the refund destination. See Refunding to a Different Account below. ### Refund via API > **Activation Required:** Refund are not enabled by default. You must request activation for the API (and UI - if needed) to be enabled both your Sandbox and/or Live environments. Contact integration-support@monnify.com to get this enabled stating your use case for the feature. As part of the email, you will be expected to idemnify Monnify for potential use and misuse of the feature on your platfrom. All refund API calls require a valid bearer token. Authenticate first using your API key and secret, then use the returned token in the Authorization header. #### Partial Refund A partial refund returns only a portion of the original transaction amount. Set refundAmount to any value less than the full transaction amount. #### Full Refund A full refund returns the entire transaction amount. Set refundAmount to the original transaction amount. You can optionally specify a different destination account; if omitted, the refund is sent back to the originating account. #### Refunding to a Different Account By default, Monnify sends the refund to the account that made the original payment. You can override this by supplying destinationAccountNumber and destinationAccountBankCode in the request body. > **Virtual account payments require a different destination:** Monnify does not refund to virtual account numbers . Virtual accounts are temporary receive-only accounts — transfers back to them will fail. If a customer paid through a virtual account (i.e. a dynamic account number generated for the transaction), ask them to provide a regular bank account number and use it as the destinationAccountNumber when initiating the refund. #### Request Fields Field Type Required Description transactionReference string Yes The unique transaction reference generated by Monnify for the original payment. refundReference string Yes A unique reference you generate to identify this refund. Must be distinct for each refund request. refundAmount number Yes Amount to refund. Must be between ₦100 and the original transaction amount. For a full refund, set this to the full transaction amount. refundReason string Yes Internal reason for the refund (max 64 characters). Used for your records. customerNote string Yes Narration that appears on the customer's bank credit alert (max 16 characters). destinationAccountNumber string No Account number to send the refund to. If omitted, the refund is sent back to the originating account. destinationAccountBankCode string No Bank code for the destinationAccountNumber . Required if destinationAccountNumber is provided. #### Response Field Description refundType PARTIAL_REFUND or FULL_REFUND . Determined automatically based on whether the refund amount equals the full transaction amount. refundStatus Current status of the refund. See statuses below. refundStrategy Indicates how the refund is funded. For example, MERCHANT_WALLET means the refund amount is debited from your Monnify wallet. comment A human-readable message about the refund's current state. refundStatus Meaning PENDING Refund has been accepted and is being processed. COMPLETED Refund was successfully sent to the customer's account. FAILED Refund could not be processed. Check the error codes section for details. ### Get Refund Status Poll this endpoint to check the current status of a refund using the refundReference you supplied when initiating it. > **Prefer webhooks over polling:** Polling is useful for a one-time status check, but for production systems configure a webhook URL to receive real-time refund notifications instead. See the section below. ### Refund Webhooks Monnify sends a webhook notification to your configured URL when a refund reaches a terminal state. There are two refund event types: #### Successful Refund Sent when the refund has been processed and the customer's account has been credited. #### Failed Refund Sent when the refund could not be processed. Use the refundReference to look up further details or surface an error to your support team. #### Setting Up Your Webhook URL Configure your webhook URL in the Monnify dashboard under **Settings > API Keys & Webhooks**. All webhook notifications include a monnify-signature header containing an HMAC-SHA512 hash of the request body signed with your client secret. Always verify this signature before processing the payload. > **Webhook best practices:** Respond with HTTP 200 immediately on receipt. Do your processing after acknowledging. Verify the monnify-signature header before trusting the payload. Check for duplicate notifications using refundReference before crediting or updating order state. Whitelist Monnify's IP addresses on your server firewall. See Webhooks & Event Types for the full signature verification guide and code samples in Node.js, PHP, and Java. ### Refund From Monnify Dashboard To initiate a refund on a particular transaction, click on the transaction to view its details as shown below; Clicking on the "Refund" button takes you to the refund page; Finally populate the necessary fields and click on the refund button to perform a refund on such transaction. Field Reference Error Message Meaning Action 99 Error occurred while processing your request. Engage the Monnify support R1 Transaction with specified reference does not exist. Recheck if there's a transaction with such reference. R2 Refund not permitted for specified transaction. Refund is currently only possible for payments via Account_Transfer. Recheck if the transaction is an Account_Transfer payment. R3 Specified refund amount is above transaction amount. Recheck the transaction amount and retry accordingly. R4 Specified refund amount is below minimum refundable amount. The minimum refundable amount is N100 R5 Merchant does not have sufficient funds to process refund. Merchant should topup his Monnify wallet and retry. R6 Customer account details are invalid Merchant should request valid account details from the customer or try again later. R7 No refund was initiated with the supplied refund reference. Kindly recheck if a refund with the refund reference was successfully initiated. R8 Supplied value has exceeded the maximum allowed number of characters. The refundReason should not be more than 64 characters and the customerNote should not be more than 16 characters. R9 Supplied refund reference already exists for the merchant. Kindly use a new and distinct refund reference. R10 Merchant account balance could not be retrieved. Contact Monnify's support. R11 Name inquiry network error. Kindly retry later or Contact Monnify's support. R12 The total amount of all refunds done on a particular transaction has exceeded the transaction amount. No refunds can be done for the particular transaction as the total amount of partial refunds have summed up to the transaction amount. M01 System error. Contact support. Contact Monnify's support. M02 System error. Contact support Contact Monnify's support. --- ## [Transaction Splitting / Sub Accounts](https://developers.monnify.com/docs/collections/manage-payments/transaction-splitting) > Transaction splitting is a feature on Monnify that allows you to create subaccounts so payments could be split across different accounts. This simply means that for a single transaction, Monnify can help you share the amount paid between up to five different accounts. ## Transaction Splitting / Sub Accounts Transaction splitting is a feature on Monnify that allows you to create subaccounts so payments could be split across different accounts. This simply means that for a single transaction, Monnify can help you share the amount paid between up to five different accounts. > This means you can specify either percentage/amount of incoming payments should go into your default settlement account and what percentage/amount of payments should also go into the sub-account you’ve created. You can create sub-accounts by integrating with the Monnify Create Sub-Account Endpoint You can do the following to a sub-account once it has been created: - Delete a Sub-Account Endpoint you no longer need - Get the Sub-Accounts created - Update the details of a Sub-Account ### Create a Sub-Account Use the Create Sub-Account API to register a sub-account. The request body is an array, so you can create multiple sub-accounts in a single call. ### Before You Begin Before integrating the SubAccount API, make sure you have completed the following steps: - **Enable Sub Account on your account** Subaccounts are not enabled by default. You must request activation for the API (and UI - if needed) to be enabled both your **Sandbox** and/or **Live** environments. Contact integration-support@monnify.com to get this enabled stating your use case for the feature. As part of the email, you will be expected to idemnify Monnify for potential use and misuse of the feature on your platfrom. > **Enabling SubAccount UI and API** Please note that activation of subaccount API does not enable it on the UI automatically, users are expected to explictly mention if they need both UI and API enabled to get both activated ### Attaching Subaccounts to other payment API To attach a subaccount to a payment request, simply append the ** incomeSplitConfig ** array to the request body. Each entry in the array defines how a portion of the payment is routed to a sub-account. There are two ways to define the split amount for each sub-account: - **Percentage split**: a percentage of the total transaction amount is sent to the sub-account, using the **splitPercentage** field. - **Flat amount split**: a fixed static amount is sent to the sub-account regardless of the transaction value, using the **splitAmount** field. > **Split Options** Only one of splitPercentage or splitAmount should be provided per sub-account entry, not both. However, you can add a mix of sub-accounts with fixed amount and percentage but not a single subaccount with both configuration. ### Percentage Split Use `splitPercentage` to route a proportion of the transaction to a sub-account. The `feePercentage` field controls what share of Monnify's transaction fee the sub-account bears. ### Flat Amount Split Use `splitAmount` to route a fixed amount to a sub-account, independent of the total transaction value. This is useful when you always want a sub-account to receive a specific amount (e.g. a platform fee of ₦500). You can see sample usage examples on the Reserved Account API section. ### Creating a Sub Account on Monnify UI Please send an email to integration-support@monnify.com to have the Sub Account UI enabled for you. Once enabled, you will see the Sub Account Tab under your Collections menu. To Create a Sub Account, click on Create New and fill in the necessary details --- ## [Verify Transactions](https://developers.monnify.com/docs/collections/manage-payments/verify-transactions) > Always verify payment status server-side before delivering value. Learn how to use the Monnify transaction verification API and what each response field means. ## Verify Transactions Never trust a client-side callback or redirect alone. Always verify a transaction on your server using the Monnify API before delivering goods, granting access, or crediting a wallet. > > **Why server-side verification matters:** Client-side callbacks (SDK onComplete , redirect URL parameters) can be intercepted or manipulated by a bad actor. A server-to-server verification call ensures the payment status you act on is authoritative and tamper-proof. ### Verification by Payment Reference Use this endpoint when you know your own paymentReference (the reference you generated and passed when initializing the transaction). ### Verification by Transaction Reference Use this when you have the transactionReference returned by Monnify (e.g. from a webhook payload). ### Response Reference Field Description paymentStatus The authoritative payment status. See statuses below. amountPaid Actual amount received. Always verify this equals your expected amount. totalPayable The amount the customer was charged (may include fees if fee bearer is customer). settlementAmount Amount that will be settled to your account after Monnify fees. paymentMethod Method used: ACCOUNT_TRANSFER , CARD , USSD , PHONE_NUMBER . paymentSourceInformation For bank transfers: the customer's actual account name and number. Useful for reconciliation and fraud checks. ### Payment Status Values Status Meaning Action PAID Full payment received. Fulfill the order / grant access. PARTIALLY_PAID Customer paid less than the required amount. Do not fulfill. Request the balance or issue a refund. PENDING Payment initiated but not yet confirmed. Wait for a webhook or re-poll after a short delay. OVERPAID Customer paid more than the required amount. Fulfill the order. Refund the excess or credit the customer's wallet. FAILED Payment attempt failed. Do not fulfill. Notify the customer and offer a retry path. REVERSED Payment was reversed after confirmation. Suspend access / hold order if not already fulfilled. EXPIRED The checkout session expired before payment. Ask the customer to start a new payment session. > **Overpayment and underpayment configuration:** By default, Monnify rejects over and under payments. The funds are returned to the sender and you receive a REJECTED_PAYMENT webhook instead. The OVERPAID and PARTIALLY_PAID statuses only appear if your Monnify contract has been configured to accept them. You can update this setting in Settings > Contracts Setup > Edit Contract on the Monnify dashboard. ### Recommended Verification Flow > **Check both status AND amount:** Always verify that amountPaid is at least the amount you expected. A successful status with an incorrect amount should be treated as a partial or fraudulent payment. ### Using Webhooks Instead of Polling Rather than only verifying on the redirect callback, configure your webhook URL to receive real-time payment notifications. This is especially important for: - Customers who close the browser before the redirect completes. - Reserved account payments that happen asynchronously. - Direct debit charges triggered server-to-server. See Webhooks & Event Types for details on how to validate the webhook signature and handle each event type. --- ## [Checkout API](https://developers.monnify.com/docs/collections/one-time-payments/checkout-api) > Use the Monnify Checkout API to accept payments without an SDK. Initialize a transaction, redirect customers to the hosted checkout URL, or build your own payment UI using the raw bank transfer and card charge endpoints. ## Checkout API The Checkout API gives you full control over the payment flow without requiring a Monnify SDK. Use it to redirect customers to the Monnify-hosted checkout URL, or build your own payment UI by calling the bank transfer and card charge endpoints directly. > > **Prefer a library over raw API calls?** Monnify has official server-side libraries for Node.js, Python, Go, Java, PHP (Laravel), and more, so you can skip the boilerplate and integrate in minutes. See Libraries and Plugins . ### Option A – Hosted Checkout (Redirect to checkoutUrl) The fastest way to go live. Your server initializes a transaction via the API, receives a checkoutUrl , and redirects the customer to it. Monnify handles the entire payment UI and redirects the customer back to your site when done. #### Step 1 – Authenticate Base64-encode your apiKey:secretKey and call the login endpoint to get a Bearer token (valid for 1 hour). #### Step 2 – Initialize the Transaction > **Important:** Always confirm that the values returned by this endpoint match what you sent in the request payload. Bad actors can intercept requests and alter values such as the transaction amount. #### Step 3 – Redirect the Customer Take the checkoutUrl from Step 2's response and redirect the customer to it. Monnify handles the full payment UI from here. > **Checkout expiry:** The checkoutUrl is valid for 40 minutes . If the customer does not complete payment within this window, the transaction expires and they must start again. #### Step 4 – Handle the Redirect Callback After payment, Monnify redirects the customer to your redirectUrl with the result as query parameters: > **Always verify server-side:** Never fulfill an order based on the redirect URL parameters alone. Always call the Verify Transactions API from your server before delivering value. ### Option B – Build Your Own Payment UI (Raw Endpoints) If you want to build a fully custom payment flow with your own bank transfer screen and card form, use the raw API endpoints below instead of the hosted checkout URL. #### Pay with Bank Transfer Call the Pay with Bank Transfer endpoint with the transactionReference of an initialized transaction. Monnify returns a dynamic virtual account number your customer transfers to. - You can call this endpoint multiple times; each call returns how many seconds the account remains valid (maximum 2400 seconds / 40 minutes). - Pass a bankCode to also receive a USSD code for that bank. - Inform your customers of the account expiry to prevent failed or erroneous transfers. > **Note:** The virtual account is valid for 40 minutes . Always display this expiry clearly to your customers. #### Charge Card Call the Charge Card endpoint with the customer's card details and the transactionReference of an initialized transaction. > **PCI-DSS required:** Access to the direct card charge endpoint requires PCI-DSS certification. Contact integration-support@monnify.com to apply. ### Request Field Reference Field Required Description amount Yes Payment amount in NGN (or USD for enabled merchants). paymentReference Yes Your unique order reference. Must be unique per transaction. contractCode Yes Your contract code from the Monnify dashboard. redirectUrl Yes (Option A) Where Monnify redirects the customer after payment. Not required when building your own UI. currencyCode No Defaults to NGN . Use USD if enabled for international card collection. paymentMethods No Restrict available payment methods. Omit to show all. incomeSplitConfig No Split the payment across multiple sub-accounts. See Transaction Splitting . ### Common Error Messages Error Message Meaning Action Unknown currency code supplied The currencyCode is not supported on your account. NGN is default; USD is only available for merchants specifically enabled for international card collection. Use NGN or USD (if enabled). Could not find specified contract The contractCode is invalid or does not belong to the authenticated merchant. Verify your contract code in the dashboard and ensure it matches the environment (test vs. live). Duplicate payment reference The paymentReference has already been used by this merchant in this environment. Generate a unique reference for every new transaction. Invalid Card Number The card PAN supplied is incorrect. Verify the card number and retry. Merchant has not been configured for bin The first six digits of the card PAN are not among Monnify's supported card bins. Customer should confirm the card is a Nigerian-issued card, or contact Monnify support. Could not find transaction with the specified transaction reference The transaction reference does not exist for this merchant. Confirm the reference and retry. --- ## [Checkout Page](https://developers.monnify.com/docs/collections/one-time-payments/checkout-page) > Integrate the Monnify Checkout Page into your website or mobile app using the JS, Android, Flutter, or iOS SDK. Customers pay via bank transfer, card, USSD, or phone number, all inside a Monnify-hosted modal. ## Checkout Page The Monnify Checkout Page is a pre-built payment UI that opens as a modal on your website or inside your mobile app. It handles all payment methods (bank transfer, card, USSD, and phone number) so your customers can pay without leaving your platform. > - **Pay with Bank Transfer:** A dynamically generated account number is displayed for the transaction. The customer transfers the exact amount from any bank app. - **Pay with USSD:** A bank-specific USSD code is generated. The customer dials it to authorize the payment with no internet connection required. - **Pay with Card:** The customer enters their debit card details directly in the Monnify modal. - **Pay with Phone Number:** The customer enters their phone number to initiate a payment session from their mobile wallet. Option A – Script tag (no bundler) Drop the Monnify script into your HTML and call MonnifySDK.initialize() directly. No installation needed. Option B – npm Package (React, Vue, Angular) If you're using a framework with a bundler, install the package that matches your project: Both packages expose the same class-based API. Instantiate with your credentials and call initializePayment() . Here's a React example: Always verify the transaction server-side using the Verify Transactions API before fulfilling an order. Monnify will also notify you via webhook for every completed transaction. ### User Cancelled Response If the customer closes the modal, Monnify returns the following to your ** onClose ** function: **Controlling which payment methods appear:** By default all methods are shown. Pass a paymentMethods array to restrict them: - Card Payment - Bank Transfer - USSD Payment - Payment by Phone Number ### Steps to Implementation **1. Add the dependency for the Monnify SDK** To your root build.gradle file add: To your app-level build.gradle file add: **2. Create an instance of the Monnify SDK** - Card Payment - Bank Transfer - USSD Payment - Payment by Phone Number ### Steps to Implementation **1. Add the dependency for the Monnify SDK** Add monnify_payment_sdk as a dependency in your pubspec.yaml file. **2. Initialize the plugin** Initialize once, preferably in the initState of your widget. **3. Initialize payment** Create a Transaction object and pass it to initializePayment . - Card Payment - Bank Transfer - USSD Payment - Payment by Phone Number ### Steps to Implementation - **Add the SDK via CocoaPods.** Add the following line to your Podfile: - **Access the shared SDK instance.** - **Set your API key and contract code** in AppDelegate.swift . Do this once at app startup. Switch to ApplicationMode.live for production builds. - **Specify the transaction parameters:** - **Launch the payment modal when the customer taps Pay.** Option C – WordPress / WooCommerce #### Step 1 – Install the Plugin - In your WordPress admin, go to **Plugins > Add New**. - Search for **Monnify** and click **Install Now** on the _Monnify Official_ plugin. - Click **Activate** once installation completes. Alternatively, download the ZIP from the WordPress Plugin Directory (https://wordpress.org/plugins/monnify-official/) and upload it via **Plugins > Add New > Upload Plugin**. #### Step 2 – Configure Your API Keys - Go to **WooCommerce > Settings > Payments**. - Find **Monnify** in the list and click **Manage**. - Enter your **API Key**, **Secret Key**, and **Contract Code** from the Monnify dashboard . - Set the environment to **Sandbox** for testing or **Live** for production. - Click **Save changes**. > **Where to find your keys:** Log in to your Monnify dashboard , navigate to Settings > API Keys & Webhooks . Your Contract Code is under Settings > Contracts . #### Step 3 – Test in Sandbox With the environment set to **Sandbox**, place a test order on your WooCommerce store and complete the payment using a test card or bank transfer. Confirm that the WooCommerce order status updates to _Processing_ before going live. #### Step 4 – Go Live Switch the plugin environment to **Live**, replace your sandbox keys with your live API Key, Secret Key, and Contract Code, then save. Your store is now accepting real payments. > **Webhook setup:** To keep WooCommerce order statuses in sync automatically, add your webhook URL in the Monnify dashboard under Settings > API Keys & Webhooks . Your WooCommerce webhook URL is: https://yourstore.com/?wc-api=monnify_webhook --- ## [Invoice](https://developers.monnify.com/docs/collections/one-time-payments/invoice) > Monnify Invoicing allows you to generate invoices for your customers using our Create Invoice API. Each invoice can either be static or dynamic, depending on your business needs. ## Invoice Monnify Invoicing allows you to generate invoices for your customers using our Create Invoice API. When you create an invoice, Monnify either generates a unique virtual account number tied to that invoice or provides a checkout URL so customers can make payments directly with their debit cards. > ### Types of Invoices Monnify supports two types of invoices: **Static Invoices** and **Dynamic Invoices**. Both are created using the same Create Invoice API but differ in how virtual accounts are generated and used. Feature Static Invoice Dynamic Invoice Virtual Account Number Same account reused for a specific customer New account generated for every invoice Account Availability Dormant until attached to an active invoice Active only for the duration of that invoice Use Case Recurring billing, subscriptions, repeat customers One-time payments, single-use invoices Post-Payment Behavior Account becomes dormant until next invoice Account expires and cannot be reused KYC Requirement Requires customer BVN or NIN to reserve the account No BVN/NIN required ### 1. Static Invoicing (Invoice Reserved Accounts) Static invoicing is ideal when you bill the same customer repeatedly, for example, subscriptions, recurring services, or regular payments. Instead of generating a new virtual account number each time, Monnify lets you **reserve a dedicated account number** for that customer. This account number stays the same across all future invoices you send them, but it can only accept payments when attached to an active invoice. > **Info:** Important: Reserving a virtual account requires the customer's BVN or NIN to comply with regulatory KYC requirements. Once the account is reserved, you can generate as many invoices as needed without repeating the KYC step. #### Steps to Implement Static Invoicing Follow these steps to set up and use static invoicing in your integration: - **Reserve a Virtual Account:** Use the Create Invoice Reserved Account API to reserve a dedicated account for a customer. You will need to provide the customer’s **BVN or NIN** as part of this process. The response will include a accountReference that uniquely identifies the reserved account. - **Attach an Invoice to the Reserved Account:** Once the account is reserved, use the Create Invoice API to generate an invoice linked to that reserved account. You must pass the accountReference you obtained earlier in the request payload. The invoice will use the same virtual account number every time. - **Send Invoice to Customer:** Share the generated invoice details with your customer. They can pay by transferring funds into the reserved account or through the provided checkout URL. - **Handle Post-Payment Behavior:** Once the invoice is paid, it expires immediately and the reserved account goes dormant. It remains inactive until a new invoice is generated for that customer. **Key characteristics:** - A single virtual account number is reserved for a customer and reused for every invoice you send them. - Customers cannot make payments into this account unless it’s attached to an active invoice. - After payment, the invoice closes, and the account becomes dormant until the next invoice is generated. - Requires customer BVN or NIN during the initial reservation step. - Ideal for recurring billing, subscription-based services, or repeat customers. #### Sample Request – Static Invoice ### 2. Dynamic Invoicing Dynamic invoicing is the simplest and most flexible way to bill customers. Each time you create an invoice, Monnify automatically generates a **unique virtual account number** tied to that specific invoice. Once the invoice is paid, it expires immediately, and the account number is no longer valid. This approach is ideal when you do not bill the same customer repeatedly or when you want a fresh virtual account for every transaction. It requires no prior account reservation or KYC step. #### Steps to Implement Dynamic Invoicing Follow these steps to set up and use dynamic invoicing in your integration: - **Create an Invoice:** Call the Create Invoice API endpoint to generate a new invoice. A virtual account number will be automatically created and linked to that invoice. - **Send Invoice to Customer:** Share the invoice details with your customer. They can pay by transferring funds into the generated virtual account number or by using the provided checkout URL. - **Handle Post-Payment Behavior:** Once payment is made, the invoice expires immediately. Since a new virtual account is generated for each invoice, subsequent invoices will each have their own dedicated account numbers. **Key characteristics:** - A new virtual account number is generated for every invoice created. - No prior account reservation or BVN/NIN is required. - Once paid, the invoice expires immediately, and the virtual account is no longer active. - Ideal for one-time payments, unique transactions, or scenarios where customers vary frequently. #### Sample Request – Dynamic Invoice **Additional Notes:** - For static invoices, once an invoice expires or is paid, the reserved account simply goes dormant until a new invoice is created. - For dynamic invoices, a new virtual account is generated for every new invoice, and previous account numbers cannot be reused. Field Reference Error Message Meaning Action Invoice with this reference already exists. This implies that the invoiceReference in the request payload has already been used by you. Retry with a unique invoiceReference Unknown Contract Code provided. The contractCode in the request parameter is not correct or it doesn’t belong to the merchant. Navigate to the "Settings > Contract Setup", section of your Monnify dashboard to get your contact code Amount must be greater than 20. This implies that the amount field in the request payload must be at least 20 Naira Increase the amount above N20 Unknown currency code supplied. The currency code supplied is not valid or not enabled on your account. NGN is the default supported currency; USD is only available for merchants specifically enabled for card-based USD collection. Reconfirm that NGN is the currency code provided. Invalid invoice expiry date. This implies that the expiryDate in the request payload is before the current date. Invoice expiry date should be beyond current time. Invalid invoice expiry date format This implies that the expiryDate in the request payload is not in the correct format. Change invoice expiry date format to match yyyy-MM-dd HH:mm:ss. --- ## [Offline Pay-ins](https://developers.monnify.com/docs/collections/one-time-payments/offline-payins) > You can accept cash payments from your customers offline through Moniepoint Agents. Moniepoint is an agency banking platform with a wide reach, having agents in every local government in Nigeria. ## Offline Pay-ins Offline collections are mechanisms that enable merchants to receive cash payments from their customers via a Moniepoint Business Owner location. Through Monnify, merchants are notified about these payments so they can automatically provide value to their customers, similar to digital payment methods. Moniepoint, being an agency banking platform with agents across every local government in Nigeria, facilitates this service. > Offline Collections/Pay-ins are defined as inbound payments made to you as a merchant by your customers via the Moniepoint Business Owner location. > **Feature Activation Required** Offline Products are not enabled by default on any account. To request access, send an email to integration-support@monnify.com with your use case and an indemnity covering potential use and misuse of the feature. The Monnify team will review your request and activate the feature on your account if approved. ### Workflow and How It Works Before accepting cash payments, a merchant must first create an offline product - The merchant creates products for customers using the Monnify dashboard or API - The customer visits any Moniepoint business owner/Agent to pay for a listed product - The Agent validates the customer by entering their ID on the POS or web app - After verification, the agent either sees the payment amount (for fixed products) or the customer specifies the amount (otherwise) - The Moniepoint business collects the cash and processes the payment. - If the customer requires a token after payment, the Moniepoint business generates and issues a receipt or value token; otherwise, only a receipt is issued - The merchant is notified of the transaction ### Offline Collection Products An offline product is a commodity of interest to the customer that they are willing to pay for. Monnify supports four categories of offline products: **1. Fixed Product:** This product has a fixed amount that a customer must pay for a service or product. Merchants must state the amount on the Monnify platform. For fixed product types, the amount must be stated by merchants on the Monnify platform. An example is a monthly fixed contribution. **2. Variable Product:** This product has a flexible amount. The merchant does not specify the amount, and the customer specifies how much they want to pay at the Moniepoint Business Owner’s location. Example: variable amount for betting. For variable product type, you do not specify the amount as the customer specifies how much they want to pay at the Moniepoint Business Owner’s location where collection is done. **3. Invoice Product:** This requires an invoice to be created for every payment. Unlike other types, the invoice does not become fully active upon creation on Monnify. To activate it, the Monnify Create an Invoice endpoint must be called, specifying "CASH" as the payment method. The amount to be paid is then tied to the generated invoice ID. **4. Merchant Invoice Product:** This product type allows merchants to designate a custom payment amount for each user. Merchants can dynamically adjust the product price during the payer verification stage by including the desired amount in their successful response to Monnify. ## Set Up And Endpoints After creating an offline product, the merchant must configure necessary endpoints to receive payments seamlessly. These endpoints are configured in the developer section, on the offline payment setup tab. > ### Payer Verification Endpoint (Mandatory) This endpoint is set up on the merchant’s end and is called by Monnify to verify a customer making payment at any Moniepoint business owner location. It’s also important to note that the response format returned by the merchant’s server should follow the format described below: **HTTP Method: POST** Request Parameters sent by Monnify: Parameter Description productCode A unique string identifying the created product. This code is automatically generated by Monnify when the product is created. paymentRecipientId This is the id that uniquely identifies the customer on the merchant’s end. **Sample request to be sent by Monnify:** **Expected response format from merchant:** When user is verified successfully; **Expected response format for MERCHANT_INVOICE product type:** When user does not exist; ### Payment Request Endpoint (Optional) This endpoint is necessary when merchants sell products or services that return a form of "value token" (e.g., meter token) after the customer makes payment. Also the merchant’s server should return a response in the format described below. **HTTP Method: POST** Request Parameters: Parameter Description amount The amount to be paid for the product transactionReference Monnify’s unique reference for transactions productCode This is the product code for the product to be purchased. . This code is automatically generated by Monnify when the product is created. paymentRecipientId This is the id that uniquely identifies the customer on the merchant’s end. **Sample request to be sent by Monnify:** **Expected response format from merchant:** Success response; Failed Response; ### Payment Requery Endpoint (Optional) If provided, this endpoint is called to retrieve the status of a payment request whose initial status is unknown. **HTTP Method: GET** Request Parameters: Parameter Description transactionReference This is the unique Monnify reference for the transaction.This reference is sent as a urlEncoded string and should be decoded on the merchant’s end **Sample request to be sent by Monnify:** **Expected response format from merchant:** For a successful response; For a failed response } --- ## [One-Time Payments](https://developers.monnify.com/docs/collections/one-time-payments) > Accept one-time payments on Monnify via the checkout page, checkout API, payment links, invoices, or offline pay-ins. Choose the integration style that fits your product. desc="One-time payments are single, non-recurring transactions where a customer pays for a product or service. Monnify gives you several ways to collect these payments, from a fully hosted checkout your customers complete in seconds to a raw API you build your own UI on top of." /> > **Not sure which to use?** Start with the Checkout Page (JS SDK / mobile SDK) for the fastest integration. Use the Checkout API or Invoice if you need a redirect flow, a custom payment UI, or time-bound virtual accounts. Use Payment Links if you want to collect payments without writing any code. ## Integration Options > ## Quick Comparison > Method Code required Hosted by Best for Checkout Page (SDK) Yes (SDK integration) Monnify (modal) Web and mobile apps needing a seamless in-app experience Checkout API Yes (server-side API) Monnify (redirect) or you Custom UI or redirect-based payment flows Payment Links No Monnify Freelancers, social commerce, quick collection without a website Invoice Yes (server-side API) Monnify Static invoices for repeat or recurring customers; dynamic invoices for one-time collections with a custom expiry date Offline Pay-ins Yes (payer verification endpoint required) Moniepoint Agent Merchants collecting cash from customers with limited access to digital payments, leveraging Moniepoint's nationwide agent network WordPress / WooCommerce Plugin No (plugin install only) Monnify (via plugin) WordPress merchants who want to accept payments on WooCommerce without writing code --- ## [Pay With Bank](https://developers.monnify.com/docs/collections/one-time-payments/pay-with-bank) > Pay with Bank is a payment method that enables customers to pay directly from their bank account without leaving your checkout experience. ## Pay with Bank Pay with Bank is a payment method that enables customers to pay directly from their bank account without leaving your checkout experience. > Unlike a traditional bank transfer, where the customer copies a virtual account number, opens their banking app, and completes the transfer manually, Pay with Bank streamlines the process. The customer simply selects their bank, enters their account number, verifies the payment with a One-Time Password (OTP), and authorizes the transaction—all within a secure authentication flow. Once the payment is successfully authorized, Monnify processes the transaction and notifies your application through the transaction verification and webhook flow. > **Note** Pay with Bank currently supports Moniepoint Bank. Support for additional banks will be added over time without requiring changes to your integration. ### Bank Transfer vs Pay with Bank Feature Bank Transfer Pay with Bank Customer copies a virtual account number Yes No Customer opens their banking app Yes No Customer enters their account number No Yes Customer authorizes with an OTP No Yes Real-time payment confirmation Yes Yes Standard Monnify webhooks Yes Yes - Initialize a transaction. - The customer selects Pay with Bank as their preferred payment method. - The customer enters their account number. - Their bank sends a One-Time Password (OTP). - The customer enters the OTP to authorize the payment. - Monnify processes the transaction. - Your application receives the payment result through transaction verification or webhook notifications. Integration Method Description Hosted Checkout (Recommended) Add PAY_WITH_BANK to the paymentMethods array. Monnify handles the complete customer authentication experience. Direct API Integration Build your own payment experience by integrating directly with the Pay with Bank APIs. Regardless of the integration method you choose, transaction verification and webhook notifications remain the same. ### Option 1: Hosted Checkout (Recommended) If you're already using the Monnify Checkout (Web SDK or Checkout URL), enabling Pay with Bank requires no additional API calls. Simply include PAY_WITH_BANK in the paymentMethods array when initializing your transaction. When the checkout page is displayed, customers will see Pay with Bank as one of the available payment methods alongside any others you've enabled. After selecting Pay with Bank, the customer: - Enter their account number. - Receives a One-Time Password (OTP) from their bank. - Enter the OTP to authorize the payment. - Completes the transaction. - Is redirected back to your application. - Monnify processes the transaction. No additional backend integration is required when using the Monnify Checkout. > **Note** PAY_WITH_BANK can be used together with other payment methods such as CARD and ACCOUNT_TRANSFER. If multiple payment methods are enabled, the customer can choose their preferred option during checkout. ### Option 2: Direct API Integration Choose this option if you're building your own payment experience and are not using the Monnify hosted checkout. #### Step 1: Initialize a Transaction Initialize a Monnify transaction using the Transaction Initialization API . The response includes a transactionReference , which is required for the next step. #### Step 2: Initialize Pay with Bank #### Step 3: Redirect the Customer The authorizationUrl contains the secure bank authentication page. Redirect your customer to this URL to complete authentication. The customer will: - Enter their account number. - Receives a One-Time Password (OTP) from their bank. - Enter the OTP to authorize the payment. - Return to your application. You can verify payments in one of two ways: - Call the Verify Transaction API . - Listen for Monnify webhook notifications . You can also retrieve the latest Pay with Bank attempt for a transaction using the status endpoint. Bank Bank Code Moniepoint 50515 Support for additional banks will be added over time. Existing integrations will continue to work without modification as new banks become available. ### Best Practices - Always verify completed payments using the Verify Transaction API or webhook notifications . - Do not rely on the customer's return to your application as proof of payment. - Store the transactionReference for reconciliation and support. - If you're using the hosted checkout, simply add PAY_WITH_BANK to the paymentMethods array—no additional integration is required. - If you're building a custom checkout, always redirect customers to the returned authorizationUrl to complete authentication. } --- ## [Payment Links](https://developers.monnify.com/docs/collections/one-time-payments/payment-links) > Payment link is designed to simplify the way individuals and businesses receive payments. With Payment links, you can create a straightforward, personalised link that allows you to collect payments without the need for a website, coding knowledge, or complex integrations. This solution is perfect for a wide range of users, from event organisers and solopreneurs to SMEs and digital creators, looking to streamline their payment processes. desc="This is designed to simplify the way individuals and businesses receive payments. With Payment links, you can create a straightforward, personalised link that allows you to collect payments without the need for a website, coding knowledge, or complex integrations. This solution is perfect for a wide range of users, from event organisers and solopreneurs to SMEs and digital creators, looking to streamline their payment processes. " > ### Why should you use a payment link? - No Code Required: You can set up your Payment link without any technical expertise. - No Integration Needed: The feature is designed to be easy to use, requiring no special integration efforts. - No Website Needed: A Payment link can serve as a standalone web presence or be linked to an existing site. - Collect additional customer information ### Who can use the payment link? - Event Organizers: For simple and efficient ticket sales. - Solopreneurs: To sell products directly to customers. - SMEs and Startup Businesses: Perfect for those without an existing website. - Individuals: For personal payment links. - Freelancers: To streamline payment collections without a structured system. - Digital Creators: To monetize content easily. ### How to Use Payment Links **1. Set up a Link:** Create your Payment link from your merchant app or by going to Monnify payment links Use the link as a form to collect additional customer data **2. Customise payment link:** Customise payment link look **3. Manage Payments** - Notifications: Receive alerts via email or webhook for successful payments. - Dashboard: Access a comprehensive dashboard to view all your links, the details of transactions, and additional information collected from customers. - Data Export: Easily export data for record-keeping or analysis. - Fund Management: Oversee the funds settled from your payments in a streamlined manner --- ## [Accept Payments](https://developers.monnify.com/docs/collections) > Learn how to receive payments from your customers using the Monnify APIs, List of Pricing / Fees - Local Card Payments, Transfers (Dynamic), Transfers (Customer Reserved Account), USSD, Phone, Bank, Offline Collections > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ## 🚀 Getting Started > ## Plugins and SDKs Get up and running with Monnify plugins and SDKs. > --- ## [Payment Methods](https://developers.monnify.com/docs/collections/payment-methods) > Overview of all payment methods supported by Monnify: bank transfer, debit card, USSD, phone number, direct debit, and customer reserved accounts. ## Payment Methods Monnify supports a range of payment methods so your customers can pay the way that suits them best. You can choose to offer all methods or restrict to specific ones per transaction. > ### Account Transfer (Bank Transfer) The most popular payment method in Nigeria. When a customer selects this option, Monnify generates a **dynamic virtual account number** for that specific transaction. The customer transfers the exact amount to that account from any bank app or USSD code, and Monnify confirms the payment instantly. - **Dynamic accounts**: Each transaction gets a fresh virtual account, preventing mismatches. - **Expiry**: Accounts are valid for 40 minutes (2400 seconds). Notify your customer of this window. - **Supported banks**: Customers can pay from any Nigerian bank. See Supported Banks . - **USSD code included**: If you pass a bankCode when retrieving account details, Monnify also returns a USSD string the customer can dial. SDK key: "ACCOUNT_TRANSFER" ### Debit Card Customers can pay using their Mastercard, Visa, or Verve debit card. Monnify handles the card collection flow within the checkout modal, including 3D Secure authentication where required. - **Tokenization**: Cards can be tokenized after a successful payment for future charges without the customer re-entering their details. See Card Tokenization . - **USD support**: Merchants enabled for international collection can accept card payments in USD. - **PCI-DSS**: If you want to build your own card collection UI using the raw Charge Card API, PCI-DSS certification is required. Contact integration-support@monnify.com . SDK key: "CARD" ### USSD Customers dial a bank-specific USSD code to authorize the payment directly from their phone, with no internet connection required. This is ideal for customers without smartphones or in low-connectivity areas. - Monnify generates the USSD string as part of the bank transfer response when a bankCode is provided. - The same dynamic virtual account is used, and payment is confirmed the moment the USSD session completes. SDK key: "USSD" ### Phone Number Customers enter their phone number to initialize a payment session. They then receive a prompt on their feature phone or smartphone to authorize the debit from their mobile money wallet. SDK key: "PHONE_NUMBER" ### Customer Reserved Account (Virtual Account) A persistent virtual account number dedicated to a specific customer. Unlike the dynamic account used for one-time payments, a reserved account stays the same, and every transfer to it is automatically reconciled to that customer. Best for: - Wallet top-ups (fintechs, betting platforms, investment apps) - Subscription billing via bank transfer - Utility payment collection (electricity, internet) See Reserved / Virtual Accounts for full integration details. ### Direct Debit / Mandate A "pull" payment method. The merchant creates a mandate and the customer authorizes it once. After that, Monnify can automatically debit the customer's bank account on a schedule without them needing to initiate each payment. Best for: - Loan repayments - Insurance premiums - SaaS subscription billing in Nigeria See Direct Debit / Mandates for full integration details. ### Controlling Which Methods Are Shown By default, all available payment methods appear on the checkout. You can restrict them per transaction using the paymentMethods array in either the SDK initialization or the Initialize Transaction API payload. - JS/Web SDK (script tag) or npm packages ( monnify-js for JavaScript, monnify-ts for TypeScript): pass paymentMethods: ["CARD", "ACCOUNT_TRANSFER"] - Initialize Transaction API: pass "paymentMethods": ["ACCOUNT_TRANSFER", "USSD", "PHONE_NUMBER"] - Flutter SDK: pass paymentMethods: [PaymentMethod.CARD, PaymentMethod.ACCOUNT_TRANSFER] > **Note:** Omitting paymentMethods shows all available methods. Passing an empty array will cause an error, so always include at least one method. ### Method Availability by Integration Type Method Checkout (SDK) Checkout API Reserved Account Bank Transfer ✓ ✓ ✓ Debit Card ✓ ✓ (PCI-DSS) — USSD ✓ ✓ ✓ Phone Number ✓ — — --- ## [Quickstart – Accept Payments](https://developers.monnify.com/docs/collections/quickstart) > Get your first Monnify payment integration live in minutes. Choose between the Checkout SDK (no server authentication needed) or the full API flow. ## Quickstart Get your first payment flowing in minutes. Pick the path that matches how you > ### Before You Begin You will need: - A **Monnify merchant account**. Sign up at app.monnify.com - Your **API Key, Secret Key** and **Contract Code** from **Developers > API Keys & Contracts** on your dashboard > **Sandbox first:** Use your test API key and the base URL https://sandbox.monnify.com while building. Switch to https://api.monnify.com and your live keys when you are ready to go live. ### Choose Your Integration Path Checkout SDK No server authentication needed Drop a script tag into your page and call MonnifySDK.initialize() with your API Key and Contract Code. Monnify handles the rest. **Best for:** frontend-only setups, quick integrations, and most web apps. (#path-a) API-First Full server-side control Authenticate on your server to get a Bearer token, initialize the transaction via API, then redirect the customer to the hosted checkout or call the payment APIs directly. **Best for:** custom checkout flows, server-rendered apps, and headless payment integrations. (#path-b) WordPress / WooCommerce No code required Install the official Monnify plugin from the WordPress plugin directory, enter your API keys in WooCommerce settings, and you're ready to accept payments. **Best for:** WordPress merchants who want payments without writing any code. (#path-c) --- ### Path A – Checkout SDK (No Authentication Required) Use this path if you want to open Monnify's payment modal directly from your frontend. You only need your apiKey and contractCode , with no server-side token exchange needed. #### Step 1 – Add the SDK and Open the Checkout Option A – Script tag (no bundler) Drop the Monnify script into your HTML and call MonnifySDK.initialize() directly. No installation needed. Option B – npm Package (React, Vue, Angular) If you're using a framework with a bundler, install the package that matches your project: Both packages expose the same class-based API. Instantiate with your credentials and call initializePayment() . Here's a React example: Only mark an order as fulfilled when paymentStatus === "PAID" and amountPaid matches your expected amount. #### Step 3 – Handle Webhooks Set your webhook URL in **Developers > Webhook URLs** on the Monnify dashboard. Monnify will POST a notification to your endpoint for every completed transaction. Use this as a reliable server-side trigger instead of relying only on the onComplete callback. See the Webhooks section for the full list of event types and how to verify the webhook signature. --- ### Path B – API-First Integration Use this path when you need full server-side control: authenticate to get a Bearer token, initialize a transaction via the API, and then either redirect the customer to the checkoutUrl or open the checkout from your frontend. #### Step 1 – Authenticate All Monnify API calls require a Bearer token. Generate one by Base64-encoding your apiKey:secretKey and calling the login endpoint. Tokens expire after 1 hour. Store the accessToken and send it as Authorization: Bearer on every subsequent request. #### Step 2 – Initialize a Transaction Call the Initialize Transaction endpoint with your payment details. Use a unique paymentReference per transaction. #### Step 3 – Open the Checkout You have two options for presenting the payment UI to your customer: Option A – Redirect to Checkout URL Redirect the customer directly to the checkoutUrl returned in Step 2. Monnify will redirect them back to your redirectUrl after payment. Option B – Call Payment APIs Directly Skip the hosted checkout entirely and drive the payment flow from your server. Two methods are available after initializing a transaction: - **Pay with Transfer**: pass your transactionReference to the Pay with Bank Transfer endpoint and Monnify returns a dynamic, time-bound account number. Display that account number in your own UI; once the customer transfers the exact amount to it, Monnify notifies you via webhook. No PCI-DSS required. - **Charge a Card**: collect card details in your own UI and submit them directly to Monnify's card charge endpoint . This bypasses the checkout UI completely but requires **PCI-DSS certification**. Contact integration-support@monnify.com to enable this on your account. #### Step 4 – Verify the Payment (Server-Side) > **Critical:** Always verify the transaction on your server before delivering value. Never trust the client callback alone, as it can be tampered with. Only mark an order as fulfilled when paymentStatus === "PAID" and amountPaid matches your expected amount. #### Step 5 – Handle Webhooks Set your webhook URL in **Developers > Webhook URLs**. Monnify will POST a notification to your endpoint for every completed transaction. Use this as a reliable server-side trigger instead of relying only on the redirect callback. See the Webhooks section for the full list of event types and how to verify the webhook signature. --- ### Path C – WordPress / WooCommerce Plugin Running a WordPress store? Skip the code entirely. The official Monnify WooCommerce plugin adds card and bank transfer as payment options to your checkout with a few clicks. #### Step 1 – Install the Plugin - In your WordPress admin, go to **Plugins > Add New**. - Search for **Monnify** and click **Install Now** on the _Monnify Official_ plugin. - Click **Activate**. Or download the ZIP directly from the WordPress Plugin Directory (https://wordpress.org/plugins/monnify-official/) and upload it via **Plugins > Add New > Upload Plugin**. #### Step 2 – Enter Your API Keys - Go to **WooCommerce > Settings > Payments** and click **Manage** next to Monnify. - Enter your **API Key**, **Secret Key**, and **Contract Code** from the Monnify dashboard . - Set the environment to **Sandbox** for testing, then **Save changes**. > **Where to find your keys:** In your Monnify dashboard, go to Settings > API Keys & Webhooks for your API Key and Secret Key. Your Contract Code is under Settings > Contracts . #### Step 3 – Test, then Go Live Place a test order on your store in Sandbox mode to confirm payments are working. Once satisfied, return to the plugin settings, switch the environment to **Live**, swap in your live keys, and save. > **Webhook setup:** Add your webhook URL in the Monnify dashboard under Settings > API Keys & Webhooks so WooCommerce order statuses update automatically when customers pay. Your webhook URL is: https://yourstore.com/?wc-api=monnify_webhook --- ### Next Steps - Explore all Payment Methods supported by Monnify - Checkout API : integrate using the JS, Android, Flutter, or iOS SDK - Verify Transactions : detailed guide on server-side verification - Going Live : checklist before switching to your production keys --- ## [Card Tokenization](https://developers.monnify.com/docs/collections/recurring-payments/card-tokenization) > Tokenize a customer's card during their first payment and use the token to charge them in future without requiring card details again. ## Card Tokenization Tokenize a customer > Card Tokenization allows you to debit a customer's card automatically on future transactions, without requiring any input from the customer. After the customer completes their first card payment with tokenization enabled, Monnify generates a secure token representing their card. You store this token and use it to charge them on subsequent payments. ### How It Works - The customer makes their **first payment** using the Monnify checkout or SDK. If tokenization is enabled on your merchant account, Monnify will automatically generate a card token on successful payment. - On successful payment, you call the **Get Transaction Status API** to retrieve the cardToken from the cardDetails object. - You **store the cardToken ** securely on your server, linked to the customer's account and email address. - For future charges, you send the cardToken to the **Charge Card Token API** with no checkout UI required. > **Enable tokenization first:** Card tokenization must be activated on your integration before use. Contact integration-support@monnify.com to enable this feature on your account. ### Step 1 – Collect the First Card Payment If card tokenization is enabled on your merchant account, Monnify automatically returns a card token after any successful card payment — no additional parameter is needed in your SDK call. ### Step 2 – Retrieve the Card Token After the first payment completes, call the Get Transaction Status API using the transaction's transactionReference or paymentReference . The cardDetails object in the response contains the cardToken . > **Sandbox behaviour:** In the sandbox environment, Monnify does not return a real cardToken . Instead, check the supportsTokenization field in reusable : true means the card would produce a token in production, and false means it would not. ### Step 3 – Store the Card Token Once you have the cardToken , store it securely on your server alongside the customer's email address used for the original transaction. Both the token **and the email must match** on every subsequent charge, as Monnify validates this pair. - Treat the token like a sensitive credential and store it encrypted at rest. - Never expose the token to the client (browser or mobile app). - Link the token to the customer's internal user ID so you can retrieve it when scheduling future charges. ### Step 4 – Charge the Token (Future Payments) Use the stored cardToken to charge the customer for future payments. This call happens entirely server-to-server, with no checkout UI required. ### Token Lifecycle & Best Practices - **One token per card per merchant**: if the same customer tokenizes the same card twice, you get the same token. - **Expired cards**: the token becomes invalid when the underlying card expires. Re-collect card details from the customer and tokenize again. - **Customer consent**: always inform customers that you are saving their card for future charges. This is a regulatory and trust requirement. - **Webhook on charge**: Monnify sends a webhook notification for every token-based charge, just like a regular payment. See Webhooks . - **Verify every charge**: always call the Verify Transactions API after a token charge before delivering value. ### Sample Error Messages Error Message Meaning Action Card token has expired. The supplied token has expired. Ask the customer to complete a new card payment with tokenization enabled to generate a fresh token. Invalid card token The token supplied in the request does not exist or is malformed. Verify that the token stored in your database matches what was returned from the Get Transaction Status API. Duplicate payment reference The paymentReference used in the init-transaction request was already used in the same environment. Generate a unique reference for every new transaction. --- ## [Direct Debits](https://developers.monnify.com/docs/collections/recurring-payments/direct-debit) > Monnify Account Direct Debit is a simple, secure and convenient ‘pull’ payment method that allows merchants to automatically collect recurring payments from a payer directly from their Account. ## Direct Debits Monnify Account Direct Debit is a simple, secure and convenient ‘pull’ payment method that allows merchants to automatically collect recurring payments from a payer directly from their Account. > > **Feature Activation Required** Direct debit is not enabled by default on any account. To request access, kindly send an activation email to integration-support@monnify.com . The Monnify team will review your request and activate the feature on your account if approved. ### Key Processes Monnify Direct Debit enables merchants to set up recurring payments by creating and activating mandates for customers. The process involves mandate creation, customer authorization, and mandate activation/debiting. ### Mandate Management Workflow A mandate is the agreement between a customer and a merchant that authorizes recurring debits. Below are all possible mandate statuses: Mandate Status Description PENDING Mandate creation is in progress. PENDING AUTHORIZATION Mandate is awaiting customer authorization. PENDING ACTIVATION Mandate has been authorized by the customer and is awaiting activation by the customer’s financial institution. ACTIVATED Mandate has been activated and can now be debited. AUTHORIZATION EXPIRED Mandate authorization expired because the customer didn’t authorize it within the available timeframe. EXPIRED Mandate has reached its expiration time. CANCELLED Mandate was canceled by the merchant. SUSPENDED Mandate was suspended by the customer’s financial institution. ### Ways To Use Depending on your business needs, mandates can be configured in four ways: - **Open Flexible:** Varying amounts, no end date. Example: utility company debiting based on usage. - **Open Fixed:** Fixed amount, no end date. Example: streaming subscription until cancelled. - **Closed Flexible:** Varying amounts with an end date. Example: car instalment plan over 12 months. - **Closed Fixed:** Fixed amount with an end date. Example: insurance premiums of ₦10,000 monthly for 12 months. ## Mandate Creation & Activation Flow Monnify routes mandates to the right provider depending on bank configuration: - **TeamApt:** Used if the customer’s bank is enabled for the merchant on TeamApt. Mandates require customer authorization via the provided URL. - **NIBSS:** Used if the bank is not enabled on TeamApt. NIBSS mandates are also authorized via URL for better experience. For testing, static instructions can be mocked. The process has three steps: (1) create mandate, (2) customer authorizes mandate via authorization link, and (3) once activated, merchant can debit the account. ## API Integration Workflow Setting up a direct debit with Monnify follows a 5-step workflow. Each step corresponds to an API call or customer action in the mandate lifecycle. - **Initiate Mandate Creation:** Merchants send a request to the Create Mandate API with customer and mandate details. - **Mandate Routing:** Monnify automatically routes the mandate to the appropriate provider: **TeamApt** → if the customer’s bank is enabled for the merchant on TeamApt. - **NIBSS** → if the bank is not enabled on TeamApt. - **Mandate Creation:** A unique mandateReference and authorization link are generated. The mandate status is set to PENDING_AUTHORIZATION . This link is valid for 30 days. - **Customer Authorization:** Merchants must share the authorization link with customers (via app, email, or SMS). The customer uses the link to provide consent and authorize the mandate. - **Mandate Activation:** **TeamApt mandates** → Activated once the customer completes authorization via the URL. - **NIBSS mandates** → Preferably activated via the authorization URL for a smoother experience. Static instructions can be mocked for testing. ### Create Mandate ### Sample Response ### Key Notes for Merchants - **Bank Availability:** Each merchant account is configured with specific banks enabled on either TeamApt or NIBSS. Confirm your setup. - **Authorization Links:** Always share links with customers promptly so mandates are not delayed or expired. - **Testing with NIBSS:** You can mock NIBSS mandates since the instructions are static. - **Essential APIs:** Use the Create Mandate and Get Mandate Status APIs for integration. ### Mandate APIs - ** Create Mandate: ** Create a mandate on the customer's bank account. - ** Get Mandate Status: ** Check the status of an existing mandate. - ** Debit Mandate: ** Debit the account linked to an activated mandate. - ** Get Debit Status: ** Check the debit status on a mandate. - ** Update Mandate: ** Cancel or update a mandate. - ** Get Mandates: ** Retrieve a paginated list of mandates you have created. ### Get Mandate Status ### Debit Mandate ### Get Debit Status ### Get Mandates The Get Mandates endpoint lets you query all mandates created under your merchant account. You can filter results by date range, customer email, scheme code, or mandate status, making it easy to reconcile mandates and track their lifecycle at scale. Parameter Required Description startDate Yes Start of the date range. Format: YYYY-MM-DDTHH:MM:SS . The range must not exceed 90 days. endDate Yes End of the date range. Format: YYYY-MM-DDTHH:MM:SS . The range must not exceed 90 days. customerEmail No Filter results to mandates belonging to a specific customer email. schemeCode No Filter by direct debit scheme code (e.g. ADD ). mandateStatus No Filter by mandate status. Accepted values: PENDING , ACTIVE , FAILED , CANCELLED , EXPIRED . page No Zero-based page number. Defaults to 0 . limit No Number of records per page. Defaults to 20 . ### Supported Banks The table below lists all banks supported for direct debit mandates and their default activation mode. Use the filter to view banks by activation type. ### Error Messages Error Message Meaning Action Mandate start date cannot be in the past The mandate start date was set earlier than the current time. Adjust the date to a future time. Unable to validate account information Account name validation failed for the supplied account number and bank code. Confirm that the account number and bank code are correct. Unable to find bank against customerAccountBankCode The bank code supplied does not exist on Monnify. Reconfirm that the bank code is for a CBN-approved bank. Mandate with provided mandate reference already exists. The mandateReference has been previously used. Retry with a unique mandateReference. --- ## [Recurring Payments](https://developers.monnify.com/docs/collections/recurring-payments) > Set up recurring payments on Monnify using reserved accounts, direct debit mandates, or card tokenization. Automate collections for subscriptions, loan repayments, and wallet top-ups. desc="Recurring payments let you collect money from customers on an ongoing basis without requiring them to manually initiate each payment. Monnify supports three approaches depending on your use case, so pick the one that fits your product." /> > **When to use recurring payments:** Use recurring payments for subscriptions, loan repayments, insurance premiums, wallet top-ups, or any scenario where you need to collect money from the same customer more than once. ## Choose Your Approach > ## Choosing the Right Method > Method Customer action required Best for Reserved Account Transfer to their dedicated account Wallet top-ups, savings, investment apps Direct Debit One-time mandate authorization Loan repayments, insurance, subscription billing Card Tokenization First card payment only SaaS subscriptions, one-click renewals --- ## [Customer Reserved Account](https://developers.monnify.com/docs/collections/recurring-payments/reserved-accounts) > Customer Reserved Account - Monnify allows merchants to receive customer payments via bank transfers, debit cards, USSD, and through the use of phone numbers. Every time a transaction is initiated, the Monnify SDK displays a distinct account number, which customers can pay into by using any of the available Monnify payment methods. ## Customer Reserved Account This feature allows you to generate a virtual account for your customers. The account number generated is dedicated to a customer and every payment to that virtual account is associated with the customer for which the account was reserved. > These accounts are very useful for merchants whose; - **Customers can only pay for a single service:** This is common for electricity companies, internet service providers, etc. The account reserved for the customer in this scenario allows them to pay for a service by doing a simple transfer to their reserved account and the payment is confirmed. - **Businesses that involves the use of a wallet:**Here, an account number is reserved for each customer's wallet to enable them to top up by simply transferring to that account. Examples of this are Super Agents, Investment Applications, Betting Platforms, Logistics Applications, etc. > **Note:** For virtual accounts generated in Sandbox, Use the Monnify Payment simulator to complete test payments. Real transactions are not supported in Sandbox mode. ### How does Customer Reserved Account work? - You can generate a reserved account for your customers by making a POST request to the Reserve an Account API. - Once the account is created, the customer can then make payments to the reserved account at any time. - Once the transfer is made by the customer, the partner bank gets notified, Monnify is notified and the merchant is then notified of the transaction on the account - The transaction details along with the account reference for the transaction is made available to the merchant. > **Note:** If you want to reserve accounts across all partner banks for your customers, you will need to pass “true” for the “getAllAvailableBanks” field. For now, Moniepoint bank accounts are the default virtual accounts. ### Create Reserved Account > **Note:** Please note that the BVN or NIN of your customer must be supplied when sending this request. ### Reserve Account Response Body ### Invoice Reserved Account Monnify invoice reserved account allows you to reserve an account for your customers to whom you send invoices to regularly. This account can be attached to invoices being generated for a customer so that the same account number is received for every invoice peculiar to that customer. These accounts are slightly different from regular customer reserved accounts as customers cannot pay into these accounts until they are attached to an invoice. Basically, the account number is inactive until when attached to an invoice and returns to it's inactive state when the invoice is paid. See Invoice Reserved-Account API for details on how to implement one. ### Reserved Account Creation on Monnify Dashboard To create reserved account via the Monnify dashboard, kindly navigate to the reserved account section, click on the “create new” button and populate the fields shown in the image below; ### Split payments on Reserved Accounts The incomeSplitConfig field allows you to use split payments with your reserved accounts by specifying one or more sub-account(s) and a specific percentage of each payment to be credited into each sub-account. IncomeSplitConfig is an array of objects so you can split into multiple sub-accounts per transaction. ### Sample Request ### Transaction Limits You can establish a limit on a customer's account using the Transaction Limit APIs. This means that on a customer's account, you can specify the maximum amount per transaction, the maximum number of transactions per day, and the total amount per day. To do so, you will need to create a Limit Profile and use the Limit Profile code to assign customers to the limit profile. In managing Transaction Limits, you can do the following - **Create Limit profiles:** The Create Limit API , allows you to set a limit on a customers account. Once the POST request has been made to this endpoint, a limit profile code is returned. This code becomes the unique identifier for the limit profile created, and will be used to reference the limit profile in reserve account requests. - **Update Limit profile:** To make updates to any limit profile you have created, you are required to make a PUT request to the Update Limit Profile API , providing updates such as, the single transaction value, daily transaction volume and daily transaction value. - **Reserve Account with Limit:** You can create a reserved account on Monnify and creating a limit profile on the account. It works similar to creating a reserve account, except that a limit profile code in included in the request to create the reserved account. See Reserve Account with limit API - **Get Limit profiles:**The Get Limit Profile API helps you get a list of all the limit profiles you have created. - **Update Reserve Account Limit:** The Update Reserve Account Limit API helps you update the information on an existing limit profile created for a reserved account. ### Restriction of Payment Sources on Reserved Accounts Merchants are able to restrict source accounts that can fund a reserved account using either BVNs or Account Name or Account Number. This is mandatory if the **restrictPaymentSource** request parameter is set to true. This feature is useful for merchants in a regulated business category, where only the authorized user(s) of a reserved account should fund the reserved account, to allow more payment sources, only BVNs will be used to allow more payment sources other than the default customerBvn already on a reserve account. The rule application is as follows: - If only account numbers are specified, funding of account will be restricted to specified account numbers. - If only account names are specified, funding of account will be restricted to specified account names. - If both account numbers and account names are specified, funding will be permitted when either of the two rules match, i.e. source account number matches specified account numbers or source account name matches specified account name. ### Sample Request ### Sample Response ### Update Reserved Account KYC Info The Update Kyc Info API allows merchants to link a customer's BVN and/or NIN to their respective static reserved account. The API accepts either the customer’s BVN or NIN or both, subject to the following merchant requirements: - For accounts that wish to enjoy the maximum transaction limit, both BVN and NIN must be linked to the reserved account. - For accounts with limited transaction amounts, one of NIN or BVN is required. Field Reference Error Message Meaning Action You can not reserve two accounts with the same reference. The accountReference parameter in the request payload has already been used by you. Retry with a unique accountReference You cannot reserve more than 1 account(s) for a customer. Please contact support for assistance. There is an exisiting active reserved account generated with this customerEmail. Kindly share exsting account details with your customer. Invalid contract code supplied. The contractCode in the request parameter is not correct or it doesn’t belong to the merchant. Navigate to the "Settings > Contract Setup", section of your Monnify dashboard to get your contact code Is invalid. Must be 11 digits This most times implies that the BVN provided is invalid If BVN/NIN is supplied, confirm that it has the required length BVN or NIN is required. BVN and NIN were not supplied in the request payload. Retry with the BVN and/or NIN details of the customer. Unknown currency code supplied. The currency code supplied is not valid or supported Reconfirm the currency code supplied We do not support virtual accounts from banks with code XXX. This implies that we do not create virtual account for some of the bank codes passed in the preferredBanks array Retry with any of the supported bank codes Unknown sub account code XXXXXXX. The happen when using the incomeSplitConfig and the sub account doesn’t belong to the merchant. Kindly confirm from the SubAccount section of your Monnify dashboard if the subAccount being used exists there R42 You cannot reserve more than 1 account(s) for a customer. Please contact support for assistance. Kindly use unique customer email when generating reserved account --- ## [Retry & Failure Handling](https://developers.monnify.com/docs/collections/recurring-payments/retry-failure-handling) > Build robust retry flows for failed recurring payments. Detect failures by verifying transaction status, notify customers, and implement retry logic to recover revenue. ## Retry & Failure Handling Payment failures are normal in recurring billing. This guide shows you how to detect failures, communicate with customers, and implement a retry strategy that recovers revenue without creating a poor customer experience. > ### Types of Failures - **Insufficient funds**: the customer's account does not have enough balance at the time of the debit. - **Card expired**: the tokenized card has expired and the token is no longer valid. - **Mandate debit failure**: a direct debit mandate debit was rejected by the customer's bank (e.g. account restricted, mandate limit exceeded). - **Bank downtime**: temporary unavailability on the customer's bank side. - **Transaction timeout**: the payment session expired before the customer completed it. ### Step 1 – Detect Failures Monnify only sends a webhook notification when a transaction is **successful**. The event type is `SUCCESSFUL_TRANSACTION`. There is no webhook for failed or pending transactions. To detect a failure, your server must actively check the transaction status after the expected payment window: - Listen for the SUCCESSFUL_TRANSACTION webhook on your configured webhook URL. - If the webhook does not arrive within a reasonable window (e.g. 2–5 minutes after initiating the charge), call the Get Transaction Status endpoint with the payment reference. - Inspect the paymentStatus field in the response. A status of PAID means the payment succeeded. Any other status (including PENDING or FAILED ) means the transaction did not complete. > **Always verify server-side:** Never rely solely on client-side callbacks to determine payment outcome. Always confirm the status via the server-side transaction status API before granting or revoking access. ### Step 2 – Classify the Failure Not every failure should trigger an immediate retry. Classify failures before acting: Failure Reason Retryable? Recommended Action Insufficient funds Yes Retry after 4–8 hours; notify customer to fund account. Bank downtime / timeout Yes Retry after 1–6 hours. Card expired No Do not retry. Prompt customer to add a new card. Mandate limit exceeded No A new mandate is needed with the right amount. Account restricted No Customer must resolve with their bank before retrying. ### Step 3 – Notify the Customer Send a notification as soon as you confirm the failure via the transaction status check. Timely communication significantly improves recovery rates. - Tell the customer exactly what happened (e.g. "Your payment of ₦5,000 was not completed"). - Give them a clear action: fund their account, update their card, or pay manually via a payment link. - Include a direct **payment link** so they can resolve it in one click. See Payment Links . > **Dunning best practice:** Space out retry notifications so customers do not feel harassed. A common pattern: notify immediately, then at 24h, then at 72h, then a final notice before service suspension. ### Step 4 – Implement Retry Logic For retryable failures (e.g. insufficient funds, bank downtime), implement a retry schedule on your server. The handler below covers both card token charges and direct debit mandate debits: > **Use a job queue for production:** setTimeout is for illustration only. In production, use a durable job queue (Bull, Agenda, AWS SQS, etc.) so retries survive server restarts and can be monitored. ### Step 5 – Verify Every Retry After each retry attempt (whether from your scheduler or a customer paying manually), always verify the transaction status server-side before restoring access. Only restore access when paymentStatus === "PAID" and amountPaid matches the expected amount. See Verify Transactions for the full response reference. ### Direct Debit Retry Flow For Direct Debit / Mandates , Monnify sends a `MANDATE_UPDATE` webhook whenever the mandate's status changes (e.g. activated, suspended, cancelled). A failed debit attempt will not always trigger a webhook. To confirm whether a debit succeeded, poll the **Get Debit Status** endpoint using the debit reference returned when you initiated the debit. If the debit did not succeed: - Schedule another debit attempt against the same mandate (for retryable failures such as insufficient funds or bank downtime). - Fall back to a payment link or new mandate if the mandate itself is no longer valid (expired, cancelled, or suspended). > **NIP mandate retry rules:** Banks may have restrictions on how frequently a mandate can be debited, Monnify currently sets limit to 2 per day. Check the specific terms of the mandate type to avoid unnecessary bank-side rejections. --- ## [Bulk Transfers](https://developers.monnify.com/docs/disbursements/bulk-transfers) > With the Monnify Transfer API, you can pay multiple recipients at once with the Monnify bulk transfer feature. ## Bulk Transfers The Monnify Bulk Transfer API allows you to send money to multiple recipients in a single request. Each entry in the batch is processed individually, and you receive a consolidated status for the entire batch. This guide walks you through the prerequisites and the full integration flow. > **Making Bulk Disbursement From UI** You can perform a bulk transfer directly from your Monnify dashboard. Simply click on Bulk Transfer, download the provided template, and fill in the necessary details. Once, a response is gotten, there are two possible responses that can be gotten. ### Before You Begin Before integrating the Bulk Transfer API, make sure you have completed the following steps: - **Enable Disbursements on your account** Disbursements is not enabled by default on Monnify. To request access, navigate to **Settings > Preferences** on your Monnify dashboard. Under the **Disbursements** section, enable the **"Enable Disbursements to third party accounts"** toggle. This automatically submits a request for your account. Once submitted, the request will be reviewed internally before the feature is approved and enabled for your account. - **Whitelist your server IP address** For security in the **Live** environment, Monnify only processes disbursement requests from whitelisted static IP addresses. After you submit your disbursement enablement request from the dashboard, our team will send a follow-up email to your registered business email address requesting the information required to complete the setup, including the static IP address(es) to be whitelisted. Once your IP address(es) have been whitelisted and the feature has been approved, you can begin making disbursement requests. If you need to whitelist additional IP addresses after your account has been configured, contact integration-support@monnify.com . Requests originating from IP addresses that have not been whitelisted will be rejected with a **D06** error. - **Understand how MFA (OTP) works** Multi-Factor Authentication (MFA) via OTP is **enabled by default** for all disbursement accounts in both Sandbox and Live instances. When MFA is active, each transfer request will return a PENDING_AUTHORIZATION status and require you to submit an OTP before the transfer is processed. The OTP is sent to the registered email address on your Monnify account. If your integration handles transfers programmatically and you do not need OTP authorization, you can request for MFA to be disabled by contacting integration-support@monnify.com . > **Note** You can merge and send the three requests above as a single email. As part of the email, you will be expected to indemnify Monnify for potential use and misuse of the feature as it pertains to your wallet balance with us. ### Integration Flow Once your account is set up, here is the typical flow for a bulk transfer: - Initiate the bulk transfer: your server sends a batch request to Monnify with a list of transactions (Maximun of 5000). - If MFA is enabled, authorize the batch by submitting the OTP received via email. - Poll the batch status or receive webhook notifications as individual transactions are processed. ### Initiating a Bulk Transfer Make a **POST** request to the Initiate Transfer (Bulk) API with your batch details. The response will differ depending on whether MFA is enabled on your account. > **Use the right account details** Before initiating a bulk transfer, use the Name Enquiry API to look up and verify each recipient's account. The name returned should be passed as the destinationAccountName for each entry. Submitting a mismatched name will cause that transaction to fail. To get the correct destinationBankCode , use the Get Banks API to retrieve the full list of supported banks and their codes. > **Validation Status Options** The `onValidationFailure` field expects either `BREAK` or `CONTINUE`. **BREAK** means the request should stop the moment an account validation fails, **CONTINUE** means to skip the specific account number that failed validation and continue the execution of the request. **Response (MFA enabled, OTP required):** **Response (MFA disabled, batch proceeds immediately):** ### Authorizing a Bulk Transfer (MFA / OTP) If your account has MFA enabled and you received a PENDING_AUTHORIZATION batch status, you must authorize the batch by submitting the OTP sent to your registered email. Make a **POST** request to the Authorize Transfer (Bulk) API . ### Resending an OTP If the OTP was not received or has expired, you can request a new one via the Resend OTP API . ### Getting Bulk Transfer Status To check the status of a batch, make a **GET** request to the Bulk Transfer Status API with the batch reference. ### Getting Bulk Transfer Transactions To retrieve a paginated list of all individual transactions within a batch and their statuses, make a **GET** request to the Get Bulk Transfer Transactions API . Provide pageNo (starts at 0) and pageSize as query parameters. ### Searching Disbursement Transactions To search across all your disbursement transactions, make a **GET** request to the Search Disbursement Transactions API . You can filter by reference, status, date range, and more. ### Getting Your Wallet Balance You can check the available balance in your Monnify disbursement wallet at any time by making a **GET** request to the Wallet Balance API . ### Batch Status Reference Status Description PENDING_AUTHORIZATION MFA is enabled and the batch is waiting for OTP authorization before it can be processed. OTP_EMAIL_DISPATCH_FAILED Monnify could not send the OTP email. Use the Resend OTP API to request a new one. AWAITING_PROCESSING The batch has been authorized and is queued for processing. IN_PROGRESS The batch is currently being processed. Individual transactions may complete at different times. COMPLETED All transactions in the batch have been processed. Check individual transaction statuses for results. FAILED_ON_ACCOUNTS_VALIDATION One or more transactions failed account validation. If onValidationFailure is set to BREAK , the entire batch is halted. FAILED The batch could not be processed. Check the error message for the reason. ### Transaction Status Reference Status Description PENDING, AWAITING_PROCESSING and IN_PROGRESS The transaction is still being processed. Re-query to get the final status. SUCCESS and COMPLETED The disbursement was processed successfully and the recipient has been credited. REVERSED The disbursement was reversed. The funds have been returned to your wallet. FAILED The disbursement was not successful. Check the error message for the reason. EXPIRED The transaction was not authorized within its validity period. Initiate a new transfer. Field Reference Error Code Meaning Recommended Action 99 An unexpected error occurred while processing the transaction. Re-query to confirm the transaction status before retrying. D01 Something went wrong and the transaction could not be processed. The actual error will be in the responseMessage field. Treat as Failed. D02 Transaction does not exist. Treat as Failed. D03 Invalid account details supplied. Treat as Failed. D04 Insufficient wallet balance. Top up your Monnify wallet and retry. D05 The reference supplied has already been used for a previous transaction. Retry with a new unique reference. D06 Unauthorized request. The request originated from an IP address that is not whitelisted. Send your server IP address to integration-support@monnify.com (mailto:integration-support@monnify.com) for whitelisting. D07 Duplicate request. A transfer to the same account for the same amount was made within a 2-minute window. Retry after 2 minutes, or contact integration-support@monnify.com (mailto:integration-support@monnify.com) to disable duplicate detection. Invalid destination account number The account number did not pass name enquiry validation. Ask the customer to provide a valid account number. Dormant beneficiary account The recipient's account is dormant. The customer should contact their bank. Beneficiary account name mismatch The account name does not match the account number. Ask the customer to reconfirm their account details. Unknown destination bank code The bank code supplied is not recognized on Monnify. Confirm the correct destinationBankCode from the list of supported banks. Transaction timed out while waiting for destination bank The recipient's bank did not respond in time. Re-query the transaction status. Invalid amount The transaction amount is invalid. Confirm the transaction amount and retry. Delayed processing from NIP Delay from the NIP (interbank network). Re-query the transaction status. Post No Credit restriction on beneficiary account The recipient's account has a Post No Debit (PND) restriction and cannot be credited. The customer should contact their bank. Beneficiary bank not available The recipient's bank is currently unavailable. Re-query the transaction status. Invalid session ID The session ID for the transaction is invalid. Re-query the transaction status. Rejected by destination institution The credit was rejected by the recipient's bank. The customer should contact their bank to find out the reason. Suspected fraud The recipient's account is under investigation for fraud. The customer should contact their bank. Invalid response code from beneficiary institution An unrecognized response code was received from the recipient's bank. Re-query the transaction status. System malfunction by destination institution The recipient's bank is experiencing a system issue. Re-query the transaction status. Beneficiary account limit exceeded The recipient's account is a low-KYC account and cannot receive the transfer amount. The customer should contact their bank to upgrade their account tier. Sender not permitted to credit beneficiary The recipient's account has a restriction that prevents it from being credited. The customer should contact their bank to identify and resolve the restriction. Unable to complete the transaction at this time The recipient's bank or payment provider is currently unavailable. Re-query the transaction status. Transaction could not be processed at this time. Please try again The payment provider is currently unavailable. Re-query the transaction status. Transaction processing in progress The transaction is still being processed. Re-query the transaction status. Account number could not be validated Name enquiry failed: the account number may be invalid or the destination bank is unavailable. Reconfirm the destination account details and check bank availability. Transaction Failed The transaction failed due to a system or provider error. Contact Monnify support. System Malfunction - Internal service failure The transaction failed due to an internal Monnify error. Contact Monnify support. System Malfunction - Transaction transmission unsuccessful The transaction failed due to a system malfunction during transmission. Contact Monnify support. Processor Malfunction - Transaction transmission failed An error occurred during transaction processing with NIBBS. Re-query the transaction status. --- ## [Offline Pay-outs (Paycode)](https://developers.monnify.com/docs/disbursements/offline-payout) > A paycode is a short form for a payment code. It is a 10-digit number generated by merchants for their customers to take to a Moniepoint Agent to withdraw cash. ## Offline Pay-outs (Paycode) Offline disbursements are cash payments made by the merchant to their customers through a Paycode generated on the Monnify platform. This feature allows customers to withdraw cash from a Moniepoint Business Owner. > > **Info:** FEE: For offline disbursements done using paycodes, a flat fee of N 100 will be charged. ### Paycode Definition and Features A Paycode is a short form for a payment code. It is a 10-digit number that a merchant generates and provides to a customer to withdraw cash at a Moniepoint Agent. Merchants generate this paycode and provide it to customers who then take this paycode to any Moniepoint business owners close by. Once the paycode is shown to the agent, the paycode is verified and the amount tied to the paycode is given to the customer in cash while the merchant account is debited of the amount. Key features of a paycode include: - The Generated code: A 10-digit number. - Beneficiary Name: Beneficiary of a paycode. - Status: The status of the paycode could be Pending, Success, Expired, or Cancelled. - Created Date: This is the date that the paycode was created. - Expiry Date: This is a date in the future when the paycode will expire. - Reference: Unique reference per merchant for each paycode. ### Workflow and How It Works - Merchant generates paycode on the Monnify platform. - Merchant shares paycode with their customer. - Customer visits Moniepoint business owners. - Customer provides paycode. - Moniepoint verifies the paycode by calling the Monnify validation endpoint. - Monnify debits merchants and returns responses to Moniepoint. - Moniepoint business owners gives cash to the customer. ### Paycode Generation Merchants can generate paycode for their customers from their dashboard by using the create new paycode button. Upon clicking the **Create New Paycode** button, you are redirected to a page to provide details that should be linked with the paycode which is what the Moniepoint business owners will use to verify the transaction before releasing funds to the your customers. Details to be provided include beneficiary name (name of customer for funds to be disbursed to), amount to be disbursed, reference, and also expiry date (If expiry date for paycode is not defined, it will expire by default after 24 hours) as shown; And after filling in the required details, he can click on the make transfer button to complete the transfer process. ### Paycode API Paycodes can also be generated using the Paycode generation APIs. Below is a list of endpoints required for paycode management. - ** Create Paycode: ** This endpoint helps generate a paycode for a transaction, check Create Paycode API for more information. - ** Cancel Paycode: ** This endpoint helps to cancel a paycode after it has been created, check Cancel Paycode API for more information. - ** Get Paycode: ** This endpoint is called to get details of a paycode that has been created. The paycode returned is always masked as a layer of security. check Get Paycode API for more information. - ** Get Clear Paycode: ** This endpoint provides a clear view of the paycode once authorization is provided, check Get Clear Paycode API for more information. - ** Fetch Paycodes: ** This endpoint provides all paycodes that have been created within a specific period, check Fetch Paycode API for more information. When a Paycode is created or used, it’s list of possible status are outlined as follows; **PENDING** - Ready to be used but not used. **SUCCESS** - Has been utilized successfully. **EXPIRED** - Has been automatically expired having exhausted the configured lifespan. **CANCELLED** - Was canceled by the user. In general, all offline products can easily be tested from the Simulator tab on the developer section of the monnify dashboard. } --- ## [Transfer/Payout](https://developers.monnify.com/docs/disbursements) > Send Money to Nigerian Bank Accounts with Monnify. Learn how to make transfers with Monnify. > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ## Transfers The Monnify transfer API enables you to initiate payouts from your Monnify Wallet to any bank account in Nigeria. > --- ## [Single Transfers](https://developers.monnify.com/docs/disbursements/single-transfers) > With the Monnify Transfer API, you can send money to bank accounts and money wallets. ## Single Transfers The Monnify Single Transfer API allows you to send money directly to a bank account or mobile wallet in real time. This guide walks you through the prerequisites and the full integration flow. #### Before You Begin Before integrating the Single Transfer API, make sure you have completed the following steps: - **Enable Disbursements on your account** Disbursements is not enabled by default on Monnify. To request access, navigate to **Settings > Preferences** on your Monnify dashboard. Under the **Disbursements** section, enable the **"Enable Disbursements to third party accounts"** toggle. This automatically submits a request for your account. Once submitted, the request will be reviewed internally before the feature is approved and enabled for your account. - **Whitelist your server IP address** For security in the **Live** environment, Monnify only processes disbursement requests from whitelisted static IP addresses. After you submit your disbursement enablement request from the dashboard, our team will send a follow-up email to your registered business email address requesting the information required to complete the setup, including the static IP address(es) to be whitelisted. Once your IP address(es) have been whitelisted and the feature has been approved, you can begin making disbursement requests. If you need to whitelist additional IP addresses after your account has been configured, contact integration-support@monnify.com . Requests originating from IP addresses that have not been whitelisted will be rejected with a **D06** error. - **Understand how MFA (OTP) works** Multi-Factor Authentication (MFA) via OTP is **enabled by default** for all disbursement accounts in both Sandbox and Live instances. When MFA is active, each transfer request will return a PENDING_AUTHORIZATION status and require you to submit an OTP before the transfer is processed. The OTP is sent to the registered email address on your Monnify account. If your integration handles transfers programmatically and you do not need OTP authorization, you can request for MFA to be disabled by contacting integration-support@monnify.com . > **Note** You can send merge and send the three requests above as a single email. As part of the email, you will be expected to idemnify Monnify for potential use and misuse of the feature on your platfrom. ### Integration Flow Once your account is set up, here is the typical flow for a single transfer: - Initiate the transfer: your server sends a transfer request to Monnify. - If MFA is enabled, authorize the transfer by submitting the OTP received via email. - Poll or receive a webhook notification for the final transfer status. ### Initiating a Transfer Make a **POST** request to the Initiate Transfer (Single) API with your transfer details. The response will differ depending on whether MFA is enabled on your account. > **Use the right account details** Before initiating a transfer, use the Name Enquiry API to look up and verify the recipient's account. The name returned should be passed as the destinationAccountName in your request. Submitting a mismatched name will cause the transfer to fail. To get the correct destinationBankCode , use the Get Banks API to retrieve the full list of supported banks and their codes. **Response (MFA enabled, OTP required):** **Response (MFA disabled, transfer proceeds immediately):** ### Authorizing a Transfer (MFA / OTP) If your account has MFA enabled and you received a PENDING_AUTHORIZATION status, you must authorize the transfer by submitting the OTP sent to your registered email. Make a **POST** request to the Authorize Transfer (Single) API . ### Resending an OTP If the OTP was not received or has expired, you can request a new one via the Resend OTP API . #### Asynchronous Transfers By default, Monnify processes transfers synchronously and your server waits for a final status. If you prefer not to block your server, you can process transfers asynchronously by setting async to true in your request. Monnify will send the final status to your webhook URL once the transfer is processed. ### Transfer with Sender Details You can specify the actual sender's details on a transfer so that the recipient's bank statement shows the real sender rather than your business name. This is particularly useful for platforms that process transfers on behalf of other parties. Include a senderInfo object in your request payload. ### Getting Transfer Status To check the status of a transfer, make a **GET** request to the Single Transfer Status API with the transaction reference. ### Getting All Transfers You can retrieve a paginated list of all single transfers from your account by making a **GET** request to the Get All Single Transactions API . Provide pageNo (starts at 0) and pageSize as query parameters. ### Searching Disbursement Transactions To search across all your disbursement transactions, make a **GET** request to the Search Disbursement Transactions API . You can filter by reference, status, date range, and more. #### Getting Your Wallet Balance You can check the available balance in your Monnify disbursement wallet at any time by making a **GET** request to the Wallet Balance API . ### Transaction Status Reference Status Description PENDING, AWAITING_PROCESSING and IN_PROGRESS The transaction is still being processed. Re-query to get the final status. PENDING_AUTHORIZATION MFA is enabled and the transfer is waiting for OTP authorization before it can be processed. OTP_EMAIL_DISPATCH_FAILED Monnify could not send the OTP email. Use the Resend OTP API to request a new one. SUCCESS and COMPLETED The disbursement was processed successfully and the recipient has been credited. REVERSED The disbursement was reversed. The funds have been returned to your wallet. FAILED The disbursement was not successful. Check the error message for the reason. EXPIRED The transaction was not authorized within its validity period. Initiate a new transfer. Field Reference Error Code Meaning Recommended Action 99 An unexpected error occurred while processing the transaction. Re-query to confirm the transaction status before retrying. D01 Something went wrong and the transaction could not be processed. The actual error will be in the responseMessage field. Treat as Failed. D02 Transaction does not exist. Treat as Failed. D03 Invalid account details supplied. Treat as Failed. D04 Insufficient wallet balance. Top up your Monnify wallet and retry. D05 The reference supplied has already been used for a previous transaction. Retry with a new unique reference. D06 Unauthorized request. The request originated from an IP address that is not whitelisted. Send your server IP address to integration-support@monnify.com (mailto:integration-support@monnify.com) for whitelisting. D07 Duplicate request. A transfer to the same account for the same amount was made within a 2-minute window. Retry after 2 minutes, or contact integration-support@monnify.com (mailto:integration-support@monnify.com) to disable duplicate detection. Invalid destination account number The account number did not pass name enquiry validation. Ask the customer to provide a valid account number. Dormant beneficiary account The recipient's account is dormant. The customer should contact their bank. Beneficiary account name mismatch The account name does not match the account number. Ask the customer to reconfirm their account details. Unknown destination bank code The bank code supplied is not recognized on Monnify. Confirm the correct destinationBankCode from the list of supported banks. Transaction timed out while waiting for destination bank The recipient's bank did not respond in time. Re-query the transaction status. Invalid amount The transaction amount is invalid. Confirm the transaction amount and retry. Delayed processing from NIP Delay from the NIP (interbank network). Re-query the transaction status. Post No Credit restriction on beneficiary account The recipient's account has a Post No Debit (PND) restriction and cannot be credited. The customer should contact their bank. Beneficiary bank not available The recipient's bank is currently unavailable. Re-query the transaction status. Invalid session ID The session ID for the transaction is invalid. Re-query the transaction status. Rejected by destination institution The credit was rejected by the recipient's bank. The customer should contact their bank to find out the reason. Suspected fraud The recipient's account is under investigation for fraud. The customer should contact their bank. Invalid response code from beneficiary institution An unrecognized response code was received from the recipient's bank. Re-query the transaction status. System malfunction by destination institution The recipient's bank is experiencing a system issue. Re-query the transaction status. Beneficiary account limit exceeded The recipient's account is a low-KYC account and cannot receive the transfer amount. The customer should contact their bank to upgrade their account tier. Sender not permitted to credit beneficiary The recipient's account has a restriction that prevents it from being credited. The customer should contact their bank to identify and resolve the restriction. Unable to complete the transaction at this time The recipient's bank or payment provider is currently unavailable. Re-query the transaction status. Transaction could not be processed at this time. Please try again The payment provider is currently unavailable. Re-query the transaction status. Transaction processing in progress The transaction is still being processed. Re-query the transaction status. Account number could not be validated Name enquiry failed: the account number may be invalid or the destination bank is unavailable. Reconfirm the destination account details and check bank availability. Transaction Failed The transaction failed due to a system or provider error. Contact Monnify support. System Malfunction - Internal service failure The transaction failed due to an internal Monnify error. Contact Monnify support. System Malfunction - Transaction transmission unsuccessful The transaction failed due to a system malfunction during transmission. Contact Monnify support. Processor Malfunction - Transaction transmission failed An error occurred during transaction processing with NIBBS. Re-query the transaction status. --- ## [MCP Server](https://developers.monnify.com/docs/integration/mcp-server) > Give your AI assistant the ability to accept payments, verify identities, manage virtual accounts, and query transactions through the Monnify MCP server. No custom integration code required. filename="" code= /> > **Sandbox first** Always test your MCP integration against sandbox before pointing it at production credentials. Actions triggered through an AI client, like debiting a mandate or processing a refund, call real Monnify endpoints and can move real money in production. ### Connect your AI client The server speaks the MCP stdio protocol, supported by all major AI tools. Register it in your client's MCP config, using your own API Key, Secret Key, and Contract Code in place of the placeholders below. Where a client supports it, pass credentials through the config's env block rather than embedding them in args , so they don't end up committed to a shared config file. }, , , , , , , , , ]}> Mac: ~/Library/Application Support/Claude/claude_desktop_config.json . Windows: %APPDATA%\\Claude\\claude_desktop_config.json . Simplest path is one command: Verify it loaded with claude mcp list . To share the setup with your team instead, add a .claude/mcp.json to your repo using the same servers shape shown under VS Code. Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in your project root: Create .vscode/mcp.json in your workspace root. VS Code uses a servers key with an explicit type instead of mcpServers : Mac: ~/Library/Application Support/ChatGPT/mcp.json . Windows: %APPDATA%\\ChatGPT\\mcp.json . Add to ~/.gemini/settings.json : Run gemini in your terminal, then type @monnify to confirm it's available. Add to ~/.codeium/windsurf/mcp_config.json : Add to ~/.config/zed/settings.json under context_servers : Add to ~/.continue/config.json . Continue.dev takes mcpServers as an array rather than an object: Restart your client after saving. You'll see "monnify" appear in its tools panel. ### Try it out With your AI client connected, try a few prompts against sandbox to confirm everything is wired up correctly. #### Payment collection - _"Initiate a payment of ₦15,000 for invoice #INV-2024-007 and send me the checkout link"_ - _"Create a dedicated virtual account for customer cust_089 so they can pay anytime by bank transfer"_ - _"Get me the status of transaction TRX-20240601-001"_ #### Engineering / integrations - _"List all banks and their codes so I can populate a dropdown in my checkout form"_ - _"Create a sandbox reserved account for test@example.com so I can test my webhook handler"_ - _"Show me the raw response from initiating a bank transfer so I can model my TypeScript types"_ - _"Check the status of mandate MND-2024-001 while I debug my direct debit flow"_ > **Keep your credentials out of prompts and version control** Never paste your API Key, Secret Key, or Contract Code directly into a chat with your AI client, and never commit a config file with production credentials to source control. Pass them via environment variables instead, for example MONNIFY_API_KEY . --- ## [Sample Codes](https://developers.monnify.com/docs/integration/sample-codes) > Monnify also provides libraries and plugins to extend the functionality of your application, which are: desc="Monnify also provides sample implementation of libraries and plugins to extend the functionality of your application, which are: " /> --- ## [Integration Guide for Monnify BVN Verification](https://developers.monnify.com/docs/integration-guide-bvn-nin-update) > The purpose of this document is to provide a comprehensive and clear set of instructions for developers or businesses integrating Monnify services in accordance with the Central Bank of Nigeria's circular on virtual accounts. This guide will specifically cover BVN verification endpoints, account creation, and updating existing accounts. ## Integration Guide for Monnify BVN Verification The purpose of this document is to provide a comprehensive and clear set of instructions for developers or businesses integrating Monnify services in accordance with the Central Bank of Nigeria > > **Monnify Update** This feature is only available Live Mode ### Table of Content - Introduction - About BVN - About NIN - Capturing BVN or NIN for new customers - Capturing BVN or NIN for old customers - Fees ### Introduction The Central Bank of Nigeria, released a circular recently, regarding virtual accounts issued to customers, as follows: - Every virtual account must be linked with either a Bank Verification Number (BVN) or National Identification Number (NIN). - For accounts that wish to enjoy the maximum transaction limit, both BVN and NIN must be linked to the Account Number. Following this update, we would be sharing with you below how to; - Verify BVN using Monnify BVN Verification endpoints - How to add BVN during Account Creation / when reserving an Account - How to Update Existing Account with BVN/NIN - A Sample Flow / Implementation ### About BVN #### What is BVN The Bank Verification Number (BVN) is a unique 11-digit identification number that uniquely identifies an account holder across all banks in Nigeria. #### How to get BVN An account holder can enrol for BVN by visiting any commercial bank branch in Nigeria. For customers who need to remember their BVN info, they can dial the USSD Code *565*0# on your number registered with BVN. There is a N20 service charge for checking BVN with USSD #### Verification process for BVN The objective of this step is to verify that the BVN supplied by a customer is correct and that the customer owns this BVN. This process often entails capturing the customer’s BVN and other bank account information, then sharing with a service which confirms the accuracy of this information. There are several services available for this and you can check out Monnify’s BVN verification API here ### About NIN #### What is NIN The National Identification Number (NIN) is your unique 11-digit identifier issued by the National Identification Management Commision (NIMC). #### How to get BVN To get a NIN Number you would be required to provide Original Birth Certificate and Valid Proof of Identity. You can find list of NIMC registration centers and designated enrollment agents on the NIMC website https://nimc.gov.ng/nimc-enrolment-centres (https://nimc.gov.ng/nimc-enrolment-centres) #### Verification process for BVN The objective of this step is to verify that the customer owns this NIN. This step entails capturing the customer’s NIN and other important information and sharing with a service which confirms the accuracy of this information. There are several services available for this and you can check out Monnify’s NIN verification in the Documentation section ### Capturing BVN or NIN for new customers - On your onboarding flow, implement a section to capture BVN or NIN from customers. - Verify the BVN or NIN information provided using your preferred verification service (as indicated in the description sections above) - Once this information is verified, complete the user sign up process on your application. - Send request to Monnify for account creation via this here , supplying the BVN and/or NIN captured. - Monnify would verify the information provided and generate virtual accounts as applicable - Save the accounts generated on your system and display them to the customer. ### Capturing BVN or NIN for existing customers - On a visible screen within your website or app, implement a notification bar to prompt users to update their KYC information. - On click of this notification bar, display a screen to capture BVN and/or NIN information for the user. - Verify the BVN or NIN information provided using your preferred verification service (as indicated in the description sections above)Once this information is verified by you, send a request to Monnify for account details update via this https://teamapt.atlassian.net/wiki/spaces/MON/pages/289046549/Reserve+An+Account+V2 , supplying the BVN and/or NIN captured. - Monnify would verify the information provided and save this information with the customer’s information. - On successful response from Monnify, display a message to the user accordingly. ### Applicable Fees Monnify would NOT charge merchants for creating accounts or updating account details with BVN or NIN. Those actions are completely free of charge as usual. However, to verify BVN / or NIN on a merchant's application, the verification method of choice may attract fees depending on the service being used. This is solely at the discretion of the merchant and not imposed nor charged by Monnify. --- ## [Integration Tools](https://developers.monnify.com/docs/integration-tools) > Learn how to verify the phone numbers, bank accounts, and BVNs of your customers. > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ## 🚀 Getting Started We > ## Plugins and SDKs > --- ## [Libraries and Plugins](https://developers.monnify.com/docs/integration-tools/plugin-libraries) > Monnify also provides libraries and plugins to extend the functionality of your application, which are:, Monnify Wordpress Plugin, Monnify Nodejs library(In Progress), Monnify Python library(In Progress), Monnify PHP library(In Progress), Monnify Java library(In Progress), Monnify Vue library(In Progress), Monnify React library(In Progress), Monnify Angular library(In Progress) ## Libraries and Plugins Monnify also provides libraries and plugins to extend the functionality of your application, which are: > --- ## [Sample Codes](https://developers.monnify.com/docs/integration-tools/sample-codes) > Monnify also provides libraries and plugins to extend the functionality of your application, which are: ## Sample Codes Monnify also provides sample implementation of libraries and plugins to extend the functionality of your application, which are: > --- ## [Monnify SDK](https://developers.monnify.com/docs/integration-tools/sdk) > SDKs (Software Development Kits), This section contains sample codes, plugins and implementations of Monnify webhooks. Monnify provides merchant with already made SDKs to make integration faster and easier, some of our them includes; ## Monnify SDKs (Software Development Kits) Monnify provides merchant with already made SDKs to make integration faster and easier, some of our them includes; > --- ## [Going Live](https://developers.monnify.com/docs/live) > A checklist of everything you need to verify before going live with Monnify. ### Going Live After successfully uploading the necessary documents and meeting compliance requirements, your Monnify account will be activated and you will be ready to go live. Before doing so, use the checklist below to confirm that every critical component is properly configured. This ensures smooth payment collection, accurate settlements, and reliable communication between Monnify and your application. ### 1. Switch to Live API Keys Your sandbox API Key and Secret Key are entirely separate from your live credentials. Using sandbox keys in production means your transactions will never actually process. A video on how to access your developer keys is available Here **Checklist:** Replace the sandbox **base URL** (`https://sandbox.monnify.com`) with the live base URL (`https://api.monnify.com`). Replace the sandbox **API Key** with your live API Key. Replace the sandbox **Secret Key** with your live Secret Key. Replace the sandbox **Contract Code** with your live Contract Code. ### 2. Configure Webhooks Webhooks allow Monnify to send real-time notifications to your server when transactions occur (e.g. payment received, disbursement completed, settlement made). Without a valid webhook URL, your application will not be notified of payment events automatically. See the different type of webhook events and sample body here **How to configure:** Navigate to **Developers > Webhook URLs** on your Monnify dashboard. Populate the relevant fields (Transaction Completion, Refund Completion, Disbursement, Settlement) with your server's webhook URLs, then click **Save**. **Checklist:** Transaction Completion webhook URL is set and reachable. Disbursement webhook URL is set (if using disbursement APIs). Refund and Settlement webhook URLs are set where applicable. Your server correctly validates the webhook hash/signature before processing notifications. ### 3. Whitelist Your Server IP Address (Merchants using Disbursement) If your application uses Monnify's disbursement (transfers) API, you must whitelist your server's IP address. This ensures that only requests from your server are accepted, adding an important layer of security against unauthorized transfers. **How to configure:** Send an email to **integration-support@monnify.com** requesting: Disabling OTP for API disbursement on your account. Whitelisting your server's static IP address(es). > **Important: Static IP Address(ess) Supported** Monnify supports withlisting of more than one IP addressess and supports both IPv4 and IPv6 addressess. Ensure your server has a static IP address before making this request. Dynamic IPs will cause disbursement requests to be rejected after an IP change. ### 4. Use the Correct Contract Code Every transaction on Monnify is tied to a contract. Using the wrong contract code can result in payments being processed under the wrong configuration, incorrect fee structures, or failed transactions. **Checklist:** Confirm the contract code used in your integration matches your live contract on the Monnify dashboard. Do not reuse sandbox contract codes in your live environment. If you have multiple contracts (e.g. for different products or business units), verify each service is pointing to the correct contract. Confirm you have the right Underpayment or Overpaymen configuration from **Settings > Contracts Setup**. By default, Monnify rejects over or under payment. ### 5. Verify Your Settlement Account Your settlement account is the bank account where Monnify pays out funds collected on your behalf. An incorrectly configured settlement account can result in settlements going to the wrong account. **Checklist:** Navigate to **Settings > Bank Accounts** on your dashboard and confirm the correct bank account is linked. Verify the account name, account number, and bank match your intended settlement destination. Ensure the settlement account has been validated/verified to receive inflow. Configure your settlemt report email address to ensure you get report of all settlement beside Webhooks. ### 6. Confirm Your Settlement Method Monnify supports two settlement methods: **Wallet** and **Bank Account**. Your choice determines where collected funds are held before being disbursed to you but it currently defaults to Wallet. - **Wallet Settlement:** Funds are settled into your Monnify wallet. You then initiate transfers to your bank account manually or via the API. This is suitable for businesses that need float or want to manage payouts programmatically. - **Bank Account Settlement:** Funds are settled directly into your designated bank account during the next settlement cycle (Same day 10PM). This is the simpler option for most businesses.(Go to **Settings** > **Contract Setup**, select the contract and choose the right Settlement destination) **Checklist:** Confirm your preferred settlement method is selected in your dashboard settings. If using wallet settlement, ensure your disbursement flow (manual or automated via API) is tested and working. --- ## [Customer Verification](https://developers.monnify.com/docs/verification-api) > Learn how to verify the phone numbers, bank accounts, and BVNs of your customers. > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ## 🚀 Getting Started > --- ## [Verifying your Customers](https://developers.monnify.com/docs/verification-api/verifying-your-customers) > With the Monnify Verification APIs, you can confirm account details, validate BVN information, and verify NIN data before performing financial transactions. ### Verifying your Customers The Monnify Verification APIs allow you to confirm the accuracy of your customers' identity and account details before performing any financial transaction. This helps you reduce failed transfers, prevent fraud, and meet KYC compliance requirements. This guide covers all four verification services and how to use each one. > **Environment and billing** The Name Enquiry API is free and available on both the Sandbox and Live environments. All other verification APIs (BVN and Account Name Validation, BVN Information Verification, and NIN Verification) are available on the Live environment only . Requests to these APIs will fail if your Monnify wallet balance is below the cost of the service being requested. #### Name Enquiry The Name Enquiry service lets you look up and confirm the name tied to a bank account number before initiating a transfer. Make a **GET** request to the Validate Bank Account API with the account number and bank code. #### BVN and Account Name Validation This service lets you verify that the BVN information supplied by your customers matches what is registered on their BVN record. Make a **POST** request to the BVN and Account Name Match API with the customer's BVN, bank code, and account number. #### BVN Information Verification This service allows you to verify that the Bank Verification Number (BVN) and account number provided by your customers match the BVN and account number linked to the account. Make a **POST** request to the BVN Details Match API with the customer's BVN and account details. > **Pricing** This service costs ₦10 per successful request. Ensure you account for this in your integration design, particularly if you are running high-volume verifications. #### NIN Verification This service allows you to verify the National Identification Number (NIN) supplied by your customers. Make a **POST** request to the NIN Verification API with the customer's NIN. > **Pricing** This service costs ₦60 per successful request. Ensure you account for this in your integration design, particularly if you are running high-volume verifications. ### Response Reference Field Type Description requestSuccessful Boolean Indicates whether the API request was received and processed successfully. responseCode String 0 means success. Any other value indicates a failure; check responseMessage for details. bvnAccountNameMatch Boolean Returned by the BVN and Account Name Validation service. true means the name matches the BVN record; false means it does not. bvnInformationMatch Boolean Returned by the BVN Information Verification service. true means the supplied details match the BVN record. ninInformationMatch Boolean Returned by the NIN Verification service. true means the supplied details match the NIN record. ### Error Reference Error Meaning Recommended Action Invalid account number The account number supplied could not be found at the specified bank. Ask the customer to confirm their account number and bank. Invalid bank code The bank code is not recognized on Monnify. Use the Get Banks API to confirm the correct bank code. Account number could not be validated Name enquiry failed. The destination bank may be temporarily unavailable. Retry after a short delay. If the issue persists, contact integration-support@monnify.com (mailto:integration-support@monnify.com). Invalid BVN The BVN supplied is not a valid 11-digit BVN. Ask the customer to confirm their BVN. Invalid NIN The NIN supplied is not a valid 11-digit NIN. Ask the customer to confirm their NIN. Service unavailable The verification service or the upstream identity provider is temporarily unavailable. Retry after a short delay. Contact integration-support@monnify.com (mailto:integration-support@monnify.com) if the issue persists. --- ## [Create Wallet](https://developers.monnify.com/docs/wallets/create-wallet) > The Monnify Wallet Creation API facilitates the process of creating wallets for customers. > **Monnify Update** This feature is only available on request Kindly send a request to our sales team sales@monnify.com for review. ### Creating Wallet To create wallets using the Monnify wallet creation API, you have to initiate a POST request to the Create Wallet API. (/api#tag/wallet/#create-wallet) The API requires that the customer's BVN is valid (although this is configurable on business review) and matches the date of birth associated with the BVN. Once these details are sent through the endpoint, the API will return a Moniepoint account number along with the wallet details. The associated account name will match the customer name provided in the request. #### Crediting The Wallet To credit the generated Monnify wallet, you simply make a bank transfer to the moniepoint account number returned from the Create Wallet API. (/api#tag/wallet/#create-wallet) #### Debiting The Wallet To debit the generated Monnify wallet, you simply make a POST request to the Single Transfer API or the Bulk Transfer API. The sourceAccountNumber in your request parameter becomes the internal accountNumber (that is the internal wallet id) of the generated wallet. --- ## [Get Wallets](https://developers.monnify.com/docs/wallets/get-wallets) > The Monnify Wallet Creation API facilitates the process of creating wallets for customers. ### Get Wallets The Monnify Get Wallets API helps retrieve a comprehensive list of customer wallets that have been generated by the merchant. When invoked, this API provides a response containing the complete collection of customer wallets that have been created. To retrieve all created wallets, you can make a GET request to the "Get Wallets" API. Additionally, merchants have the option to filter the request by providing either the customer's email address or the wallet reference. This allows for a more specific and targeted retrieval of wallets based on the provided filter criteria. --- ## [Wallet](https://developers.monnify.com/docs/wallets) > Create and manage digital wallets for operations and customer service needs > **Signing Up** Before you can start integrating to Monnify, you will need to create a Monnify account. ## Wallet Monnify Wallets API is an infrastructure service designed to empower businesses with the capabilities to create and manage digital wallets for their operations and customer service needs.. > --- ## [Wallet Balance](https://developers.monnify.com/docs/wallets/wallet-balance) > The Monnify Get Customer Balance API retrieves a customer's available balance. ### Get Customer Balance The Monnify Get Customer Balance API facilitates the retrieval of a customer's available balance by providing their wallet account number. To retrieve the wallet balance for a customer, simply append the imputed customer's wallet account id to the endpoint URL, and the account balance linked to the wallet will be returned. #### Get Wallet Transactions To retrieve transactions done on a customer's wallet, you simply make a GET request to the Wallet Transactions API. You can specify a pageNo and pageSize to get a parginated result. --- ## [Wallet Statement](https://developers.monnify.com/docs/wallets/wallet-statement) > The Monnify Wallet Statment API enable Merchants using wallets to conveniently generate a wallet statement ### Introduction The Monnify Statement feature enables merchants using wallets to conveniently generate wallet statements. This statement would contain: - Deposits into the wallets (Credits) - Withdrawals for payment (Debits) - Any charges where applicable - Balances on every transaction, - Transaction references and descriptions - Narration #### Feature Details To generate a wallet statement, the merchant would simply make a GET request to the Wallet statement API and specify the following in the request - Source Account number : The merchant's WALLET ACCOUNT NUMBER - Start Date (In Long format) : A timestamp value specifying the date to start filtering transactions by the createdAt field - End Date (In Long format): A timestamp value specifying the date to stop filtering disbursement transactions by the createdAt field - Enable Time Filter: This param allows caller to filter based on time (hour only) given in startDate and endDate query params. - Page Number: The current page from the total to be retrieved - Page Size: The number of entries/records to be returned in a single page A JSON response containing the statement would then be returned. #### API Endpoint: #### Sample Request #### Response Structure --- ## [Webhooks](https://developers.monnify.com/docs/webhooks) > Webhooks is an API concept that enables applications to automatically communicate with each other without constant polling. Monnify integration sends notifications to a URL on the merchants’ server when specific events such as when payments are being received or when settlements are made to your account, allowing further actions such as sending an email or providing value to the user. alt="" classes="my-3 h-auto scale-100 ease-in duration-500 w-full" /> Monnify supports webhooks for various events like card transactions, settlement and disbursement completion, and refunds. To implement webhooks on your Monnify integration, it is recommended to follow certain best practices such as validating transaction hash, whitelisting Monnify's IP address, checking for duplicate notifications, and processing complex logic after acknowledging receipt of the notification with a 200 HTTP status code. These practices ensure the integrity and security of the payload, prevent unauthorized requests, avoid redundant processing, and prevent time-out issues. ### Monnify Webhook Events and Structure As part of the Monnify integration, notifications are automatically sent to your system when certain actions are completed. These notifications trigger corresponding activities on your system, and you can specify URLs for certain activities on your integration. The notifications include an event-type property that indicates what action has taken place, as well as event data containing details of the event. Supported notification event types on Monnify include: - Successful Collection (for successful payments made on your account). - Successful Disbursement (for disbursement transactions with a successful definite status). - Failed Disbursement (for failed disbursement transactions). - Reversed Disbursement (for reversed disbursement transactions). - Successful Refund (for successfully processed initiated refunds). - Failed Refund (for failed initiated refunds). - Settlement Completion (for successfully processed settlements to your bank account or wallet). - Completed Offline Payments (for completed offline payment transactions). - Rejected Payments (for payments that were rejected or failed). - Mandate Status Change (This is sent when the status of a mandate changes from PENDING to FAILED or CANCELLED or ACTIVATED etc). - Wallet activity notification (For notifying merchants of credits and debits to their Main or SubWallets). - Low Balance Alert (for notifying merchants when their account balance is low). ### Structure and Sample A typical event notification structure is of the format: ### Transaction Hash Computation As a security measure, Monnify computes a hash of the request body whenever it sends a notification and includes it in the request header with the key 'monnify-signature'. To ensure the notification is valid and authorized, you should also calculate the hash and compare it to the one sent by Monnify before accepting or acting on the notification. To calculate the hash, you can use a SHA-512 encoding of your client secret key and the object of the request body. The formula is: SHA-512(client secret key + object of request body). ### Sample Examples: Sample Client Key: 91MUDL9N6U3BQRXBQ2PJ9M0PW4J22M1Y Sample Request: Hashed Value: f04fb635e04d71648bd3cc7999003da6861483342c856d05ddfa9b2dafacb87 3b0de1d0f8f67405d0010b4348b721c49fa171d317972618debba6b638aedcd3c ### Computing Hash in Nodejs ### Computing Hash in Java ### Best Practices It’s highly recommended you do the following when processing webhook notifications from us. - **Transaction Hash Validation:** This is applicable by default on our transaction notification webhook. A hash of some properties in the request payload is computed, and you can validate this on your server by computing the same hash and comparing outputs. - **Whitelist Monnify's webhook IP address:** To prevent requests from un-authorized origins, you can whitelist our IP address and only honor requests from this IP. Webhook notifications from Monnify will come from the following IP addresses - **35.242.133.146**. - **Check for duplicate notifications:** It’s important to keep track of all notifications you’ve received. When a new notification is received, always check that this has not been processed before giving value so as not to give double value to customers. A resend of already processed notification can happen if we do not get a 200 HTTP Status code, or in the case of a request time out. - **Process Complex Logic After Responding to Monnify:** If your application will perform complex or time consuming logic with received notifications, this might lead to a time out between Monnify and your system, hence leading to a resend. For this reason, it’s recommended you immediately acknowledge receipt of the notification by returning a 200 HTTP Status code, and then perform your long processing activities. --- ## [Monnify API Reference](https://developers.monnify.com/api) > Complete Monnify REST API reference with interactive testing. Covers all endpoints for collections, disbursements, wallets, customer verification, webhooks, and BVN/NIN integration. --- ## [Error Codes](https://developers.monnify.com/docs/error-codes) > A reference list of Monnify API error codes, their meanings, and recommended resolutions to help developers quickly diagnose and fix integration issues. --- ## [Supported Banks](https://developers.monnify.com/docs/supported-banks) > A complete list of Nigerian banks supported by Monnify for collections, transfers, and account verification, including bank names and their bank codes. --- ## [Webhook Event Types](https://developers.monnify.com/docs/webhooks/event-types) > Reference for all Monnify webhook event types including successful transactions, settlement notifications, disbursement completions, and refund events. Covers payload structure and best practices for validating webhook notifications. --- ## [Testing Pay with Transfer on Monnify Sandbox](https://developers.monnify.com/blog/testing-pay-with-transfer-on-monnify-sandbox) > Learn how to test Pay with Transfer on Monnify's sandbox — whether you're using the One-Time Payment SDK, the Initialize Transaction API, or a custom account display — using the Monnify Bank Simulator. --- ## [Monnify Disbursement Changes: Account Name Now Mandatory](https://developers.monnify.com/blog/changes-to-monnify-disbursement) > Monnify now requires the destinationAccountName field in all single transfer requests. Learn what changed, why it matters, and exactly how to update your integration. --- ## [Implementing Card Payments with Monnify — A Practical Guide](https://developers.monnify.com/blog/implementing-card-payments-with-monnify) > A practical guide covering both approaches to card payments on Monnify: the hosted Checkout SDK and direct card charge with OTP / 3DS flows. --- ## [Building a Wallet Service with Monnify](https://developers.monnify.com/blog/building-a-wallet-service-with-monnify) > This article guides on how to leverage Monnify's Reserved Account and Disbursement APIs to build a complete wallet service with deposit and withdrawal flows. --- ## [Monnify Payment Gateway for Zoho Books](https://developers.monnify.com/blog/integrating-monnify-into-zoho-books) > A comprehensive guide on integrating Monnify with Zoho Books for seamless payment processing — accept bank transfers, cards, or USSD directly in your invoices. --- ## [Using The Monnify Nodejs Lib For Reserved Account Management](https://developers.monnify.com/blog/implementing-monnify-reserve-Account-in-nodejs) > This article guides on how to leverage Monnify's Nodejs library to interact with the Monnify Reserved Account API — covering account creation, retrieval, and deallocation. --- ## [Integrating One-time Payment Checkout into Your Web Project](https://developers.monnify.com/blog/integrating-monnify-checkout-into-your-project) > A comprehensive guide on integrating Monnify's one-time payment checkout into web projects using the Monnify JavaScript SDK, with a practical e-commerce example. --- # About Monnify Monnify (by Moniepoint) is a leading Nigerian payment infrastructure provider. Businesses integrate Monnify to accept payments via bank transfer, card, USSD, and phone-number-based payments, as well as to disburse funds to any Nigerian bank account. Monnify is regulated by the Central Bank of Nigeria (CBN). - Website: https://monnify.com - Developer Portal: https://developers.monnify.com - API Reference: https://developers.monnify.com/api - Support: integration-support@monnify.com