Testing
Everything on this page happens in Test mode, with a key that starts with ctp_test_sk_. No real funds are involved. See Test mode and live mode.
There are two ways to make a test payment:
| Simulate a payment | Pay on a test network | |
|---|---|---|
| What it is | cTpeWay creates the payment for you. Nothing is sent on any network. | You send test coins from a wallet. |
| You need | Only your test API key. | A wallet on the test network, and test coins from a faucet. |
| Good for | Testing your own code: webhooks, order fulfilment, every outcome. | Seeing the real checkout, wallet payment, confirmations and settlement. |
Start with the simulator. It covers almost everything your code has to handle.
Simulate a payment
Section titled “Simulate a payment”A simulated payment goes through the same steps as a real one. The invoice changes status, a settlement is created and the same webhook events are sent. You can tell it apart by simulated: true on the payment, and by a transaction hash that starts with sim_.
curl -X POST "https://api.ctpeway.com/v1/test/invoices/{id}/simulate_payment" \ -H "Authorization: Bearer $CTPEWAY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "outcome": "paid", "settlement": "held" }'// A paid invoice whose settlement is held, to see what your integration does with it.await ctpeway.test.invoices.simulatePayment(invoice.id, { outcome: 'paid', settlement: 'held' });npx ctpeway simulate invoice <invoice-id> --outcome paid --settlement heldYou can also do it without code. Open a test invoice in the dashboard and choose Simulate payment.
What you can simulate
Section titled “What you can simulate”| Field | Values | Meaning |
|---|---|---|
outcome |
paid |
The full amount arrives. |
underpaid |
Less than the amount due arrives. | |
overpaid |
More than the amount due arrives. | |
late |
The payment arrives after the invoice has expired or been canceled. | |
reorg |
The payment is confirmed and then removed from the network. | |
dropped |
The payment is seen and then disappears before it is confirmed. | |
stage |
detected, confirmed |
How far the payment goes. Use detected to stop before confirmation. |
settlement |
released, held |
Whether the funds reach the master wallet or stay held. |
amount |
A whole number of the asset’s smallest unit | The exact amount, if you do not want the one the outcome implies. |
inferred |
true |
The payment is noticed as a rise of the address’s balance, with no transaction known yet. Only with the outcome paid. See A payment without a transaction. |
option_id, or asset and network |
One of the invoice’s options | Which option is paid. Without them the payment goes to the option the payer selected, or to the only option the invoice has. |
You do not have to open the checkout page first. If nobody has selected the option yet, the simulator selects it exactly as the checkout page would: the rate is locked and the address is assigned.
Simulate a payment to a deposit address
Section titled “Simulate a payment to a deposit address”POST/v1/test/deposit_addresses/{id}/simulate_payment does the same for a reusable deposit address. It takes the same fields, and asset, the asset that was sent, is required.
Confirm a detected payment
Section titled “Confirm a detected payment”A payment simulated with "stage": "detected" stays unconfirmed, so that you can see what your integration does in between. Then confirm it in one of two ways. Both work on simulated payments only, and both take "settlement" to play the settlement as well.
| Endpoint | What it does |
|---|---|
| POST/v1/test/payments/{id}/confirm | Confirms the payment at once, with everything a confirmation does: the platform fee, the settlement, the invoice’s status and the events. |
| POST/v1/test/payments/{id}/add_confirmation | Gives the payment one more confirmation. Call it repeatedly to watch the count rise on the payment and on the checkout page. The call that reaches the network’s confirmations_required confirms the payment. |
# One more confirmationcurl -X POST "https://api.ctpeway.com/v1/test/payments/{id}/add_confirmation" \ -H "Authorization: Bearer $CTPEWAY_API_KEY"
# Or confirm at once, with the settlement heldcurl -X POST "https://api.ctpeway.com/v1/test/payments/{id}/confirm" \ -H "Authorization: Bearer $CTPEWAY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "settlement": "held" }'// A payment that is seen but not confirmed yet, as your integration first meets it...const detected = await ctpeway.test.invoices.simulatePayment(invoice.id, { stage: 'detected' });// ...gains a confirmation, as the checkout page counts them...await ctpeway.test.payments.addConfirmation(detected.id);// ...then is confirmed, with its settlement held, to see what your integration does with that.const payment = await ctpeway.test.payments.confirm(detected.id, { settlement: 'held' });A payment without a transaction
Section titled “A payment without a transaction”A real payment is sometimes noticed as a rise of an address’s balance before its transaction is known. See Payments and confirmations. To test that your integration copes with a payment that has no tx_hash:
- Simulate a payment with
"inferred": true. The payment hasdetected_by: "balance"and notx_hash. - Call POST/v1/test/payments/{id}/attach_transaction. The payment gets a
tx_hashand you receivepayment.transaction_attached. It keeps its id, its status and its settlement. This works once for each payment, whether it is still detected or already confirmed.
curl -X POST "https://api.ctpeway.com/v1/test/invoices/{id}/simulate_payment" \ -H "Authorization: Bearer $CTPEWAY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "inferred": true }'
curl -X POST "https://api.ctpeway.com/v1/test/payments/{payment-id}/attach_transaction" \ -H "Authorization: Bearer $CTPEWAY_API_KEY"// A deposit noticed as a balance change has no transaction until it is identified.const inferred = await ctpeway.test.depositAddresses.simulatePayment(depositAddressId, { asset: 'USDT', inferred: true,});await ctpeway.test.payments.attachTransaction(inferred.id); // emits payment.transaction_attachedRefund a simulated payment
Section titled “Refund a simulated payment”POST/v1/refunds works on a simulated payment too. Nothing is paid: the refund is played. It is completed at once and marked simulated: true, and you receive refund.created and refund.completed. No payout and no transaction are created.
Pay on a test network
Section titled “Pay on a test network”A test invoice is paid on a public test network. Open its checkout_url and pay as a customer would, with a connected wallet or by sending manually. The checkout page shows the test network’s name on every label and links to a faucet.
Test networks
Section titled “Test networks”| Live network | Test network |
|---|---|
| Ethereum | Sepolia |
| BNB Smart Chain | BNB Smart Chain testnet |
| Bitcoin | Bitcoin testnet4 |
| Solana | Solana devnet |
| Tron | Nile |
This list comes from the v2 design and is not final. The test networks for the other planned EVM networks are still to be confirmed. GET/v1/networks with a test key returns the test networks that are actually enabled.
Test coins and test tokens
Section titled “Test coins and test tokens”- Native coins come from each test network’s public faucet. Test invoices link to one from the checkout page. On Solana devnet you can also use the Solana command line:
solana airdrop 1 <address> --url devnet. - Tokens. cTpeWay provides its own test tokens,
tUSDTandtUSDC, on the test networks that have tokens. Anyone can mint them for free.
Each test network that GET/v1/networks returns carries faucet_url, the place to get its test coins. The link to the test token mint page will be listed here when it is published.
Test the held path
Section titled “Test the held path”Test mode charges the platform fee and the network fees for real, in test coins. That means you can watch a token deposit being held and released, exactly as in live mode:
- Make sure your test master wallet on the network has no native coin.
- Pay a test invoice with a test token, for example
tUSDTon the BNB Smart Chain testnet. - The invoice becomes
paid. The settlement becomesheld, and you receivesettlement.heldwith the amount of native coin needed. - Send test coins from a faucet to your master wallet address.
- The deposit is released and you receive
settlement.released.
With the simulator you can reach the same state in one call, by passing "settlement": "held".
See Settlement and the platform fee.
Test your webhooks
Section titled “Test your webhooks”- Send a test event. POST/v1/test/webhooks/ping sends a
test.pingevent to one of your test endpoints, or to all of them. Use it to check that your server is reachable and that your signature check passes. - Simulate payments. Each simulated payment sends the real events, in the real format.
- Look at the deliveries. The dashboard lists every delivery under Developers → Webhooks, with the request, your server’s response and a Resend button.
In test mode, a webhook URL may use localhost or a hostname ending in .test. Any other hostname must be on a verified domain, as in live mode.
To build a signed test request yourself, without cTpeWay sending anything, the SDK has CtpeWay.webhooks.generateTestHeader. See Node SDK.
What to test before going live
Section titled “What to test before going live”| Case | How to produce it | What your code should do |
|---|---|---|
| Paid in full | outcome: paid |
Fulfil the order once, on invoice.paid. |
| Underpaid | outcome: underpaid |
Do not fulfil. Tell the customer the rest is due. |
| Overpaid | outcome: overpaid |
Fulfil. Decide what to do about the extra amount. |
| Seen but not confirmed | stage: detected, then confirm it |
Do not fulfil until it is confirmed. |
| Refunded | Refund a simulated payment | Handle refund.completed. |
| No transaction yet | inferred: true, then attach the transaction |
Work without a tx_hash, and take it from payment.transaction_attached. |
| Expired | Let a test invoice expire | Offer the customer a new invoice. |
| Late payment | outcome: late |
Accept it or refund it. |
| Payment reversed | outcome: reorg |
Handle invoice.payment_reverted. |
| Held | settlement: held |
Alert whoever tops up the master wallet. Still fulfil the order. |
| The same event twice | Resend a delivery from the dashboard | Handle it once. |
| A forged request | Send a request with a wrong signature | Reject it. |
When these work, see Going live.

