Testing

Test mode simulates payments end to end, with no card charged and no money moved. Make payments succeed, fall short or be declined on demand, send sample webhook events, and go live with confidence.

On this page

Test mode

Test mode is a complete, separate copy of your account. Test keys start with rb_test_, and everything they create is simulated: checkouts, payments, settlement and webhooks all behave as in Live mode, but no card is charged and no money moves. Switch the dashboard between Test and Live with the toggle at the top of each page.

Test modeLive mode
Secret keysrb_test_…rb_live_…
Card paymentsSimulated on Railbed's test provider pageReal, on the provider's page
SettlementSimulated, with the same checks as liveUSDC to your payout wallet
Webhook endpointsAny https:// address (for your own computer, a tunnel)Public https:// addresses only
WebhooksReal, signed HTTP requests to your endpointsThe same
POST /v1/payments/:id/simulateAvailableRefused
AI agentsThe default when you approve oneOnly if you choose Live when you approve it

Test and live data never mix: a test key can't read or change a live payment, and each mode has its own endpoints and keys.

Simulate an outcome as a buyer

Open a test session's url (or any test checkout or payment link), enter an email and choose Pay. The test provider page offers three outcomes:

  • Simulate successful payment: about 97% of the order's value arrives, as a real provider's fee would leave it, and the payment becomes paid.
  • Simulate an underpayment: half arrives, so the payment is held for review, exactly as a live shortfall would be.
  • Simulate declined card: the payment stays open. Return to checkout and choose another way to pay on the same payment.

Simulate an outcome from your server

To test without a browser, start the session and simulate the outcome through the API. Use declined to test trying another provider on the same payment. Use failed to test a terminal failure and its payment.failed webhook.

# Start it (the buyer would normally do this by choosing a provider)
curl -X POST \
  https://pay.railbed.io/v1/checkout_sessions/pay_7AAiYH0Ykt11ED4hmfiN/start \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "customer_email": "buyer@example.com" }'

# Choose an outcome: "paid", "underpaid", "declined" or "failed"
curl -X POST \
  https://pay.railbed.io/v1/payments/pay_7AAiYH0Ykt11ED4hmfiN/simulate \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "outcome": "paid" }'

Simulated money runs through the same settlement checks and webhooks as a live payment. A declined outcome records the card decline without a failed webhook or a final payment state, so the same session can be retried. Simulating again on a finished payment returns it unchanged. See Simulate a payment for the details.

Send sample webhook events

In Developers, choose Send test event on a Test endpoint and pick any event. Railbed sends a signed, realistic event with a made-up payment, order and customer (the payment's metadata.sample is "true", the order is ord_sample and the customer cus_sample, and none of them is in your account or the API), then shows the exact body your server received and how it answered. Live endpoints can receive a ping only, so a live system never sees a payment that didn't happen.

Every delivery, test or real, appears in the endpoint's delivery log with its body, and can be sent again.

Receive webhooks on your own computer

Railbed sends webhooks from the internet, so it can't reach a server that only listens on your computer. While you build, expose your local server through a tunnel that gives it a public https:// address (for example Cloudflare Tunnel or ngrok), and add that address as a Test endpoint. When the tunnel's address changes, edit the endpoint: pending retries go to the new address.

A test plan worth running

Before going live, check that your integration handles each of these without a human:

ScenarioHow to cause itExpected result
A normal paymentSimulate paidOrder fulfilled once
The same event twiceResend a delivery from the delivery logNothing changes the second time
An underpaymentSimulate underpaidOrder not fulfilled; payment.held received
A card declineSimulate declinedOrder not fulfilled; buyer can retry another provider on the same session
A terminal failureSimulate failedOrder not fulfilled; payment.failed received; a new session is needed
A buyer who never paysCreate a session and leave itOrder not fulfilled; payment.expired after 24 hours
A lost create responseSend the same create request twice with one Idempotency-KeyOne payment, the same id both times
A second try at one orderCreate two sessions with the same order.id and new keys, and pay the secondOne order, both payments in its payment_ids, fulfilled once
A paid order sent againCreate another session for an order.id that's paid409 order_paid; the buyer isn't asked to pay twice
Your server is downPoint the endpoint at a failing address, then fix itDeliveries retry; Retry now in the log delivers it
A forged webhookSend a request with a wrong signatureYour endpoint rejects it with a 4xx

Going live

  1. Add your payout wallet in Settings. It must be a self-custody Polygon wallet you control, not an exchange deposit address.
  2. Switch the dashboard to Live and create a live key and live webhook endpoints. Live endpoints need public https:// addresses.
  3. Put the live key and the live endpoint's signing secret on your production server. Keep the test ones for your test environment. An AI agent you connected in Test stays in Test: if it should work on live data, connect it again and choose Live.
  4. Take one small real payment and follow it through: payment.paid received, the order fulfilled once, USDC in your wallet.

Updated · This page as Markdown