Sandbox Mode for Trading APIs: Testing Without Risking Real Money
Most trading APIs claim to offer "sandbox mode," but reality is messy. Some brokers call their demo accounts sandboxes. Others run synthetic environments that pretend to fill orders but never touch real liquidity. Developers waste days figuring out which flavor they're dealing with — then waste more days when production behaves nothing like testing.
CopyBridge's sandbox is narrower than most, and knowing exactly how narrow is the point. It is a single boolean on the provider account. While it is on, that provider's trades are accepted, validated, deduplicated and stored by the same endpoint as always, and outbound webhooks fire exactly as in production — but the trades are withheld from every follower-facing endpoint, so nothing can reach a broker. Switching modes is one API call against the provider record; your own code and credentials do not change.
What Sandbox Actually Means in Trading
Traditional broker "demo accounts" are production servers that happen to use paper money. They connect to live pricing feeds, simulate slippage, and sometimes reject orders if liquidity looks thin. They're useful for backtesting strategies, but terrible for API development. Rate limits apply. Data resets unpredictably. And if you're building a multi-broker copy trading platform, you'd need demo accounts at every broker — each with different quirks.
Synthetic sandbox environments (Alpaca sandbox, for example) run on separate infrastructure. They accept orders, return fill confirmations, and emit account updates — but nothing touches a real order book. The problem: synthetic fills are too perfect. Market orders fill at the exact bid/ask. No requotes. No "off quotes" errors. When you go live, production throws errors your tests never surfaced.
CopyBridge takes a simpler route: it does not simulate fills at all. A sandbox trade goes through the same POST /api/v1/trades validation and the same deduplication as a production trade, and emits the same outbound webhook. What changes is delivery. The row is written with is_sandbox = true, and every follower-facing endpoint — GET /api/v1/trades, /api/v1/trades/open, /api/v1/trades/snapshot — excludes sandbox rows. No Copier EA ever receives them, so there is no fill to simulate.
What is_sandbox Actually Is
is_sandbox is a column on the provider account, not a parameter you pass per request. POST /api/v1/trades reads action, symbol, type, lots, price, sl, tp, magic, ticket and timestamp from the body — sending is_sandbox there does nothing, because the server takes the flag from the authenticated provider instead. The only endpoints that accept is_sandbox as input are the integrator provisioning calls covered in the checklist below.
You do see the flag on the way out. The HTTP 201 response to a trade submission is the stored row, and is_sandbox is one of its fields, alongside id, seq, action, symbol, type, lots, price, sl, tp, magic, ticket, timestamp and created_at. There is no separate signal object and no sandbox-prefixed identifier: a trade is identified by the ticket you supplied and the id/seq the server assigned.
Followers have no sandbox setting of their own. A follower belongs to exactly one provider, and there is no follower-level flag, no Copier EA input and no registration field for sandbox. Whether a follower sees anything is decided entirely by its provider's flag — while that is on, the provider's trades are withheld from the feed for all of its followers at once.
Deduplication and Webhook Events in Sandbox
Sandbox preserves production semantics for deduplication and webhooks. There is no idempotency_key in the CopyBridge API; deduplication is keyed on the trade itself. OPEN and CLOSE are unique per (provider_id, ticket, action), enforced by a partial unique index, so resubmitting the same action for the same ticket does not create a second row — it returns HTTP 200 with a body of {"status": "duplicate", ...} instead of the 201 and trade row that a first submission returns. MODIFY is outside the index and always inserts.
Because the check is on the ticket you supply, retry logic behaves identically in both modes: resend the same event with the same ticket, and the second call is a no-op.
Outbound webhooks fire on sandbox trades exactly as on production ones, provided the provider has a delivery URL and secret configured. The envelope is the same in both modes — id, type, created_at and data — with one addition: while the provider is in sandbox, every event carries a top-level sandbox: true. The field is sandbox, not is_sandbox, and for a production provider it is absent entirely rather than sent as false.
The event types are the same four in both modes — trade.opened, trade.closed, follower.created and follower.deactivated. There is no separate family of sandbox events.
Signature verification uses the same Standard Webhooks HMAC-SHA256 process as production — the webhook-id/webhook-timestamp/webhook-signature headers, verified against your whsec_... secret exactly as described in the copy trading webhooks guide. Same code, same environment variables, same failure modes. If your webhook handler drops sandbox events due to a signature mismatch, it'll drop production events too. You find out now, not after launch.
More on webhooks: Developer docs
Going Live Checklist
Sandbox isn't a separate codebase — it's a runtime flag. Going live means flipping is_sandbox from true to false, but a few gotchas exist.
1. Sandbox Is a Provider Flag, Not an EA Setting
There is no "Sandbox Mode" switch in the Master EA — it isn't an EA input at all. is_sandbox is a flag on the provider account, and it's provisioned through the integrator API, not set locally in MT4/MT5:
curl -X PATCH https://api.copybridge.io/api/v1/integrator/providers/{provider_id} \
-H "X-Integrator-Key: <your-integrator-key-uuid>" \
-H "Content-Type: application/json" \
-d '{ "is_sandbox": true }'
(The same field can also be set at creation time via POST /api/v1/integrator/providers.) This is an integrator-level operation, scoped to a child provider under a white-label account — there's no self-service sandbox toggle in the standard provider dashboard.
Once is_sandbox is true for a provider, their submitted trades are tagged as sandbox and bypass the platform's production risk caps (symbol whitelist, lot-size ceiling), so integrators can stage test data without those guardrails getting in the way.
2. It's the Follower's Copier EA That's Gated — By Build Date, Not Version Number
The compatibility check that matters runs against followers, not the Master EA. Every request a Copier EA makes reports its build via an X-EA-Version header, which the API stores as that follower's last-reported version. Before the platform will let a provider flip into sandbox mode, it checks every active follower on that provider: if any of them last reported a version older than a minimum build date (currently 2026.05.22), the toggle is rejected until those followers update.
That cutoff is a build date, not a semantic version — the Copier EA stamps its version from its own compile date, so "sandbox-aware" means "built on or after the cutoff," not "v2.5 or later." There's nothing to configure in the EA itself: installing a current Copier EA build is what raises the reported version. A sandbox-aware Copier EA recognizes the is_sandbox flag on trades it receives and skips sending them to the broker instead of copying them for real. An older EA has no such check — which is exactly why the platform won't enable sandbox mode for a provider until its followers are current.
3. Sandbox Trades Are Never Served to Followers
Sandbox trades are stored with is_sandbox = true, and switching the provider back to production does not remove them. They are not kept forever, though: a nightly job archives closed trades and deletes them from the live table after 30 days, and it makes no distinction between sandbox and production rows. They stay invisible to the trade feed, though: GET /api/v1/trades, /api/v1/trades/open and /api/v1/trades/snapshot exclude sandbox rows unconditionally, so there is no filter to pass and no risk of a stale test trade being served to a follower after you go live. If you want the history separated anyway, provision a dedicated child provider for testing rather than reusing the one you will run live.
4. Webhook Endpoints Might Differ
Sandbox webhooks typically point to localhost tunnels (ngrok, localtunnel) or staging environments. Production webhooks need public HTTPS endpoints with real certs. Update webhook URL in account settings when going live. Test signature verification on the new endpoint before flipping is_sandbox: false — a misconfigured production endpoint means missed events.
5. Rate Limits Are Shared
Rate limiting is applied per IP across everything under /api/ — 200 requests per minute, the same ceiling for every account and every tier. Sandbox requests are not exempt, so a load test run from the same host as your production integration eats the same budget. If you're running automated tests, throttle them or run them from a different host; separate API keys will not help, because the limit is not keyed on the credential.
Common Gotchas
Sandbox Doesn't Exercise Replication or Execution
Because sandbox trades are never served to a Copier EA, nothing downstream of submission is tested: lot scaling, broker symbol-name differences, off-quotes errors, "trade context busy" rejections, margin calls. Sandbox exercises the API contract — submission, validation, deduplication, webhook delivery and signature verification — and stops there. For replication and execution behaviour, attach a real Copier EA to a demo account, after sandbox has confirmed your server-side integration works.
Webhook Replay Isn't Automatic
If your webhook endpoint is down when a sandbox event fires, CopyBridge retries once more (~500 ms later) and times out each attempt after 5 seconds. After both attempts fail, the delivery is marked failed — there's no further automatic retry. Production has the same behavior; recovering a failed delivery is a manual replay, covered in the copy trading webhooks guide. Test failure scenarios by intentionally returning HTTP 500 from your endpoint, confirm your logs show the retry, and verify you're deduplicating on the webhook-id header in case a late arrival overlaps a replay.
Why This Matters for SaaS Builders
If you're building a copy trading SaaS, sandbox mode compresses your dev cycle. No waiting for broker demo account approvals. No juggling credentials for 10+ brokers. Point a test provider at your integration, drive the whole submission-and-webhook path against it, and assert on what your own server receives. All without risking capital or violating broker ToS (some brokers disallow automated trading on demo accounts).
For white-label integrators, sandbox is provisioned per child provider, so you can stage a client's account and exercise the integration before that client has followers of their own. The version gate is a useful forcing function too: the platform refuses to enable sandbox until every active follower on that provider is running a current Copier EA build.
Start Testing Today
Sandbox is an integrator-tier feature: it is set on a child provider through the integrator API, not toggled from the standard provider dashboard. If you're building on CopyBridge, start at the developers page for keys and the endpoint reference. If you need a sandbox provider provisioned, that runs through the white-label program.
Full API reference: CopyBridge Docs. Questions about going production? Email support. Building a custom integration? Explore our white-label program — seat-based pricing, priority support.