This end point initiates the withdrawal of an authenticated account.
Use the Quidax API to send Nigerian Naira (NGN) from a Quidax wallet to a Nigerian bank account.
An NGN withdrawal involves four steps:
- Retrieve supported banks.
- Resolve the recipient's bank account.
- Create the bank withdrawal.
- Listen for the
withdraw.successfulwebhook.
Before you begin
Authenticate your API requests using your Quidax secret key.
Authorization: Bearer <secret_key>
Keep your secret key on your server. Don't expose it in client-side applications.
1. Retrieve supported banks
Retrieve the list of banks that can receive NGN withdrawals.
curl --request GET \
--url https://openapi.quidax.io/exchange-open-api/api/v1/banks \
--header 'Authorization: Bearer <secret_key>' \
--header 'Accept: application/json'
Response
The response contains the bank name, bank code, country, and supported currency.
The complete response can contain many banks. The example below shows one bank from the response.
{
"status": "success",
"message": "Successful",
"data": [
{
"code": "0000",
"name": "Test (Test bank)",
"country": "Nigeria",
"currency": "NGN"
}
]
}
Use the selected bank's code when resolving the account and creating the withdrawal.
For example, the bank code for Paycom (Opay) is:
100004
API reference: https://docs.quidax.io/reference/list-banks
2. Resolve the bank account
Before creating a withdrawal, resolve the recipient's account number.
This lets you retrieve the account name associated with the bank account so that the customer can confirm the recipient before sending funds.
Pass the account number as fund_uid, the bank code as fund_uid2, and ngn as the currency.
curl --request POST \
--url https://openapi.quidax.io/exchange-open-api/api/v1/banks/verify_account \
--header 'Authorization: Bearer <secret_key>' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"fund_uid": "0123456789",
"fund_uid2": "0000",
"currency": "ngn"
}'
Parameters
| Parameter | Description |
|---|---|
fund_uid | The recipient's bank account number. |
fund_uid2 | The bank code returned by the banks endpoint. |
currency | The withdrawal currency. Set this to ngn. |
Response
A successful request returns the name associated with the bank account.
{
"status": "success",
"message": "Successful",
"data": {
"account_name": "TEST USER"
}
}
Display account_name to the customer and ask them to confirm that the recipient is correct before creating the withdrawal.
Resolving an account only verifies the recipient's bank details. It doesn't create a withdrawal or move funds.
API reference: https://docs.quidax.io/reference/verify-bank-account
3. Create the bank withdrawal
After the customer confirms the resolved account details, create the NGN withdrawal.
Use the same account number and bank code from the previous step.
curl --request POST \
--url https://openapi.quidax.io/exchange-open-api/api/v1/users/me/withdraws \
--header 'Authorization: Bearer <secret_key>' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"currency": "ngn",
"amount": "1000",
"fund_uid": "0123456789",
"fund_uid2": "0000",
"transaction_note": "NGN withdrawal",
"narration": "Payout",
"reference": "withdrawal_123456"
}'
Parameters
| Parameter | Description |
|---|---|
currency | The currency to withdraw. Set this to ngn. |
amount | The amount of NGN to withdraw. |
fund_uid | The recipient's bank account number. |
fund_uid2 | The recipient's bank code. |
transaction_note | A note associated with the transaction. |
narration | The narration associated with the payout. |
reference | A unique reference generated by your application. |
Use me to withdraw from your main Quidax account.
To withdraw from a sub-account, replace me with the sub-account's user_id.
Generate a unique reference for each withdrawal. Store the reference in your application so that you can reconcile the withdrawal with webhook events.
Verify the recipient's bank details before creating the withdrawal. A withdrawal sent to incorrect bank details might not be recoverable.
Response
A successful request creates the withdrawal.
{
"status": "success",
"message": "Successful",
"data": {
"id": "FW-60baecb6a6374cbf89e8b0d3da11b8f6",
"reference": "withdrawal_123456",
"type": "bank_account",
"currency": "ngn",
"amount": "1000.0",
"fee": "200.0",
"stamp_duty_fee": "0.0",
"total": "1200.0",
"txid": "withdrawal_123456",
"transaction_note": "NGN withdrawal",
"narration": "Payout",
"status": "Done",
"reason": null,
"created_at": "2026-08-14T10:04:45Z",
"done_at": "2026-08-14T10:04:45Z",
"recipient": {
"type": "bank_account",
"details": {
"bank_code": "0000"
}
},
"wallet": {
"id": "c1e3356a606e46278360dd6f01d41b951777967506624",
"name": "NGN",
"currency": "ngn",
"balance": "1583.0045457533",
"locked": "0.0",
"staked": "0.0",
"user": {
"id": "23azi7bj",
"sn": "Qtestaccount",
"email": "[email protected]",
"reference": null,
"first_name": "Test",
"last_name": "User",
"display_name": "example",
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-10T21:05:30.000Z"
},
"converted_balance": "0.0",
"reference_currency": "ngn",
"is_crypto": false,
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-14T10:04:46.000Z",
"blockchain_enabled": false,
"default_network": null,
"networks": [],
"deposit_address": null,
"destination_tag": null
},
"user": {
"id": "23azi7bj",
"sn": "Qtestaccount",
"email": "[email protected]",
"reference": null,
"first_name": "Test",
"last_name": "User",
"display_name": "example",
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-10T21:05:30.000Z"
}
}
}
Creating the withdrawal doesn't mean that you should immediately mark the payout as successful.
The withdrawal is processed asynchronously. Use webhooks to determine when Quidax has successfully processed it.
Store at least these fields with your internal withdrawal record:
data.id
data.reference
data.amount
data.currency
API reference: https://docs.quidax.io/reference/create-bank-withdrawal
4. Listen for the withdrawal webhook
Use webhooks to receive updates about the withdrawal.
When Quidax successfully processes a fiat withdrawal, your webhook endpoint receives a withdraw.successful event.
Event
withdraw.successful
Webhook payload
The following example shows the complete payload for an NGN bank withdrawal.
{
"event": "withdraw.successful",
"data": {
"id": "FW-91c854af0cac4825a979eaaa0c2d7388",
"reference": "fbbfbbfbfbbfbff",
"type": "bank_account",
"currency": "ngn",
"amount": "1000.0",
"fee": "200.0",
"stamp_duty_fee": "0.0",
"total": "1200.0",
"txid": "fbbfbbfbfbbfbff",
"transaction_note": null,
"narration": "Payout",
"status": "Processing",
"reason": null,
"created_at": "2026-08-14T10:04:45Z",
"done_at": "2026-08-14T10:04:45Z",
"recipient": {
"type": "bank_account",
"details": {
"bank_code": "0000"
}
},
"wallet": {
"id": "c1e3356a606e46278360dd6f01d41b951777967506624",
"name": "NGN",
"currency": "ngn",
"balance": "1583.0045457533",
"locked": "0.0",
"staked": "0.0",
"user": {
"id": "23azi7bj",
"sn": "Qtestaccount",
"email": "[email protected]",
"reference": null,
"first_name": "Test",
"last_name": "Uset",
"display_name": "testaccount",
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-10T21:05:30.000Z"
},
"converted_balance": "0.0",
"reference_currency": "ngn",
"is_crypto": false,
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-14T10:04:46.000Z",
"blockchain_enabled": false,
"default_network": null,
"networks": [],
"deposit_address": null,
"destination_tag": null
},
"user": {
"id": "23azi7bj",
"sn": "Qtestaccount",
"email": "[email protected]",
"reference": null,
"first_name": "Test",
"last_name": "Uset",
"display_name": "example",
"created_at": "2021-04-09T09:48:14.000Z",
"updated_at": "2026-08-10T21:05:30.000Z"
}
}
}
Handle the event
Use data.id or data.reference to find the corresponding withdrawal in your application.
When you receive the event:
1. Check that event is withdraw.successful.
2. Find the withdrawal using data.id or data.reference.
3. Check whether you've already processed the event.
4. Mark the withdrawal as successful.
5. Return HTTP 200.
Your webhook endpoint should be idempotent. Processing the same event more than once shouldn't result in duplicate updates or side effects.
Use the event type as the success signal
For fiat withdrawals, a
withdraw.successfulwebhook can contain"status": "Processing".Don't require
data.statusto equalDonebefore marking the withdrawal as successful. Thewithdraw.successfulevent indicates that Quidax has successfully processed the withdrawal.
For example:
if (payload.event === "withdraw.successful") {
const withdrawal = payload.data;
// Find the withdrawal using withdrawal.id
// or withdrawal.reference.
// Mark the withdrawal as successful.
}
Webhook reference: <https://docs.quidax.io/docs/withdraw-successful>
Complete integration flow
Customer chooses a bank
↓
GET /banks
↓
Store the selected bank code
↓
Customer enters account number
↓
POST /banks/verify_account
↓
Display resolved account name
↓
Customer confirms recipient
↓
POST /users/{user_id}/withdraws
↓
Store withdrawal ID and reference
↓
Wait for webhook
↓
withdraw.successful
↓
Mark withdrawal as successful
Summary
1. Retrieve the bank
GET /banks
Use the returned bank code, for example 100004 for Paycom (Opay).
2. Resolve the recipient
POST /banks/verify_account
Pass the account number as fund_uid and the bank code as fund_uid2. Use the returned account_name to let the customer confirm the recipient.
3. Create the withdrawal
POST /users/{user_id}/withdraws
Pass the same account number and bank code along with the withdrawal amount and a unique reference.
4. Wait for the webhook
withdraw.successful
Treat the withdraw.successful event as confirmation that the fiat withdrawal has been successfully processed.

