Money Transfer
Send money from your Paga business balance to more than 570 banks and financial institutions in Nigeria, or to a Paga wallet, with the same API call.
| Environment | Base URL |
|---|---|
| Sandbox | https://beta.mypaga.com |
| Live | https://www.mypaga.com |
Money transfer uses the Business API: send your keys as principal and credentials headers with a request hash, as in Authentication, from a whitelisted IP address. Payouts come from your Paga business balance, so keep it funded.
How it works
Get the bank’s UUID
Call getBanks and find your recipient’s bank. To pay a Paga wallet, use Paga’s own UUID.
Validate the account
validateDepositToBank confirms the account exists and returns the account holder’s name and the fee.
Send the money
depositToBank pays the account from your business balance. Include your statusCallbackUrl.
Get notified
Paga notifies your statusCallbackUrl once the transfer is processed. If it doesn’t arrive, check the transaction status.
1. Get the bank’s UUID
Call getBanks to list every supported institution with its UUID. UUIDs never change, but new institutions are added every month. Cache the list and refresh it weekly or monthly, rather than hard-coding it or calling it before every payout.
POST /paga-webservices/business-rest/secured/getBanks
principal: YOUR_PUBLIC_KEY
credentials: YOUR_SECRET_KEY
hash: sha512(referenceNumber + hashKey)
Content-Type: application/json{
"referenceNumber": "BNK-2026-1103"
}{
"referenceNumber": "BNK-2026-1103",
"responseCode": 0,
"banks": [
{
"uuid": "40090E2F-7446-4217-9345-7BBAB7043C4C",
"name": "Access Bank",
"interInstitutionCode": "000014",
"sortCode": "044"
},
{
"uuid": "8B9CCA8B-F092-4704-82FD-B82D2B9A1993",
"name": "First Bank",
"interInstitutionCode": "000016",
"sortCode": "011"
},
{
"uuid": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA",
"name": "Paga",
"interInstitutionCode": null,
"sortCode": "327"
}
]
}Response fields (5)
| Field | Meaning |
|---|---|
referenceNumber | Your reference from the request |
banks[].uuid | The value you need. Send it as destinationBankUUID. A bank’s UUID never changes |
banks[].name | The institution’s name, to show in your bank picker |
banks[].interInstitutionCode | The NIBSS institution code. Can be null |
banks[].sortCode | The CBN sort code |
Paying a Paga wallet? Use Paga’s bank UUID, AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA, the same in Sandbox and Live, with the recipient’s Paga account number.
2. Validate the account
Check the account before you send. You get the name registered at the bank and the fee, so you can show the sender who they’re paying and what it costs.
POST /paga-webservices/business-rest/secured/validateDepositToBank
principal: YOUR_PUBLIC_KEY
credentials: YOUR_SECRET_KEY
hash: sha512(referenceNumber + amount + destinationBankUUID + destinationBankAccountNumber + hashKey)
Content-Type: application/json{
"referenceNumber": "VAL-2026-0311",
"amount": "5000.00",
"currency": "NGN",
"destinationBankUUID": "40090E2F-7446-4217-9345-7BBAB7043C4C",
"destinationBankAccountNumber": "0000000000"
}{
"referenceNumber": "VAL-2026-0311",
"responseCode": 0,
"destinationAccountHolderNameAtBank": "Test Customer",
"fee": 50,
"vat": 2.5,
"message": null
}Validate fields (4)
| Field | Meaning |
|---|---|
destinationAccountHolderNameAtBank | The account holder’s name, as the bank has it. Show it to the sender to confirm |
fee | What the transfer will cost, taken from your business balance |
vat | VAT on the fee |
responseCode | 0 means the account is valid. For any other code, see Business API error codes |
3. Send the money
POST /paga-webservices/business-rest/secured/depositToBank
principal: YOUR_PUBLIC_KEY
credentials: YOUR_SECRET_KEY
hash: sha512(referenceNumber + amount + destinationBankUUID + destinationBankAccountNumber + hashKey)
Content-Type: application/jsonThe hash is the same as for validation. Use a new referenceNumber for the transfer, up to 50 characters. The examples show the essentials; every optional parameter is in the table below.
{
"referenceNumber": "PAY-2026-0311",
"amount": "5000.00",
"currency": "NGN",
"destinationBankUUID": "40090E2F-7446-4217-9345-7BBAB7043C4C",
"destinationBankAccountNumber": "0000000000",
"remarks": "Salary for June",
"statusCallbackUrl": "https://yourstore.com/webhooks/paga-payouts"
}Same call, with Paga’s UUID and the recipient’s Paga account number.
{
"referenceNumber": "PAY-2026-0311",
"amount": "5000.00",
"currency": "NGN",
"destinationBankUUID": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA",
"destinationBankAccountNumber": "3080242757",
"remarks": "Salary for June",
"statusCallbackUrl": "https://yourstore.com/webhooks/paga-payouts"
}Request parameters (16)
| Parameter | Required | Description |
|---|---|---|
referenceNumber | Yes | Your unique reference, up to 50 characters. Hash value 1 |
amount | Yes | Amount to send. Hash value 2 |
destinationBankUUID | Yes | The bank’s UUID from getBanks, or Paga’s UUID for a wallet. Hash value 3 |
destinationBankAccountNumber | Yes | The 10-digit account number. Hash value 4 |
currency | No | NGN |
statusCallbackUrl | No | Where Paga notifies you once the transfer is processed. Strongly recommended |
recipientName | No | Recipient’s full name |
recipientPhoneNumber | No | Recipient’s phone number, for the SMS notification |
recipientMobileOperatorCode | No | The recipient’s network, for reliable SMS delivery |
recipientEmail | No | Recipient’s email address |
remarks | No | A note on the transfer, such as Salary for June |
transferReference | No | A second reference of your own, for reconciliation |
suppressRecipientMessage | No | true stops Paga texting the recipient. Default false |
alternateSenderName | No | The sender name shown to the recipient, up to 16 characters |
miniRecipentKYCLevel | No | For Paga wallets: the lowest KYC level the recipient needs (KYC1, KYC2 or KYC3) |
holdingPeriod | No | Days the recipient has to reach that KYC level before the money returns to you. Default 120. Only with miniRecipentKYCLevel |
International money transfer operators (IMTOs)
If you’re an IMTO, these fields are required on every transfer:
| Parameter | Description |
|---|---|
senderFormalName | Sender’s full name |
senderGender | MALE or FEMALE |
senderOccupation | FORMAL or INFORMAL |
senderAge | Sender’s age |
senderAddress | Sender’s address |
recipientAddress | Recipient’s address |
sourceCurrency | The currency sent, such as USD or GBP |
sourceAmount | The amount before conversion |
effectiveExchangeRate | The rate from sourceCurrency to currency |
{
"referenceNumber": "PAY-2026-0311",
"responseCode": 0,
"message": "Successfully deposited N5,000.00 to bank account ******8830. Transaction Id: RP658.",
"transactionId": "RP658",
"destinationAccountHolderNameAtBank": "Test Customer",
"fee": 50,
"vat": 2.5,
"currency": "NGN",
"exchangeRate": null,
"sessionId": null
}Response fields (10)
| Field | Meaning |
|---|---|
responseCode | 0 means Paga accepted the transfer. Other codes can mean pending, duplicate reference or failed, so look each one up in Business API error codes before retrying |
referenceNumber | Your reference |
transactionId | Paga’s short ID for the transfer. Share it with the recipient if they ask |
message | Readable result |
destinationAccountHolderNameAtBank | The recipient’s name at the bank |
fee | Fee taken from your balance |
vat | VAT on the fee |
currency | NGN |
exchangeRate | Only for foreign-currency transfers |
sessionId | The bank transfer’s session ID, for tracing it with the recipient’s bank |
4. Handle the notification
Paga sends a notification to your statusCallbackUrl once the transfer is processed. Verify the hash, decide on responseCode, then respond with HTTP 200 and {"status": "SUCCESS"}.
x-paga-request-id: bfb63229-c212-4b89-8a38-fffb87447bc0
x-paga-attempt-id: 204a702d-0f59-48f1-8467-2140055f0eef
x-paga-hash-parameters: referenceNumber,transactionDate,transactionId,amount,sessionId,hashKey
x-paga-hash: 074ff3f2dfb8488d9660104f58990be919c648f64f186f06d9e6b0702a25d623e74d15df22a567bd9f633ed0aa62a1b19e983aa2ef087108ae78252a1f49f686{
"responseCode": 0,
"message": "Successfully deposited N5,000.00 to bank account ******8830. Transaction Id: RP658.",
"referenceNumber": "PAY-2026-0311",
"transactionId": "RP658",
"transactionReference": "SCBS-U_20261103110225559_989465645_RP658_bfrgw",
"transactionType": "USER_SEND_CASH_TO_BANK_ACCOUNT_SETTLED",
"transactionDate": "2026-11-03 11:02:25.56",
"amount": "5000.0",
"currency": "NGN",
"fee": 53.75,
"vat": 3.75,
"taxes": { "vat": 3.75 },
"sessionId": "100002261103110226001406467019",
"destinationAccountHolderNameAtBank": "Test Customer",
"reversalId": null,
"exchangeRate": null,
"integrationStatus": null,
"responseCategoryCode": null
}Notification fields (17)
| Field | Meaning |
|---|---|
responseCode | The field to decide on. 0 means success. Other codes can mean the transfer is pending, the reference was a duplicate, it failed, or something else, so look each one up in Business API error codes before acting |
message | Readable result |
referenceNumber | Your reference from the request |
transactionId | Paga’s short ID for the transfer |
transactionReference | Paga’s full reference for the transfer |
transactionType | The kind of transaction, such as USER_SEND_CASH_TO_BANK_ACCOUNT_SETTLED |
transactionDate | When the transfer was made |
amount | Amount sent, as a string such as 5000.0 |
currency | NGN |
fee | Fee taken from your balance |
vat | VAT on the fee. Also in taxes.vat |
sessionId | The bank transfer’s session ID, for tracing it with the recipient’s bank |
destinationAccountHolderNameAtBank | The recipient’s name at the bank |
reversalId | Set if the money was returned to your balance |
exchangeRate | Only for foreign-currency transfers |
integrationStatus | Usually null |
responseCategoryCode | The HTTP status code, if there was a problem |
Don’t treat every non-zero code as a failureSome codes mean the transfer is still pending, or that the reference was already used. Look up each
responseCodein the Business API error codes before you refund a customer or send the money again.
Check the hash
Join referenceNumber + transactionDate + transactionId + amount + sessionId + hashKey, hash the result with SHA-512, and compare it with the x-paga-hash header.
The hash is sent in the x-paga-hash header, not the body. Build it from the fields named in x-paga-hash-parameters, in that order, using each value exactly as received. For the example above, the string to hash is PAY-2026-03112026-11-03 11:02:25.56RP6585000.0100002261103110226001406467019 followed by your hash key.
Retries. Until Paga gets HTTP 200 with {"status": "SUCCESS"} back, it sends the notification again, each time with a new x-paga-attempt-id. De-duplicate on referenceNumber, so a retried notification isn’t processed twice.
5. Check the transaction status
If a notification hasn’t arrived, or a request timed out, check the transfer’s status before doing anything else. transactionStatus covers operations from the last 48 hours; for older ones, use the transaction history below.
POST /paga-webservices/business-rest/secured/transactionStatus
principal: YOUR_PUBLIC_KEY
credentials: YOUR_SECRET_KEY
hash: sha512(referenceNumber + hashKey)
Content-Type: application/json{
"referenceNumber": "PAY-2026-0311",
"locale": "en"
}{
"responseCode": 0,
"message": null,
"referenceNumber": "PAY-2026-0311",
"status": "SUCCESSFUL",
"transactionId": "RP658",
"transactionReference": "SCBS-U_20261103110225559_989465645_RP658_bfrgw",
"transactionType": "USER_SEND_CASH_TO_BANK_ACCOUNT_SETTLED",
"dateUTC": 1793790145560,
"amount": 5000.0,
"currency": "NGN"
}Request parameters (2)
| Parameter | Required | Description |
|---|---|---|
referenceNumber | Yes | The referenceNumber you used for the transfer. Hash value 1 |
locale | No | Language for messages, such as en |
Response fields (12)
| Field | Meaning |
|---|---|
responseCode | The field to decide on. 0 means success. Other codes can mean pending, duplicate reference, failed and more, so look each one up in Business API error codes before acting |
status | A readable status, such as SUCCESSFUL. Values vary by transaction type, so don’t base decisions on it |
message | Why the transfer failed, if it did |
referenceNumber | Your reference |
transactionId | Paga’s short ID for the transfer |
transactionReference | Paga’s full reference for the transfer |
transactionType | The kind of transaction |
dateUTC | When it happened, in milliseconds since 1970 (UTC) |
amount | Amount sent |
currency | NGN |
merchantTransactionReference | Only for bill payments: the biller’s confirmation code or token |
additionalProperties | Only for bill payments: extra details from the biller |
Decide on responseCode, not status
statusvalues vary by transaction type, so they aren’t reliable for decisions. UseresponseCode, and look it up in the Business API error codes. Don’t treat every non-zero code as a failure: some mean the transfer is still pending or was already sent with that reference, and retrying could pay twice.
Check your balance before a large run. Purchases come from your Paga business account. Check its balance and transaction history on Your business account.
Good to know
Always validate first
A validation costs nothing. A payout to the wrong account is hard to recover.
One reference per transfer
Store each referenceNumber before sending. On a timeout, wait for the notification or check the transaction status instead of sending again.
Fees come from your balance
Make sure your available balance covers the amount plus fee and VAT, or the transfer fails.
Test in Sandbox
Use Access Bank and account 0000000000 from the Test data page.
Need help? We’re here 24/7
Talk to our support team any time, or ask questions in the developer community.
Updated 5 days ago

