> ## 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.

# Payments, deposits, and withdrawals in Dubu Pay

> An overview of the Dubu Pay payment flow — onramps, deposits, withdrawals, offramps, transfers, merchant balance, exchange rates, and sandbox testing.

The Dubu Pay payments system covers every step of moving money: receiving NGN from customers via virtual bank accounts, tracking each incoming deposit through its settlement lifecycle, withdrawing USDT to external wallets, converting USDT back to NGN via offramps, and moving funds between accounts with transfers. All payments functionality lives under the `/payments` path of the API.

## Payment flow overview

```mermaid theme={null}
flowchart TD
    A[Customer sends NGN] --> B[Onramp / Virtual Account]
    B --> C[Deposit created]
    C --> D{Settled?}
    D -->|Yes| E[Merchant Balance]
    E --> F[Withdrawal — USDT to wallet]
    E --> G[Offramp — convert back to NGN]
    E --> H[Transfer — send NGN or USD]
```

## Onramps

An **onramp** is the API term for a virtual bank account used to receive NGN. When a customer pays into an onramp, Dubu Pay automatically converts the NGN to USDT and records the result as a deposit. See [NGN virtual bank accounts](/concepts/virtual-accounts) for the full breakdown of temporary vs permanent accounts.

<CodeGroup>
  ```bash Create an onramp theme={null}
  curl -X POST https://api.dubupay.com/api/v1/payments/onramps \
    -H "X-Api-Key: dubu_sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "type": "TEMPORARY",
      "customer_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "rate_id": "rate_01HZ...",
      "amount": 50000,
      "settlement": {
        "mode": "INTERNAL_BALANCE",
        "asset": "USDT"
      }
    }'
  ```

  ```bash List onramps theme={null}
  curl "https://api.dubupay.com/api/v1/payments/onramps?status=active&limit=20" \
    -H "X-Api-Key: dubu_sk_live_..."
  ```
</CodeGroup>

## Deposits

A **deposit** is created automatically when a customer pays into a virtual account. You do not create deposits directly — you retrieve and monitor them. Each deposit has a `type` of either `NGN_DEPOSIT` or `CRYPTO_DEPOSIT`, and moves through a status lifecycle until it either settles or fails.

**Deposit status lifecycle:**

| Status      | Description                                                                 |
| ----------- | --------------------------------------------------------------------------- |
| `PENDING`   | Deposit received and queued for processing.                                 |
| `COMPLETED` | Deposit has settled successfully. USDT has been credited.                   |
| `FAILED`    | Processing failed. No funds were moved.                                     |
| `FLAGGED`   | Flagged for compliance review. Settlement is paused.                        |
| `REVERSED`  | A completed deposit has been reversed. Credited USDT has been debited back. |

<Note>
  Virtual account deposits expose fine-grained processing states (`PENDING_FX`, `PENDING_WITHDRAWAL`, `SETTLED`) on the deposit record itself. The `GET /payments/deposits` list endpoint uses the higher-level status values shown above. Use webhooks to receive real-time status transitions.
</Note>

<CodeGroup>
  ```bash List deposits theme={null}
  curl "https://api.dubupay.com/api/v1/payments/deposits?status=COMPLETED&type=NGN_DEPOSIT" \
    -H "X-Api-Key: dubu_sk_live_..."
  ```

  ```bash Get a deposit theme={null}
  curl "https://api.dubupay.com/api/v1/payments/deposits/{id}" \
    -H "X-Api-Key: dubu_sk_live_..."
  ```
</CodeGroup>

You can filter deposits by `type`, `onramp_id`, `offramp_id`, `status`, and date range (`from` / `to` as ISO 8601 timestamps).

## Withdrawals

A **withdrawal** moves USDT from your merchant balance to an external blockchain address. You specify the amount, token, chain, and destination address.

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

Supported chains for withdrawals: `APTOS`, `BASE`, `CELO`, `ETHEREUM`, `POLYGON`, `SOLANA`, `TRON`.

<Warning>
  Withdrawals are irreversible once submitted. Verify the destination address and chain before calling this endpoint. Dubu Pay cannot recover funds sent to the wrong address.
</Warning>

## Offramps

An **offramp** accepts USDT and converts it back to NGN, either crediting your internal balance or sending the NGN directly to a Nigerian bank account. You choose the settlement mode when creating the offramp.

| Settlement mode    | Description                                                                                              |
| ------------------ | -------------------------------------------------------------------------------------------------------- |
| `INTERNAL_BALANCE` | Converted NGN is held in your Dubu Pay account.                                                          |
| `NGN_PAYOUT`       | Converted NGN is sent to a specified Nigerian bank account. Requires a `rate_id` and `destination_bank`. |

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/offramps \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "TEMPORARY",
    "customer": { "customer_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" },
    "chain": "TRON",
    "asset": "USDT",
    "settlement": {
      "mode": "NGN_PAYOUT",
      "rate_id": "rate_01HZ...",
      "destination_bank": {
        "account_name": "Ada Lovelace",
        "account_number": "0123456789",
        "bank_code": "058"
      }
    }
  }'
