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

# Testing

> Rehearse payout outcomes in sandbox, including the ones that fail.

Sandbox is selected by the key you use. A `sk_sandbox_...` key hits the same base URL and
the same endpoints as live, and never moves real money.

```
https://api.orqex.com/v1
```

Payouts have their own test gateway in sandbox, with three method codes — one per instrument
type:

| Method code          | Instrument type  |
| -------------------- | ---------------- |
| `test_momo`          | `phone`          |
| `test_bank_transfer` | `bank_account`   |
| `test_crypto`        | `crypto_address` |

## Outcome matrix

The outcome is chosen by the **last two digits of the destination**. Which field that is
depends on the instrument type:

| Instrument type  | Field that drives the outcome |
| ---------------- | ----------------------------- |
| `phone`          | `phone_number`                |
| `bank_account`   | `account_number`              |
| `crypto_address` | `address`                     |

| Destination ends with | Outcome                                                                |
| --------------------- | ---------------------------------------------------------------------- |
| `01`                  | Starts `processing`, then completes once the pending delay has elapsed |
| `02`                  | Fails                                                                  |
| anything else         | Completes immediately                                                  |

```bash theme={null}
curl -X POST https://api.orqex.com/v1/payouts \
  -H "Authorization: Bearer sk_sandbox_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50,
    "currency": "EUR",
    "method": "test_bank_transfer",
    "description": "Sandbox payout",
    "instrument": {
      "type": "bank_account",
      "account_name": "Ada Lovelace",
      "account_number": "00000000000002",
      "bank_code": "TESTBANK",
      "country": "DE"
    },
    "customer": {
      "email": "ada@example.com",
      "first_name": "Ada",
      "last_name": "Lovelace"
    }
  }'
```

That account number ends in `02`, so the payout fails — the case most integrations forget to
handle.

## The processing path

A destination ending in `01` returns `processing`. It settles when the pending window
expires and Orchestrate next checks the payout — either on its own schedule, or immediately
if you call [`GET /payouts/{id}/sync`](/payouts/overview#verifying-a-payout).

Shorten the window so your asynchronous tests do not crawl:

```json theme={null}
{
  "gateway_options": {
    "test": { "pending_duration_seconds": 3 }
  }
}
```

Accepted range is 0 to 600 seconds.

## What to rehearse before going live

* A payout that fails, and how you surface it to whoever was expecting the money.
* A payout that settles asynchronously, so you prove your
  [webhook handler](/webhooks) works rather than relying on the create response.
* A duplicate `reference`, which returns `409` — the guard that stops you paying twice.
* The same webhook delivered twice.

## Going live

```diff theme={null}
- Authorization: Bearer sk_sandbox_...
+ Authorization: Bearer sk_live_...
```

That is the whole change.

<Warning>
  The test gateway does not exist in the live environment. `test_momo`,
  `test_bank_transfer` and `test_crypto` are rejected outside sandbox.
</Warning>
