Developers

Sandbox & Testing

The sandbox is a full copy of production — same endpoints, same objects, same failure modes — with no real money involved. If it works here, it works live.

Getting sandbox access

Sandbox keys are issued the moment you create an account — before underwriting, before any commercial conversation. You can build the entire integration while your application is still being reviewed.

  • Sandbox keys start sk_test_ and pk_test_.
  • Point at https://api.sandbox.bearmerchant.com.
  • Nothing here touches a card network or a bank. No money moves, ever.
  • Data is yours to reset — wipe the whole sandbox from the dashboard when it gets messy.
Test and live keys are mutually incompatible. A test key against the production host returns 401, so a wrong environment variable fails immediately rather than quietly charging a real card.

Test cards

Each number produces a deterministic outcome. Use any future expiry date and any three-digit CVC (four for Amex).

Successful payments

NumberBrandBehaviour
4242 4242 4242 4242VisaApproves
5555 5555 5555 4444MastercardApproves
3782 822463 10005American ExpressApproves
6011 1111 1111 1117DiscoverApproves
4000 0025 0000 3155VisaApproves, but requires 3-D Secure first

Declines

NumberDecline codeShould you retry?
4000 0000 0000 0002card_declinedNo — generic issuer decline
4000 0000 0000 9995insufficient_fundsYes — worth retrying in a few days
4000 0000 0000 0069expired_cardNo — ask for a new card
4000 0000 0000 0127incorrect_cvcNo — re-collect the CVC
4100 0000 0000 0019fraudulentNo — never retry a suspected-fraud decline
4000 0000 0000 0119processing_errorYes — transient, retry immediately
Build against the decline table early. Teams that only test the happy path discover their retry logic on production traffic, which is an expensive place to learn.

Simulating harder scenarios

The interesting failures are the ones that arrive days later. The sandbox can produce all of them on demand rather than making you wait.

Disputes

NumberProduces
4000 0000 0000 0259A chargeback roughly a minute after capture
4000 0000 0000 2685A pre-dispute alert you can resolve by refunding
4000 0000 0000 1976An enquiry that escalates to a chargeback if ignored

ACH

Routing / accountProduces
110000000 / 000123456789Clears normally
110000000 / 000111111116Returns R01 — insufficient funds
110000000 / 000222222227Returns R02 — account closed
110000000 / 000333333338Returns R10 — customer disputes the debit

Controlling time

Subscription and settlement logic is hard to test when a billing cycle is a month long. The sandbox clock can be moved forward so a year of renewals takes a few seconds.

clock.sh bash
# Create a test clock and attach a subscription to it
curl https://api.sandbox.bearmerchant.com/v1/test_clocks \
  -u sk_test_…: \
  -d frozen_time=2026-01-01T00:00:00Z

# Jump forward two months — renewals, dunning and payouts all fire
curl https://api.sandbox.bearmerchant.com/v1/test_clocks/clk_9Fq2/advance \
  -u sk_test_…: \
  -d frozen_time=2026-03-01T00:00:00Z

Testing webhooks locally

Your development machine is not reachable from the internet, so the CLI opens a tunnel and forwards sandbox events to whatever port you are running on.

local.sh bash
# Install
npm install -g @bearmerchant/cli
bm login

# Forward every sandbox event to your local handler
bm listen --forward-to http://localhost:3000/hooks/bearmerchant

# In another terminal, fire events without making payments
bm trigger charge.succeeded
bm trigger subscription.payment_failed
bm trigger dispute.created
bm listen prints a signing secret for the session. Use it as your BM_WEBHOOK_SECRET locally so you are exercising real signature verification, not skipping it.

How the sandbox differs

Behaviour is identical in every way that matters to your code. These are the only differences worth knowing about:

AreaSandbox behaviour
MoneyNothing is ever charged or settled. Balances are simulated.
Card networksOutcomes come from the test-card table, not a real issuer.
Payout timingSettles instantly rather than on a banking schedule.
Rate limitsLower than production, to encourage sensible client behaviour.
Data retentionObjects are kept 90 days, then cleared.
UnderwritingNot applied — any business type can create sandbox charges.

Go-live checklist

Work through this before you switch keys. Most launch incidents come from one of these being skipped.

  • Live keys are loaded from the environment, not committed anywhere.
  • Webhook endpoint is registered against production and its signature verification has been tested with a real signed payload.
  • Every decline code in the table above has a handled path in your code, not just the generic one.
  • Idempotency keys are sent on every write, and are stable across retries of the same logical operation.
  • Your statement descriptor is set to something a cardholder will recognise — vague descriptors are a leading cause of disputes.
  • Refund and cancellation policies are visible before checkout.
  • Errors are logged with the error.code and the request id, so support can trace a specific payment.
  • Someone owns the dispute.created alert, and the deadline is on a calendar.
  • You have run one real low-value transaction end to end and refunded it.
Switch one service to live keys first and watch it for a day before moving the rest. A staged cutover turns a bad surprise into a small one.