```

Offramp `type` is either `TEMPORARY` (expires) or `PERMANENT` (no expiry). You can filter listed offramps by `type`, `chain`, `asset`, `status`, and `settlement_mode`.

## Transfers

A **transfer** moves funds to a bank account. Dubu Pay supports three destination types depending on the currency and recipient:

| Type                 | Currency | Description                                                                                          |
| -------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `BANK_ACCOUNT`       | NGN      | Nigerian domestic bank transfer. Provide `account_number` and `bank_code`.                           |
| `US_BANK_ACCOUNT`    | USD      | US ACH or wire transfer. Provide routing number, account number, and `payout_scheme`.                |
| `SWIFT_BANK_ACCOUNT` | USD      | International SWIFT/IBAN transfer. Provide IBAN, BIC, account owner details, and `purpose_of_funds`. |

Each transfer requires a unique `reference` string you provide for idempotency. You can optionally associate a transfer with a customer using `on_behalf_of.customer_id`.

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/transfers \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "NGN",
    "amount": "50000",
    "reference": "txn_ref_abc123",
    "destination": {
      "type": "BANK_ACCOUNT",
      "bank_account": {
        "account_number": "0123456789",
        "bank_code": "058",
        "account_name": "Ada Lovelace"
      }
    }
  }'
```

Transfer statuses are `PROCESSING`, `SETTLED`, and `FAILED`.

<Tip>
  Always store your `reference` in your own database before calling `POST /transfers`. If the network request times out, you can use the reference to check whether the transfer was created rather than accidentally duplicating it.
</Tip>

## Merchant balance

Your **merchant balance** is the aggregated USDT held across all settled deposits, minus withdrawals and transfers. You can retrieve it at any time, transfer a portion of it to the trading engine, or list all past balance transfers.

```bash theme={null}
# Get current balance
curl https://api.dubupay.com/api/v1/payments/merchant/balance \
  -H "X-Api-Key: dubu_sk_live_..."

# Transfer balance to trading
curl -X POST https://api.dubupay.com/api/v1/payments/merchant/balance/transfer \
  -H "X-Api-Key: dubu_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"amount_usd": "500.00"}'
```

## Exchange rates

Before creating a temporary onramp or an NGN\_PAYOUT offramp, you need a `rate_id`. Fetch the current NGN-to-USDT and NGN-to-USDC exchange rates from:

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

The response includes both the rate and a `rate_id` you pass when creating a temporary onramp or NGN\_PAYOUT offramp. Rates are time-limited — fetch a fresh rate close to the moment you create the account.

<Note>
  For temporary onramps, the rate is locked at creation time. For permanent onramps, the live rate at the moment of each deposit is used. Always fetch the latest rate immediately before creating a temporary account to give your customer the most accurate amount.
</Note>

## Sandbox testing

In test mode, incoming deposits will not occur automatically. Use the sandbox endpoint to simulate an NGN deposit against any existing onramp:

```bash theme={null}
curl -X POST https://api.dubupay.com/api/v1/payments/sandbox/deposits \
  -H "X-Api-Key: dubu_sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "onramp_id": "onramp_01HZ...",
    "should_flag": false
  }'
```

Set `should_flag: true` to simulate a flagged deposit and test your compliance handling logic.

<Warning>
  The sandbox deposits endpoint only works with test API keys (`dubu_sk_test_...`). Calls with live keys will return an error.
</Warning>

## Payouts

**Payouts** are the outbound counterpart to deposits — they represent USDT or NGN being paid out as a result of a withdrawal or transfer. Payouts are read-only; you list them to track settlement status.

| Status       | Description                                                  |
| ------------ | ------------------------------------------------------------ |
| `PROCESSING` | Payout is in progress.                                       |
| `SETTLED`    | Payout has completed and funds have reached the destination. |
| `FAILED`     | Payout could not be completed.                               |

## Endpoint overview

| Method | Path                                   | Description                                      |
| ------ | -------------------------------------- | ------------------------------------------------ |
| `GET`  | `/payments/rates`                      | Get current NGN→USDT and NGN→USDC exchange rates |
| `POST` | `/payments/onramps`                    | Create a virtual bank account (onramp)           |
| `GET`  | `/payments/onramps`                    | List onramps                                     |
| `GET`  | `/payments/onramps/:id`                | Get a specific onramp                            |
| `GET`  | `/payments/deposits`                   | List deposits                                    |
| `GET`  | `/payments/deposits/:id`               | Get a specific deposit                           |
| `POST` | `/payments/sandbox/deposits`           | Simulate a deposit in test mode                  |
| `POST` | `/payments/withdrawals`                | Initiate a USDT withdrawal                       |
| `GET`  | `/payments/withdrawals`                | List withdrawals                                 |
| `GET`  | `/payments/withdrawals/:id`            | Get a specific withdrawal                        |
| `POST` | `/payments/offramps`                   | Create an offramp                                |
| `GET`  | `/payments/offramps`                   | List offramps                                    |
| `GET`  | `/payments/offramps/:id`               | Get a specific offramp                           |
| `POST` | `/payments/transfers`                  | Create a bank transfer                           |
| `GET`  | `/payments/transfers`                  | List transfers                                   |
| `GET`  | `/payments/transfers/:id`              | Get a specific transfer                          |
| `GET`  | `/payments/payouts`                    | List payouts                                     |
| `GET`  | `/payments/payouts/:id`                | Get a specific payout                            |
| `GET`  | `/payments/merchant/balance`           | Get merchant USDT balance                        |
| `POST` | `/payments/merchant/balance/transfer`  | Move balance to the trading engine               |
| `GET`  | `/payments/merchant/balance/transfers` | List balance transfers                           |
| `GET`  | `/payments/merchant/funding`           | Get merchant funding details                     |
