> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dubupay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Withdrawals & Offramps API — send funds out

> Send USDT to external crypto wallets and convert USDT to NGN via offramps with direct bank payouts. Manage recipients for recurring offramps.

Dubu Pay gives you two ways to move funds out of your merchant account. **Withdrawals** send USDT directly to an external blockchain wallet address. **Offramps** convert USDT to NGN and route the proceeds to a Nigerian bank account — either on-the-spot or on a recurring basis for a specific customer. For both, the operation originates from your merchant USDT balance.

## Authentication

All endpoints require either a Bearer token or an API key.

```
Authorization: Bearer <access_token>
```

```
X-Api-Key: dubu_sk_live_...
```

***

## Withdrawals

### Create a withdrawal

`POST https://api.dubupay.com/api/v1/payments/withdrawals`

Initiates a USDT withdrawal from your merchant balance to an external wallet address on the specified blockchain network.

<Note>
  This endpoint supports idempotency. Pass an `X-Idempotency-Key` header to safely retry without creating duplicate withdrawals.
</Note>

#### Request body

<ParamField body="amount_usd" type="string" required>
  The USD-equivalent amount to withdraw, expressed as a decimal string (e.g., `"100.00"`).
</ParamField>

<ParamField body="token" type="string" required>
  The token to withdraw. Use `USDT`.
</ParamField>

<ParamField body="chain" type="string" required>
  The blockchain network to send on. Supported values: `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, `TRON`.
</ParamField>

<ParamField body="destination_address" type="string" required>
  The recipient wallet address on the specified chain.
</ParamField>

#### Response

<ResponseField name="data" type="object">
  The created withdrawal.

  <Expandable title="data fields">
    <ResponseField name="id" type="string">
      Unique withdrawal ID.
    </ResponseField>

    <ResponseField name="amount_usd" type="string">
      Withdrawal amount in USD.
    </ResponseField>

    <ResponseField name="token" type="string">
      Token being withdrawn (e.g., `USDT`).
    </ResponseField>

    <ResponseField name="chain" type="string">
      Target blockchain network.
    </ResponseField>

    <ResponseField name="destination_address" type="string">
      Recipient wallet address.
    </ResponseField>

    <ResponseField name="status" type="string">
      Withdrawal status: `PROCESSING`, `SETTLED`, or `FAILED`.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 creation timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Example

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/withdrawals \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "X-Idempotency-Key: withdrawal-20240101-001" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_usd": "250.00",
    "token": "USDT",
    "chain": "TRON",
    "destination_address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
  }'
```

***

### List withdrawals

`GET https://api.dubupay.com/api/v1/payments/withdrawals`

Returns a paginated list of withdrawals.

#### Query parameters

<ParamField query="page" type="number">
  Page number (1-indexed).
</ParamField>

<ParamField query="limit" type="number">
  Results per page. Up to 100.
</ParamField>

<ParamField query="status" type="string">
  Filter by status. One of `PROCESSING`, `SETTLED`, `FAILED`.
</ParamField>

#### Example

```bash theme={null}
curl "https://api.dubupay.com/api/v1/payments/withdrawals?status=SETTLED&limit=20" \
  -H "X-Api-Key: dubu_sk_live_..."
```

***

### Get a withdrawal

`GET https://api.dubupay.com/api/v1/payments/withdrawals/:id`

Retrieves a single withdrawal by ID.

#### Path parameters

<ParamField path="id" type="string" required>
  The withdrawal ID.
</ParamField>

#### Example

```bash theme={null}
curl "https://api.dubupay.com/api/v1/payments/withdrawals/wdr_01HXYZ" \
  -H "X-Api-Key: dubu_sk_live_..."
```

***

## Offramps

