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

# Sandbox

> Test your integration end to end without real money: same API, same webhooks, outcomes you trigger yourself.

The sandbox runs the same API as production, at a different base URL, with its
own API keys and its own data. **No real payment ever happens**: no USSD prompt
is sent and nothing is collected or paid out. You trigger the outcome of each
transaction yourself and receive the matching webhook, signed exactly as in
production.

| | Sandbox | Production |
| - | - | - |
| Base URL | `https://sandbox.winampay.de` | `https://api.winampay.de` |
| API key | `wk_test_<prefix>_<secret>` | `wk_live_<prefix>_<secret>` |
| Money | none | real Mobile Money |
| Outcome of a transaction | you call `/simulate` | operator confirmation / Winam decision |

Keys are not interchangeable: a `wk_test_` key is rejected in production and a
`wk_live_` key is rejected in the sandbox (`401`). Ask Winam for a sandbox key;
you receive it with your webhook secret, shown once.

Interactive API explorer (sandbox only): `https://sandbox.winampay.de/docs`.

## Behaviour

* **MTN deposit** → `status: "pending"`, `collection_mode: "merchant_initiated"`.
* **Orange deposit** → `status: "pending"`, `collection_mode: "customer_initiated"`
  and an `instructions` object to display to the player (see
  [Collection modes](/api-reference/collection-modes)). The USSD code in the
  sandbox is deliberately invalid (`#150*14*000000*000000000*<amount>#`): do not
  dial it on a real phone.
* **Withdrawal** → `status: "pending_approval"`, as in production.
* A deposit that is not simulated expires after 15 minutes and sends
  `payment.expired`.

## Simulate an outcome

```http theme={null}
POST /api/v1/sandbox/transactions/{winam_tx_id}/simulate
Content-Type: application/json
X-API-Key: wk_test_...

{ "outcome": "succeeded" }
```

| Transaction | `outcome` | Result | Webhook |
| - | - | - | - |
| Deposit `pending` | `succeeded` | `succeeded` | `payment.succeeded` |
| Deposit `pending` | `failed` | `failed` | `payment.failed` |
| Deposit `pending` | `expired` | `expired` | `payment.expired` |
| Deposit `expired` | `succeeded` | `succeeded` (late payment) | `payment.succeeded` |
| Withdrawal `pending_approval` | `succeeded` | `succeeded` | `payment.succeeded` |
| Withdrawal `pending_approval` | `failed` | `failed` (rejected) | `payment.failed` |

**Response `200`:**

```json theme={null}
{
  "winam_tx_id":    "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "reference":      "platform-bet-slip-98765",
  "previous_state": "pending",
  "state":          "succeeded",
  "webhook_event":  "payment.succeeded"
}
```

| Status | Meaning |
| - | - |
| `200` | Outcome applied, webhook sent to the transaction's `callback_url` (`webhook_event` is `null` when there is none) |
| `404` | Transaction not found, or created by another application |
| `409` | Outcome not reachable from the current state (e.g. a transaction already `succeeded`, a withdrawal `expired`) |
| `422` | Unknown `outcome` |

<Warning>
  **Test the late payment case.** In production a deposit can receive
  `payment.succeeded` after `payment.expired` for the same `winam_tx_id`
  (the player paid after the deadline). Simulate `expired`, then `succeeded`,
  and check that your platform credits the player once.
</Warning>

## Suggested test plan

1. Deposit MTN → simulate `succeeded` → player credited once, webhook signature verified.
2. Deposit Orange → display `instructions` → simulate `succeeded`.
3. Deposit → simulate `failed`, then `expired`, then `expired` + `succeeded`.
4. Re-send the same `reference` → same `winam_tx_id`, no second transaction.
5. Make your webhook endpoint return `500`, simulate an outcome, then use
   [Replay Webhook](/api-reference/replay-webhook).
6. Withdrawal → simulate `succeeded` and `failed`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.