---
title: "Run a test payout"
description: "Run a sandbox payout to a Nigerian bank account end to end, know which routes complete in sandbox today, and test the failure screens another way."
---
Use this recipe to run a sandbox payout to a Nigerian bank account end to end, find out which routes complete in sandbox today, and test the failure screens another way.

**Who it is for.** A remittance app that must test its "sent", "needs more details" and "failed" screens before it goes live.

**Status.** Available for a naira bank payout and some mobile-wallet payouts. Not yet available in sandbox for a payout that fails, pauses, returns or is recalled on purpose.

## Money example

1. You simulate a 50,000.00 NGN deposit into Chidi's sandbox NGN account.
2. You create a Nigerian bank payee for his sister. In sandbox, the account-name check returns `SIM ACCOUNT HOLDER` for any account number.
3. You send 20,000.00 NGN to her. The payout completes in about 3 minutes, and `transfer.status.completed` arrives.

## Before you start

- A sandbox key. If you use a scoped key, it needs `transfer:initiate`.
- A funded source. Fund an NGN account as in [Make a test deposit land](/recipes/sandbox/make-a-test-deposit-land), or use a sandbox wallet that holds test dollars.
- A payee created with the sandbox key (`POST /v1/external-accounts`).

## Find out what is required

Use the same discovery calls as in live: `GET /v1/transfer/supported-countries`, `GET /v1/external-accounts/institutions` and `GET /v1/transfer/rates`. No call tells you whether a route is simulated. This table shows what to expect today.

| Route | In sandbox today |
| :-- | :-- |
| Naira bank payouts | Simulated. They complete in about 3 minutes |
| Uganda mobile wallets | Run on the operator's own test system, and complete |
| Kenya mobile wallets | Go to review. You receive `transfer.status.failed` while the row stays `pending` |
| Ghana, Mexico, India, and some Côte d'Ivoire mobile wallets | Not yet available. Refused with `the payee is missing required information for this transfer type — please update the payee details` |
| Rwanda, Zambia and some West African mobile wallets | Not yet available |
| ACH, wire, SWIFT, SEPA and FPS payees | Set up at once, with no bank check. The payouts need a USD, EUR or GBP source, which does not open in sandbox today |
| RTP payees | Not yet available. The API refuses every routing number for instant payments |

## Steps

### 1. Fund the source

Simulate an NGN deposit and wait for `transfer.inflow.completed`. See [Make a test deposit land](/recipes/sandbox/make-a-test-deposit-land).

### 2. Create the payee and send the payout

Follow [Pay a bank account in Nigeria](/recipes/remittance-and-crypto/pay-a-bank-account-in-nigeria) with your sandbox key. The stored `account_name` of the payee becomes `SIM ACCOUNT HOLDER`.

### 3. Follow it to the end

<CodeGroup>
```bash title="cURL"
curl --request GET \
     --url https://api.gravv.xyz/v1/transactions/1a2a73ed-562b-4f79-8374-59eef50bea63 \
     --header 'Api-Key: <API_KEY>'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/transactions/1a2a73ed-562b-4f79-8374-59eef50bea63", {
  method: "GET",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
  },
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.get(
    "https://api.gravv.xyz/v1/transactions/1a2a73ed-562b-4f79-8374-59eef50bea63",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

Read `status` until it is `completed` or `failed`, or follow the webhooks as in [Trace a transfer and resend a webhook](/recipes/transactions/trace-a-transfer-and-resend-a-webhook). If sandbox has no result for a payout yet, it checks the payout again after about a minute.

### 4. Test the other screens another way

You cannot produce a failed, paused, returned or recalled payout on purpose today. Test those screens with recorded payloads of `transfer.status.failed`, `transfer.requires_information`, `transfer.resumed` and `transfer.status.returned`, from [Transfer events](/platform/webhooks/event-catalogue#transfers). A Kenya mobile-wallet payout does go to review. Use it to test this rule: if a row is `pending` and its latest webhook says failed, the payout is under review, so do not send it again.

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 400 `the payee is missing required information for this transfer type — please update the payee details` | The route is not available in sandbox today. The payee is not at fault | Do not edit the payee. Test Nigeria or Uganda instead |
| 400 `insufficient balance` | Gravv has not credited the test deposit yet, or the source is empty | Wait for the deposit webhook |
| `FX rate unavailable for currency conversion` | Sandbox has no rate for that pair | Test the NGN route |
| 400 `routing number … cannot receive instant payments; use ach or wire` when you create an RTP payee | RTP payees are not available in sandbox | Test ACH or wire payees |
| `transfer.status.failed`, while the row status is `pending` | The payout went to review | Trust the row. Do not send again |
| The fee in the transfer response does not match the row | A known sandbox difference | Read the fee from the transaction row |

## Webhooks you will receive

You receive the same webhooks as in live: `transfer.status.pending` several times, then `transfer.status.completed` or `transfer.status.failed`.

## Testing in sandbox

This page is the sandbox guide for payouts. Each rail's recipe in [Bank payouts](/recipes/bank-payouts/overview) and [Remittance and crypto](/recipes/remittance-and-crypto/overview) has its own sandbox notes.

## Reference

- [Initiate a transfer](/api-reference/transfer/post-v1-transfer)
- [Get a transaction](/api-reference/transactions/get-v1-transactions-transaction-id)
