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

# Wallet Transfer

> Transfer funds between customer wallets or from your merchant wallet to a customer wallet.

## Transfer from merchant wallet to customer wallet

`POST /transfer/wallet`

Transfers funds between two customer wallets belonging to your merchant account, identified by their customer IDs. The source customer's wallet is debited the transfer amount plus applicable fees, and the destination customer receives the transfer amount net of fees.

<Note>
  Both customers must have active (`ACTIVE`) wallets. The source customer's tier daily limit, minimum balance, and single-transaction limits are enforced. The destination wallet's tier maximum balance is also validated.
</Note>

### Request

<ParamField header="Authorization" type="string" required>
  Bearer token. Requires `MANAGE_TRANSFER` permission.
</ParamField>

<ParamField body="fromCustomerId" type="string" required>
  UUID of the source customer whose wallet will be debited.
</ParamField>

<ParamField body="toCustomerId" type="string" required>
  UUID of the destination customer whose wallet will be credited. Must be different from `fromCustomerId`.
</ParamField>

<ParamField body="amount" type="number" required>
  Transfer amount in kobo.
</ParamField>

### Response

<ResponseField name="status" type="boolean">
  `true` on success.
</ResponseField>

<ResponseField name="message" type="string">
  `"Transaction successfully completed."` or `"Transaction successfully submitted for approval."` for web-dashboard requests.
</ResponseField>

<ResponseField name="data" type="object">
  Present on API-initiated transfers.

  <Expandable title="data properties">
    <ResponseField name="amount" type="number">
      Transfer amount in kobo.
    </ResponseField>

    <ResponseField name="reference" type="string">
      Auto-generated transaction reference.
    </ResponseField>

    <ResponseField name="total" type="number">
      Total amount deducted from the source wallet (amount + fees).
    </ResponseField>

    <ResponseField name="transaction_fee" type="number">
      Transfer fee charged in kobo.
    </ResponseField>

    <ResponseField name="fee_breakdown" type="object">
      Detailed fee breakdown.

      <Expandable title="fee_breakdown properties">
        <ResponseField name="base_fee" type="number">
          Base platform fee in kobo.
        </ResponseField>

        <ResponseField name="merchant_fee" type="number">
          Additional merchant markup fee in kobo.
        </ResponseField>

        <ResponseField name="total_fee" type="number">
          Combined total fee in kobo.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="source_customer_id" type="string">
      UUID of the source customer.
    </ResponseField>

    <ResponseField name="target_customer_id" type="string">
      UUID of the destination customer.
    </ResponseField>

    <ResponseField name="source_customer_wallet" type="string">
      UUID of the source wallet.
    </ResponseField>

    <ResponseField name="target_customer_wallet" type="string">
      UUID of the destination wallet.
    </ResponseField>

    <ResponseField name="description" type="string">
      Human-readable description.
    </ResponseField>
  </Expandable>
</ResponseField>

