> For the complete documentation index, see [llms.txt](https://apidocs.onekeypayments.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://apidocs.onekeypayments.com/api-reference/references/test-merchant-and-mock-psp.md).

# Test Merchant & Mock Psp

The Mock PSP provides a test merchant account to validate your payment flows before going live. Test API keys are the only distinction from production — same endpoints, same request/response schemas, same authentication. Just swap keys when you're ready; no code changes needed.&#x20;

When you use test credentials, transactions route automatically to the Mock PSP instead of a real processor. No real money moves. Webhooks, statuses, and lifecycle events behave identically to production.

The Mock PSP determines each transaction's outcome based on the amount you send. The scenario is keyed on the significant digits of the amount, not its absolute value — so the same amount works across currencies (e.g. 10, 100, 1000 all trigger the same scenario regardless of whether it's USD or INR).

## Amount-Based Scenario Control

The Mock PSP picks the scenario from the **leading digits** of the amount. Trailing zeros are ignored, so an amount and the same amount with extra zeros trigger the **same** scenario:

* `1`, `10`, `100`, `1000`, `10000`, … → all map to scenario **1**.
* `5`, `50`, `500`, `5000`, … → all map to scenario **5**.

Pick whatever magnitude clears the per-transaction minimum for your currency. A USD payment might send `10`; the equivalent INR payment sends `1000` — both trigger scenario **1**. **The currency itself does not affect scenario selection — only the amount does.**

**Two-digit variants.** Some scenarios have a second variant with a two-digit code (e.g. `41`, `51`). To resolve a scenario, the mock drops the amount's last digit one at a time until it matches a code (longest match wins). So `42` resolves to scenario **4**, while `41` (and `410`, `4100`, …) matches the distinct variant **41** first.

**Default behavior:** any amount whose leading digit is not listed below (e.g. starts with `7`, `8`, or `9`) results in a successful transaction (PENDING → COMPLETED) with a webhook delivered after **approximately 1 minute**.

## Payin Scenarios

### Successful Payins

| Code | Example amounts             | Behavior               | Webhook                   |
| ---- | --------------------------- | ---------------------- | ------------------------- |
| `1`  | `1`, `10`, `100`, `1000`, … | Completes after \~2s   | Yes                       |
| `2`  | `2`, `20`, `200`, `2000`, … | Completes after \~3min | Yes                       |
| `3`  | `3`, `30`, `300`, `3000`, … | Completes after \~5min | No (poll status endpoint) |

### Under Review (triggers automatic refund)

| Code | Example amounts             | Behavior                                                                   | Webhook |
| ---- | --------------------------- | -------------------------------------------------------------------------- | ------- |
| `6`  | `6`, `60`, `600`, `6000`, … | Goes to FOR\_REVIEW after \~1min (terminal) — triggers an automatic refund | Yes     |

### Failed Payins — Delayed

| Code | Example amounts        | Final Status | Delay  | Error Code        |
| ---- | ---------------------- | ------------ | ------ | ----------------- |
| `5`  | `5`, `50`, `500`, …    | CANCELLED    | \~3min | MOCK\_ERROR       |
| `51` | `51`, `510`, `5100`, … | CANCELLED    | \~8min | PROCESSING\_ERROR |

### Failed Payins — Immediate (no webhook)

| Code | Example amounts        | Error Code            | Error Message                     |
| ---- | ---------------------- | --------------------- | --------------------------------- |
| `4`  | `4`, `40`, `400`, …    | INVALID\_CARD\_NUMBER | The card number is invalid        |
| `41` | `41`, `410`, `4100`, … | INSUFFICIENT\_FUNDS   | Insufficient funds in the account |

## Payout Scenarios

### Successful Payouts

| Code | Example amounts             | Behavior               | Webhook                   |
| ---- | --------------------------- | ---------------------- | ------------------------- |
| `1`  | `1`, `10`, `100`, `1000`, … | Completes after \~2s   | Yes                       |
| `2`  | `2`, `20`, `200`, `2000`, … | Completes after \~3min | Yes                       |
| `3`  | `3`, `30`, `300`, `3000`, … | Completes after \~5min | No (poll status endpoint) |

### Failed Payouts — Delayed

| Code | Example amounts        | Final Status | Delay  | Error Code         |
| ---- | ---------------------- | ------------ | ------ | ------------------ |
| `5`  | `5`, `50`, `500`, …    | CANCELLED    | \~3min | PROCESSING\_FAILED |
| `51` | `51`, `510`, `5100`, … | CANCELLED    | \~8min | MOCK\_ERROR        |

### Failed Payouts — Immediate (no webhook)

| Code | Example amounts        | Error Code                      | Error Message                                             |
| ---- | ---------------------- | ------------------------------- | --------------------------------------------------------- |
| `4`  | `4`, `40`, `400`, …    | INVALID\_BENEFICIARY\_ACCOUNT   | The beneficiary account information is invalid            |
| `41` | `41`, `410`, `4100`, … | MERCHANT\_INSUFFICIENT\_BALANCE | Merchant does not have sufficient balance for this payout |

## Refund Scenarios

Refund scenarios use the same code scheme. The refund inherits the currency of the original payin.

### Successful Refunds

| Code | Example amounts             | Behavior                                                                               | Webhook |
| ---- | --------------------------- | -------------------------------------------------------------------------------------- | ------- |
| `1`  | `1`, `10`, `100`, `1000`, … | Completes after \~2s                                                                   | Yes     |
| `6`  | `6`, `60`, `600`, `6000`, … | Completes after \~2s (matches the automatic refund created for the under-review payin) | Yes     |

### Failed Refunds — Delayed

| Code | Example amounts     | Final Status | Delay  | Error Code  |
| ---- | ------------------- | ------------ | ------ | ----------- |
| `5`  | `5`, `50`, `500`, … | CANCELLED    | \~3min | MOCK\_ERROR |

### Failed Refunds — Immediate (no webhook)

| Code | Example amounts     | Error Code             | Error Message                          |
| ---- | ------------------- | ---------------------- | -------------------------------------- |
| `4`  | `4`, `40`, `400`, … | DUPLICATE\_TRANSACTION | This refund has already been processed |

## Key Notes

* **Currency-agnostic:** the scenario is keyed on the leading digits of the amount, independent of the currency. Append zeros to reach the minimum for your currency — `10` (USD) and `1000` (INR) both trigger scenario `1`.
* **Webhooks:** for scenarios with webhooks enabled, the Mock PSP sends a webhook to your configured notification URL with the status update. For scenarios without webhooks (code `3`), use the GET status endpoint to poll for the transaction result.
* **Automatic refund:** the under-review payin (code `6`) ends in `FOR_REVIEW` and triggers an automatic refund for the same amount (which lands on refund code `6`) — useful to test the end-to-end refund flow without issuing a refund request yourself.
* **Family fallback:** an amount that doesn't match a full code falls back to its leading digit (e.g. `42` behaves as `4`). Amounts whose leading digit is not listed default to a successful payment with a webhook after \~1 minute.
* **All other fields:** use the same request structure, headers, and authentication as documented for production. Only the amount determines the mock outcome.
