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

# NGN Wallets

> Provision customer bank accounts, inspect balances, and reconcile NGN activity

An NGN customer wallet gives an individual customer a persistent bank account for collections and customer-funded transfers. Incoming transfers are recorded as wallet transactions and reported through signed webhooks.

## Prerequisites

Before creating a wallet:

* create an `individual` customer and retain the returned UUID;
* authenticate with the production API key belonging to that customer's merchant; and
* generate a stable `walletReference` in your system.

## Create a customer wallet

```bash theme={null}
curl --request POST \
  --url https://api-production.fossapay.com/api/v1/wallets/fiat/create \
  --header "x-api-key: $FOSSAPAY_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "customerId": "11111111-1111-4111-8111-111111111111",
    "walletName": "John Doe",
    "walletReference": "wallet-customer-1042"
  }'
```

| Field             | Requirement                                              |
| ----------------- | -------------------------------------------------------- |
| `customerId`      | UUID of a customer owned by the authenticated merchant   |
| `walletName`      | Non-empty display name sent as the provider wallet name  |
| `walletReference` | Non-empty correlation reference generated by your system |

An HTTP `201` response returns the wallet ID and assigned account details:

```json theme={null}
{
  "status": "success",
  "statusCode": 201,
  "message": "Fiat wallet created successfully",
  "data": {
    "walletId": "33333333-3333-4333-8333-333333333333",
    "bankName": "Provider Bank",
    "bankCode": "000000",
    "accountName": "John Doe",
    "accountNumber": "9710000000"
  }
}
```

Store every returned value. Bank details are assigned during provisioning and must not be hard-coded.

## One wallet per customer

Only one NGN wallet can be created for a customer. A second creation attempt is rejected.

Wallet creation does not provide idempotency semantics. If the response is lost or times out, retrieve the customer wallet or reconcile with support before trying again. Repeated creation attempts can leave an upstream account that requires operational reconciliation.

## Receive NGN

<Steps>
  <Step title="Display the assigned account">
    Show the bank name, account name, and account number returned by FossaPay.
  </Step>

  <Step title="Receive a bank transfer">
    The sender transfers NGN into the persistent account. Do not treat an uploaded receipt as confirmation.
  </Step>

  <Step title="Verify the event">
    Validate the webhook signature and acknowledge `deposit.completed` quickly.
  </Step>

  <Step title="Post once">
    Deduplicate by `eventId` and update your ledger in the same database transaction as recording the processed event.
  </Step>

  <Step title="Reconcile">
    Use the wallet transaction endpoints when delivery is delayed or the outcome is disputed.
  </Step>
</Steps>

For one-time exact-amount orders, use [Checkout Wallet](/guides/checkouts) instead of a persistent customer wallet.

## Retrieve wallets and balances

Retrieve a wallet by its FossaPay UUID or assigned account number. Responses include:

* `availableBalance`: funds currently available for a new operation;
* `ledgerBalance`: the provider ledger balance;
* `walletName`; and
* the bank account details.

The API also provides the merchant's master NGN wallet through `GET /api/v1/wallets/fiat/master`. That wallet holds business funds and is the source for [Master Wallet Payouts](/guides/payouts).

## Wallet-to-wallet transfers

`POST /api/v1/wallets/fiat/transfers/wallet-to-wallet` moves NGN between wallets owned by the authenticated merchant. Both account numbers must exist and belong to that merchant.

* The amount must be positive and cannot exceed the source available balance.
* Transfers are free.
* `narration` is required and limited to 255 characters.
* `reference` identifies the logical transfer and must not be reused for a new operation.
* A successful replay of the same source/reference returns the existing successful transaction instead of moving funds twice.
* Pending or previously failed references must be reconciled rather than blindly replaced.

The operation creates withdrawal and deposit transaction records. Use the corresponding wallet histories to reconcile both sides.

## Transaction history

Wallet transaction lists are newest-first and support:

| Parameter         | Default | Rules                                                          |
| ----------------- | ------: | -------------------------------------------------------------- |
| `page`            |     `1` | Positive integer                                               |
| `limit`           |    `10` | Clamped to a maximum of `100`                                  |
| `transactionType` |     All | A supported transaction type such as `deposit` or `withdrawal` |
| `startDate`       |    None | Date/time parseable by the API                                 |
| `endDate`         |    None | Date whose full day is included for NGN history                |

The response can include beneficiary details for external withdrawals, originator details for external deposits, or the destination account for internal transfers.

## Errors and recovery

| Status | Typical cause                                                                                           | Action                                                                                   |
| ------ | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `400`  | Invalid customer, existing wallet, unavailable provider data, insufficient funds, or provider rejection | Inspect the message and reconcile before retrying                                        |
| `401`  | Missing or invalid API key                                                                              | Correct authentication                                                                   |
| `403`  | Wallet or transaction belongs to another merchant                                                       | Correct the ownership mapping                                                            |
| `404`  | Wallet, account, or transaction was not found                                                           | Verify the stored identifier                                                             |
| `409`  | Transfer reference has already been used                                                                | Retrieve the original transaction; use a new reference only for a new business operation |
| `422`  | Invalid UUID, missing field, non-positive amount, or invalid narration                                  | Correct the request body                                                                 |
| `5xx`  | Temporary platform or provider failure                                                                  | Treat writes as ambiguous and reconcile first                                            |

## API reference

| Operation                | Endpoint                                                | Reference                                                                     |
| ------------------------ | ------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Create customer wallet   | `POST /api/v1/wallets/fiat/create`                      | [Create wallet](/api-reference/virtual-account/create-wallet)                 |
| Get master wallet        | `GET /api/v1/wallets/fiat/master`                       | [Get master wallet](/api-reference/virtual-account/get-master-wallet)         |
| Get wallet by ID         | `GET /api/v1/wallets/fiat/{walletId}`                   | [Get wallet](/api-reference/virtual-account/get-wallet)                       |
| Get wallet by account    | `GET /api/v1/wallets/fiat/account/{accountNumber}`      | [Get by account number](/api-reference/virtual-account/get-wallet-by-account) |
| Transfer between wallets | `POST /api/v1/wallets/fiat/transfers/wallet-to-wallet`  | [Wallet transfer](/api-reference/virtual-account/wallet-transfer)             |
| List wallet transactions | `GET /api/v1/wallets/fiat/{walletId}/transactions`      | [Wallet transactions](/api-reference/virtual-account/wallet-transactions)     |
| Get a transaction        | `GET /api/v1/wallets/fiat/transactions/{transactionId}` | [Wallet transaction](/api-reference/virtual-account/wallet-transaction)       |

## Production checklist

* [ ] Persist the customer UUID before wallet creation.
* [ ] Generate and store `walletReference` before calling FossaPay.
* [ ] Store the assigned wallet and bank details from the response.
* [ ] Never confirm deposits from receipts alone.
* [ ] Verify webhook signatures and deduplicate by `eventId`.
* [ ] Reconcile ambiguous writes and delayed events through transaction history.
* [ ] Keep customer funds separate from merchant master-wallet funds.
