Create Bank Withdraw

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:

  1. Retrieve supported banks.
  2. Resolve the recipient's bank account.
  3. Create the bank withdrawal.
  4. Listen for the withdraw.successful webhook.

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

ParameterDescription
fund_uidThe recipient's bank account number.
fund_uid2The bank code returned by the banks endpoint.
currencyThe 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

ParameterDescription
currencyThe currency to withdraw. Set this to ngn.
amountThe amount of NGN to withdraw.
fund_uidThe recipient's bank account number.
fund_uid2The recipient's bank code.
transaction_noteA note associated with the transaction.
narrationThe narration associated with the payout.
referenceA 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.successful webhook can contain "status": "Processing".

Don't require data.status to equal Done before marking the withdrawal as successful. The withdraw.successful event 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.