Testing in the sandbox
The sandbox is a separate environment with its own address, its own merchant account and its own API keys. Nothing
in it moves real money. Its API is at https://merchant-api-sandbox.jeton.com/v2, and it works exactly like the
production API: the same endpoints, the same request signing, the same errors and webhooks.
Everything you call in the sandbox is the API you will call in production: a payment is created with
POST /v2/payments here too. What the sandbox adds is the simulator, a handful of endpoints under /v2/simulator that
do what the other side does in production: a customer paying, money arriving, a bank or a chain deciding a payout.
They take the same path the real outcome takes, so your integration sees the events, webhooks and account entries it
will see in production. One more names the sandbox's test counterparties, so a payout or a transfer has someone to
reach. In production these endpoints do not exist and answer 404.
Complete a payment
In production, your customer pays the checkout. In the sandbox, the sandbox's test customer can pay it for you:
-
Create the payment with
POST /v2/payments. Keep thecheckout.urlfrom the response: it is returned only once. -
Complete it with
POST /v2/simulator/payments/{paymentId}/complete, sending that URL and anIdempotency-Key:{ "checkoutUrl": "<checkout.url from the create response>" } -
Follow the outcome as you will in production. The answer is
202with the payment as it stands, usually stillpendingorprocessing. Shortly after, the payment readscompleted, itspayment.completedevent is recorded and sent to your webhook, and your account shows the credit inGET /v2/accounts/{accountId}/transactions.
The test customer pays through the real checkout, so the real rules apply: a payment whose checkout has expired, that
is already paid, or that is being paid is refused with payment_not_payable.
Add funds to an account
To test with a balance, credit one of your fiat accounts as if a bank transfer had arrived on it:
-
Pick the account from
GET /v2/accountsand note itsidandcurrency. -
Deposit with
POST /v2/simulator/accounts/{accountId}/depositsand anIdempotency-Key, in the account's currency:{ "amount": { "value": "1000.00", "currency": "EUR" } } -
See the credit. The answer is
202with the account as it stands. Shortly after, the account's transactions show adeposit, and its balance rises by the amount less the deposit fee your pricing sets, if any.
The deposit takes the path a real one takes, so the real rules apply: an account that is not active is not
credited. There is no deposit event, so no webhook is sent; read
GET /v2/accounts/{accountId}/transactions instead.
Decide a payout's outcome
A payout to one of these destinations is accepted as usual, then ends as listed, the way a real payout ends: its
status changes, and payout.completed or payout.failed is sent to your webhook. The rule is the last digit: …01
completes, …02 fails. None of them belongs to a real account.
destination |
Value | Outcome |
|---|---|---|
bank_account IBAN |
DE09000000000000000001 |
completed |
bank_account IBAN |
DE79000000000000000002 |
failed |
crypto_wallet address on an EVM network (Ethereum, BNB Smart Chain, Polygon …) |
0x0000000000000000000000000000000000000001 |
completed |
crypto_wallet address on an EVM network |
0x0000000000000000000000000000000000000002 |
failed |
crypto_wallet address on TRON |
T9yD14Nj9j7xAB4dbGeiX9h8unkKLxmGkn |
completed |
crypto_wallet address on TRON |
T9yD14Nj9j7xAB4dbGeiX9h8unkKT76qbH |
failed |
- Create the payout with
POST /v2/payoutsto one of these destinations. The answer is202, as for any payout. - Follow the outcome. Shortly after, the payout reads
completedorfailed; its event follows as it does in production and is sent to your webhook. A failed payout gives the money back to your account.
Everything else about the payout is real: your balance, your limits and the fee are checked and applied as they are in production. A payout to any other destination is sent on as in production, so its outcome is not yours to decide.
Send money to a test customer or business
A payout to a Jeton account needs an individual on the other end, and a transfer needs another business. The sandbox has one of each, the same for every merchant:
-
Find them with
GET /v2/simulator/counterparties. Each comes as thedestinationits request takes:{ "payoutDestination": { "type": "jeton_account", "customerNumber": "<the test customer's number>" }, "transferDestination": { "type": "business", "merchantNumber": "<the test merchant's number>" } } -
Pay out with
POST /v2/payouts, sendingpayoutDestinationas thedestination, or transfer withPOST /v2/transfers, sendingtransferDestination. -
Follow the outcome as you will in production: the status, the event and the webhook.
These are real payouts and transfers: your balance, your limits and the fee apply. If the counterparty has no active account in the currency you send, the request is refused with the code anyone's would get. A counterparty the sandbox does not have is absent from the answer.
What you cannot make happen yet
- A failed payment. A payment has no failed outcome: a failed attempt leaves it
pendingwhile the customer may retry. A payment that is never paid endsexpiredwhen its checkout's lifetime (15 minutes) runs out, so to testpayment.expired, create a payment and leave it. - A crypto deposit. Only fiat accounts can be funded.
- A returned payout. A payout that completed and is later sent back by the receiving bank is not simulated.