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

# Sandbox — payins

> Test every payin outcome — paid, underpaid, overpaid and the rest — with deterministic trigger codes.

Sandbox is a test version of the live API. Every endpoint behaves identically: same validation, same
auth, same error envelope, same response shape. But:

* No wallet impact — sandbox payins do not move real funds
* Nothing is stored, and no deposit address is ever reserved
* Callbacks are not sent for sandbox payments

Switch by changing the base URL — credentials, payloads, and code stay the same.

```
Live:    https://api.pontisglobe.com
Sandbox: https://sandbox.pontisglobe.com
```

## Trigger codes

Payouts read the trailing cents of `source_amount`. A payin cannot — its status is looked up by
`merchant_reference` — so the trigger is the **last two digits of your reference**:

| `merchant_reference` ends in | `create` → | `getPayinStatus` later →                                       |
| ---------------------------- | ---------- | -------------------------------------------------------------- |
| `-00`                        | `created`  | `paid` (`100.00` received, `99.50` credited)                   |
| `-01`                        | `created`  | `underpaid` (`40.00` received, `39.80` credited)               |
| `-02`                        | `created`  | `overpaid` (`130.00` received, `129.35` credited)              |
| `-03`                        | `created`  | `awaiting_payment` (stays awaiting — useful for polling tests) |
| `-04`                        | `created`  | `expired`                                                      |
| `-05`                        | `created`  | `failed`                                                       |
| `-06`                        | `created`  | `created`                                                      |

Any other ending falls back to the `-00` path, so your real order ids work unchanged —
`ORDER-01-1042` is an ordinary reference because only the very end counts.

### Example

```js theme={null}
// Will report as fully paid
await createPayin({ merchant_reference: 'TEST-001', amount: '250.00', ... })

// Will report as underpaid — money arrived, less than the order
await createPayin({ merchant_reference: 'TEST-001-01', amount: '250.00', ... })

// Will stay awaiting_payment — polled status never settles
await createPayin({ merchant_reference: 'TEST-001-03', amount: '250.00', ... })
```

<Warning>
  **Exercise `-01` and `-02` before you go live.** `underpaid` and `overpaid` are settled states,
  not failures: the money arrived and you were credited. A handler that fulfils only on `paid` will
  silently hold your customer's funds.
</Warning>

## The sandbox checkout page

`create` returns a real `checkout_url`. Open it and you get the page your customer would see — your
amount, your reference, a choice of networks, a scannable QR code and a deposit address in the
correct format for the chain.

<Note>
  The address is simulated and belongs to nobody. Sending real funds to it will lose them, which is
  why sandbox links are visibly `pay_sbx_`.
</Note>

## Sandbox payin IDs

Sandbox `id`s are prefixed `sbx_` and checkout tokens `pay_sbx_`, so they are easy to recognise and
impossible to confuse with live ones — the same convention as `sb_` transaction ids on the payout
side:

```
id:           sbx_1723dccb62931b24a8ec33f1
checkout_url: https://pay.pontisglobe.com/c/pay_sbx_eyJyIjoiVEVTVC0wMDEi…
```

`create` and `getPayinStatus` report the same `id` for a given reference, so you can correlate them
exactly as you would live.

## Three differences from live

Sandbox stores nothing, and all three follow from that. None change the code you write — but a test
asserting on them will behave differently here.

|                                | Live                                                                  | Sandbox                                          |
| ------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------ |
| `status` amounts               | the order you created                                                 | a fixed sample — `100.00 USDT`                   |
| Reusing a `merchant_reference` | returns the original payment, `200`                                   | mints a new one, always `201`                    |
| `success_url` / `fail_url`     | checked against your allowed domains, and the payer is returned there | not checked, and the page shows no return button |

The first is because a status lookup has only your reference to work from, and a reference carries
no amount. The figures are stable across calls, so polling loops still settle.

The third is deliberate: validating a redirect host needs your merchant profile, and this path reads
nothing. Rather than skip the check, sandbox renders no redirect at all.
