Chromia Pay

Test mode

Force every outcome with a test key — no faucet, no wallet, no testnet. Including the outcomes that break consumers.

Any consumer handles confirmed. The ones that break in production break on underpaid and on a redelivery. A test key reaches both in one HTTP call.

curl -X POST "$CPAY_API_URL/v1/test/payments/$PAYMENT_ID/simulate_payment" \
  -H "authorization: Bearer $CPAY_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{"outcome":"underpaid","chain":"chromia"}'

Or through the SDK:

await cpay.testMode.simulatePayment(payment.id, { outcome: "underpaid", chain: "chromia" })
  • outcomeconfirmed, partial, overpaid, underpaid or expired. Default confirmed. partial pays some of the total and leaves the payment open, which is the only way to reach the top-up path: underpaid is a verdict reached at expiry, so it lands on a payment with nothing left to top up. confirmed settles whatever is still outstanding, so partial then confirmed is a part payment followed by the rest — and confirms rather than reading as an overpayment.
  • chainchromia or bsc. Default chromia. The chain has to carry the payment's settlement_asset and the environment needs a verified test payout wallet on it, so a stablecoin cannot be simulated on Chromia. Simulation refuses anything the real checkout would refuse.

Simulation is refused outright for live keys.

Paying with a real testnet token

simulate_payment covers every outcome without touching a chain, and that is the right tool for almost everything. When you do want a real transfer — proving your wallet integration, or checking a stablecoin's decimals against your own maths — these are the faucets, and they are not interchangeable:

RailTokenWhere to get it
Chromia testnettCHR (native)faucet.testnet.chromia.com — registers an FT4 account, 1000 tCHR/week
BNB testnettCHR (BEP-20)claim() on 0x0e61…aa8d, any EVM address, once a week
BNB testnetUSDC / USDTBinance's BSC testnet faucet. 18 decimals, like their mainnet counterparts

The two tCHR entries are different tokens on different networks wearing the same ticker. Economy-chain tCHR cannot be spent on the BNB rail, and vice versa.

BSC's stablecoins are 18 decimals while its CHR is 6. Sandbox is the only place to exercise the 18-decimal path before real money touches it, which is why the BSC testnet rail uses genuinely 18-decimal faucet tokens rather than a 6-decimal stand-in.

You will also need gas — tBNB from the BNB testnet faucet.

What to actually check

Running the happy path proves the wiring. These prove the consumer.

Each outcome reaches your consumer, and it returns 2xx

Run all four. Confirm the order ships on confirmed and overpaid, and does not ship on underpaid or expired.

A mangled signature is rejected

Flip one character of the v1= hex and re-send the delivery. It must 4xx and must not fulfil. If it fulfils, you are not verifying — and anyone who learns your endpoint URL can hand you free orders.

A replayed delivery fulfils exactly once

Re-send a valid delivery verbatim. The second one should be a no-op.

GET /v1/payments/:id agrees with what you recorded

If the two disagree, trust ours and find out why.

Testing against localhost

A sandbox endpoint may be plain http, for exactly this. If you would rather use a real hostname, expose the local port:

cloudflared tunnel --url http://localhost:3000

Then register the tunnel URL as the endpoint.

On this page