Testing, Simulation, and Building in Sandbox
Before going live, you need to test your full integration under real conditions without moving real assets. Bitnob provides a fully functional sandbox environment, allowing you to simulate quotes, deposits, payouts, and webhooks across all key flows: offramps, swaps, airtime, Bitcoin sends, and more.
This guide helps you set up realistic, automated, and intentional tests that expose problems before users ever see them.
Why Sandbox Testing Matters
No matter how well your integration reads in code, production behavior is always messier:
Webhooks may arrive late or out of order
Users underpay or use the wrong asset
Quotes expire while users are confirming
Payouts fail due to invalid account details
Lightning payments get stuck due to route issues
You don’t want to debug these for the first time with live funds. Sandbox testing makes these failure modes visible, reproducible, and debuggable.
Sandbox and production use the same base URL:
The environment is selected by the credential you sign with, not by the host. Your client ID is the same in both; the client secret is different. A request signed with your sandbox secret runs against simulated funds, and GET /api/whoami returns "environment": "sandbox" so you can confirm which one you are in.
Because the host is the same, keep the two secrets in separate configurations so a test job can never sign with the production secret. Rotate each independently.
What You Can Simulate
Bitnob’s sandbox allows you to test:
Creating quotes for Bitcoin and USDT
Simulating crypto deposits (on-chain, Lightning, USDT TRC20 etc)
Receiving webhook events
Testing webhook retry behavior
Simulating underpayment
Handling payout failures
Observing timeouts and quote expiry
Simulating a Deposit
For naira, create a virtual account and simulate an inbound bank transfer:
No request body is needed. Each call credits a fixed ₦1,000 to your company NGN balance and fires the virtual_account.deposit.success webhook, exactly as a real transfer would. The endpoint is rejected in production. See Simulate Deposit.
Testing Underpayment
You should simulate what happens when a user sends less than the quoted amount.
If the original quote expected 2.00 , this will trigger:
payouts.asset.underpayment webhook
Quote remaining in pending or incomplete state
Your system should log this, alert the user, and allow them to top up or cancel.
Testing Quote Expiry
Quotes have a limited validity window that depends on the product. For trading, sandbox NGN quotes last 30 seconds and crypto quotes about 5 minutes. To simulate expiry:
Create a quote
Wait until the quote's expires_at timestamp
Submit an order with that quote's id
Observe the 422 response: "Quote <id> has expired"
You should:
Prevent initiating expired quotes
Prompt the user to get a new one
Never send funds to an expired quote address
Testing Webhook Delivery and Retries
Bitnob retries webhooks if your server returns an error or doesn’t acknowledge.
To test:
Deploy your webhook handler locally Use a tool like ngrok to expose it: ngrok http 3000
Set your webhook URL in the sandbox dashboard to the ngrok URL
Simulate failures by returning a 500 from your handler
Observe Bitnob’s retry behavior
Sample Handler (with forced error)
This allows you to test:
Retry count and timing
Idempotency logic
Processing from retry queue
Bitnob Webhook Dashboard
For virtual cards you can also fire a test event directly with Simulate Webhook, and verify any event you receive against Verifying Events.
You can inspect:
Payloads
Delivery status
Retry attempts
Headers and metadata
Use this during integration and debugging. It’s especially helpful if your local logs aren’t complete or your webhook handler is stateless.
Additional Edge Cases to Test
User sends wrong asset (e.g., BTC instead of USDT)
Webhook arrives before your system creates the reference in DB
Duplicate webhook arrives after success is already processed
Payment arrives just after quote expiry
User sends to expired Lightning invoice
Reference reused across multiple transaction attempts
Callback URL is unreachable (simulate timeout with a slow handler)
User sends multiple valid amounts back-to-back (test batching logic)
Webhook signature is tampered with or invalid
Multiple webhooks arrive in parallel for different parts of the same flow
Recommended Local Setup
Use .env.sandbox file with:
BITNOB_CLIENT_ID=<your client id>
BITNOB_CLIENT_SECRET=<your sandbox client secret>
BITNOB_BASE_URL=https://api.bitnob.com
Build your sandbox runner script with:
Create quote
Initiate payout
Simulate deposit
Log webhook receipt
Log status updates
Expose localhost with ngrok
Tail logs to correlate events in real time
Summary
Sandbox testing isn’t just about making sure your code works. It’s about exploring edge cases, validating failure handling, and proving that your product will be safe, reliable, and observable in production.
Create and store every quote
Simulate deposits, underpayments, and webhook flows
Expire quotes and retry gracefully
Force webhook errors and test retries
Use the Bitnob dashboard to inspect event delivery
Reproduce the ugliest edge cases so your users never experience them
Once your sandbox test flows match your production requirements, you're ready to go live.