### Examples

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.tagpay.ng/v1/transfer/wallet \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "fromCustomerId": "cust_9f8e7d6c-b5a4-3210-fedc-ba0987654321",
      "toCustomerId": "cust_1a2b3c4d-e5f6-7890-abcd-ef0987654321",
      "amount": 1500000
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.tagpay.ng/v1/transfer/wallet", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      fromCustomerId: "cust_9f8e7d6c-b5a4-3210-fedc-ba0987654321",
      toCustomerId: "cust_1a2b3c4d-e5f6-7890-abcd-ef0987654321",
      amount: 1500000,
    }),
  });

  const data = await response.json();
  ```
</CodeGroup>

```json Response theme={null}
{
  "status": true,
  "message": "Transaction successfully completed.",
  "data": {
    "amount": 1500000,
    "reference": "TXN-20240501-W2W-ABC123",
    "total": 1510000,
    "transaction_fee": 10000,
    "fee_breakdown": {
      "base_fee": 10000,
      "merchant_fee": 0,
      "total_fee": 10000
    },
    "source_customer_id": "cust_9f8e7d6c-b5a4-3210-fedc-ba0987654321",
    "target_customer_id": "cust_1a2b3c4d-e5f6-7890-abcd-ef0987654321",
    "source_customer_wallet": "wlt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "target_customer_wallet": "wlt_b2c3d4e5-f6a7-8901-bcde-fa2345678901",
    "description": "Fund transfer between customers"
  }
}
```

***

## Transfer between wallets by account number

`POST /transfer/wallet-to-wallet`

Transfers funds between two customer wallets identified by their 10-digit virtual account numbers instead of customer IDs. Use this when you have account numbers stored directly.

The source wallet must be `ACTIVE`. Post-no-credit and maximum balance rules are applied to the destination wallet.

### Request

<ParamField header="Authorization" type="string" required>
  Bearer token. Requires `MANAGE_TRANSFER` permission.
</ParamField>

<ParamField body="fromWalletId" type="string" required>
  10-digit virtual account number of the source wallet.
</ParamField>

<ParamField body="toWalletId" type="string" required>
  10-digit virtual account number of the destination wallet. Must be different from `fromWalletId`.
</ParamField>

<ParamField body="amount" type="number" required>
  Transfer amount in kobo.
</ParamField>

### Response

<ResponseField name="status" type="boolean">
  `true` on success.
</ResponseField>

<ResponseField name="message" type="string">
  `"Transaction successfully completed."`
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data properties">
    <ResponseField name="amount" type="number">
      Transfer amount in kobo.
    </ResponseField>

    <ResponseField name="reference" type="string">
      Auto-generated transaction reference.
    </ResponseField>

    <ResponseField name="total" type="number">
      Total amount deducted from source wallet (amount + fees).
    </ResponseField>

    <ResponseField name="transaction_fee" type="number">
      Transfer fee in kobo.
    </ResponseField>

    <ResponseField name="source_customer_id" type="string">
      UUID of the source customer.
    </ResponseField>

    <ResponseField name="target_customer_id" type="string">
      UUID of the destination customer.
    </ResponseField>

    <ResponseField name="source_customer_wallet" type="string">
      UUID of the source wallet.
    </ResponseField>

    <ResponseField name="target_customer_wallet" type="string">
      UUID of the destination wallet.
    </ResponseField>

    <ResponseField name="description" type="string">
      Human-readable description.
    </ResponseField>
  </Expandable>
</ResponseField>

### Examples

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.tagpay.ng/v1/transfer/wallet-to-wallet \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "fromWalletId": "0123456789",
      "toWalletId": "0987654321",
      "amount": 750000
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.tagpay.ng/v1/transfer/wallet-to-wallet", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      fromWalletId: "0123456789",
      toWalletId: "0987654321",
      amount: 750000,
    }),
  });

  const data = await response.json();
  ```
</CodeGroup>

```json Response theme={null}
{
  "status": true,
  "message": "Transaction successfully completed.",
  "data": {
    "amount": 750000,
    "reference": "TXN-20240501-WTW-DEF456",
    "total": 760000,
    "transaction_fee": 10000,
    "source_customer_id": "cust_9f8e7d6c-b5a4-3210-fedc-ba0987654321",
    "target_customer_id": "cust_1a2b3c4d-e5f6-7890-abcd-ef0987654321",
    "source_customer_wallet": "wlt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "target_customer_wallet": "wlt_b2c3d4e5-f6a7-8901-bcde-fa2345678901",
    "description": "Fund transfer between customers"
  }
}
```

***

## Error responses

| HTTP Status | Description                                             |
| ----------- | ------------------------------------------------------- |
| `400`       | Source and destination customer/wallet IDs are the same |
| `400`       | One or both customer wallets not found                  |
| `400`       | Source or destination wallet is inactive                |
| `400`       | Insufficient balance on source wallet                   |
| `400`       | Post-no-credit is enabled on destination wallet         |
| `400`       | Destination wallet maximum balance would be exceeded    |
| `400`       | Customer daily tier limit exceeded                      |
| `400`       | Customer minimum balance condition not met              |
| `401`       | Missing or invalid authentication token                 |
| `403`       | Internal transfers not enabled on this account          |

```json 400 Insufficient Balance theme={null}
{
  "status": false,
  "message": "Insufficient balance on source wallet to complete this transfer."
}
```

```json 400 Daily Tier Limit theme={null}
{
  "status": false,
  "message": "Customer daily tier limit exceeded"
}
```

```json 400 Post-No-Credit theme={null}
{
  "status": false,
  "message": "Post no credit has been enabled on the beneficiary account. Kindly reachout to support for help."
}
```