Offramps convert USDT (or USDC) received from a blockchain address into NGN and pay it out to a bank account. You can create offramps as TEMPORARY (one-time, for a specific conversion) or PERMANENT (reusable for a customer's ongoing payouts).

For NGN bank payouts, you must supply a `rate_id` (lock a rate from the [Rates endpoint](/api-reference/payments/rates)) and destination bank details.

### Create an offramp

`POST https://api.dubupay.com/api/v1/payments/offramps`

Creates a new offramp. The body shape varies depending on whether you settle to your internal balance or to an NGN bank account.

<Note>
  This endpoint supports idempotency via the `X-Idempotency-Key` header.
</Note>

#### Request body

<ParamField body="type" type="string" required>
  Offramp type. One of `TEMPORARY` or `PERMANENT`.
</ParamField>

<ParamField body="customer" type="object" required>
  The customer for this offramp. Provide either `customer_id` or `email` (with optional name fields).

  <Expandable title="customer fields">
    <ParamField body="customer_id" type="string">
      UUID of an existing customer. Mutually exclusive with `email`.
    </ParamField>

    <ParamField body="email" type="string">
      Email address. Used to look up or create a customer record.
    </ParamField>

    <ParamField body="first_name" type="string">
      Customer first name (used when creating a new customer by email).
    </ParamField>

    <ParamField body="last_name" type="string">
      Customer last name (used when creating a new customer by email).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="chain" type="string" required>
  The blockchain network the offramp listens on. One of `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, `TRON`.
</ParamField>

<ParamField body="asset" type="string" required>
  The crypto asset to accept. One of `USDC` or `USDT`.
</ParamField>

<ParamField body="settlement" type="object" required>
  How proceeds are settled after conversion.

  <Expandable title="settlement fields">
    <ParamField body="mode" type="string" required>
      Settlement mode. One of `INTERNAL_BALANCE` (credit your merchant balance in NGN) or `NGN_PAYOUT` (send NGN directly to a bank account).
    </ParamField>

    <ParamField body="rate_id" type="string">
      Required when `mode` is `NGN_PAYOUT`. A rate ID obtained from `GET /payments/rates`.
    </ParamField>

    <ParamField body="destination_bank" type="object">
      Required when `mode` is `NGN_PAYOUT`.

      <Expandable title="destination_bank fields">
        <ParamField body="account_name" type="string" required>
          Account holder name as registered with the bank.
        </ParamField>

        <ParamField body="account_number" type="string" required>
          Bank account number (6–32 characters).
        </ParamField>

        <ParamField body="bank_code" type="string" required>
          Bank sort code (3–16 characters).
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

#### Example — settle to internal balance

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/offramps \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "X-Idempotency-Key: offramp-ada-001" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "PERMANENT",
    "customer": {
      "customer_id": "b2c3d4e5-f6a7-8901-bcde-f01234567890"
    },
    "chain": "TRON",
    "asset": "USDT",
    "settlement": {
      "mode": "INTERNAL_BALANCE"
    }
  }'
```

#### Example — NGN payout to bank account

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/offramps \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "X-Idempotency-Key: offramp-payout-001" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "TEMPORARY",
    "customer": {
      "email": "ada.obi@example.com"
    },
    "chain": "SOLANA",
    "asset": "USDC",
    "settlement": {
      "mode": "NGN_PAYOUT",
      "rate_id": "rate_abc123",
      "destination_bank": {
        "account_name": "Ada Obi",
        "account_number": "0123456789",
        "bank_code": "058"
      }
    }
  }'
```

***

### List offramps

`GET https://api.dubupay.com/api/v1/payments/offramps`

Returns a paginated list of offramps with optional filters.

#### Query parameters

<ParamField query="type" type="string">
  Filter by type: `TEMPORARY` or `PERMANENT`.
</ParamField>

<ParamField query="chain" type="string">
  Filter by chain: `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, or `TRON`.
</ParamField>

<ParamField query="asset" type="string">
  Filter by asset: `USDC` or `USDT`.
</ParamField>

<ParamField query="status" type="string">
  Filter by status: `ACTIVE`, `INACTIVE`, or `EXPIRED`.
</ParamField>

<ParamField query="settlement_mode" type="string">
  Filter by settlement mode: `INTERNAL_BALANCE` or `NGN_PAYOUT`.
</ParamField>

<ParamField query="page" type="number">
  Page number (1-indexed).
</ParamField>

<ParamField query="limit" type="number">
  Results per page. Up to 200.
</ParamField>

#### Example

```bash theme={null}
curl "https://api.dubupay.com/api/v1/payments/offramps?status=ACTIVE&chain=TRON" \
  -H "X-Api-Key: dubu_sk_live_..."
```

***

### Get an offramp

`GET https://api.dubupay.com/api/v1/payments/offramps/:id`

Retrieves a single offramp by ID.

#### Path parameters

<ParamField path="id" type="string" required>
  The offramp ID.
</ParamField>

#### Example

```bash theme={null}
curl "https://api.dubupay.com/api/v1/payments/offramps/off_01HXYZ" \
  -H "X-Api-Key: dubu_sk_live_..."
```

***

## Recipients

A recipient is a saved payment destination — a bank account, crypto address, or wire details — that you can reference by ID when creating transfers or offramps. Managing recipients separately lets you avoid re-entering bank details on every payout.

### Create a recipient

`POST https://api.dubupay.com/api/v1/recipients`

#### Request body

<ParamField body="type" type="string" required>
  Recipient type. One of `BANK_ACCOUNT`, `CRYPTO_ADDRESS`, `US_BANK_ACCOUNT`, `SWIFT_BANK_ACCOUNT`.
</ParamField>

<ParamField body="customer_id" type="string">
  UUID of an existing customer to associate with this recipient. Required for `US_BANK_ACCOUNT` and `SWIFT_BANK_ACCOUNT` types.
</ParamField>

<ParamField body="bank_account" type="object">
  Required when `type` is `BANK_ACCOUNT`.

  <Expandable title="bank_account fields">
    <ParamField body="account_number" type="string" required>
      Nigerian bank account number.
    </ParamField>

    <ParamField body="bank_code" type="string" required>
      Bank sort code.
    </ParamField>

    <ParamField body="account_name" type="string">
      Account holder name.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="crypto_address" type="object">
  Required when `type` is `CRYPTO_ADDRESS`.

  <Expandable title="crypto_address fields">
    <ParamField body="asset" type="string" required>
      Asset. One of `USDC` or `USDT`.
    </ParamField>

    <ParamField body="chain" type="string" required>
      Chain. One of `ETHEREUM`, `BASE`, `POLYGON`, `ARBITRUM`, `OPTIMISM`, `CELO`.
    </ParamField>

    <ParamField body="address" type="string" required>
      Wallet address.
    </ParamField>
  </Expandable>
</ParamField>

#### Example

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/recipients \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "BANK_ACCOUNT",
    "bank_account": {
      "account_number": "0123456789",
      "bank_code": "058",
      "account_name": "Ada Obi"
    }
  }'
```
