Sandbox Philosophy
Dakota’s sandbox runs real crypto custody on testnets and mocks the banking layer. Wallets sign and broadcast real testnet transactions; the policy engine runs unmodified. Fiat rails (ACH, Fedwire) are mocked. What that means per flow:- Onramp —
POST /sandbox/simulate/inboundmocks the USD deposit. The follow-on stablecoin transfer to the Destination is a real testnet transaction. - Offramp — send real testnet crypto to the offramp’s
source_crypto_address. The on-chain inbound is real; the USD outbound to the bank Destination is mocked. - Swap — fully on-chain on testnets, end to end.
POST /sandbox/simulate/onboarding instead of waiting for real compliance review.
- Base URL:
https://api.platform.sandbox.dakota.xyz - Dashboard:
https://platform.sandbox.dakota.xyz - API keys: Base64-encoded strings, generated from the dashboard.
Sandbox Restrictions
Two safeguards run on every object-create request in sandbox to prevent accidental mainnet activity and unbounded test spend.Network Restriction
Object-create endpoints —POST /customers/{id}/recipients, POST /recipients/{id}/destinations, POST /accounts, and POST /transactions/one-off — reject mainnet networks in sandbox and reject testnet networks in production. The evm wildcard is allowed in every environment.
A request that violates the rule returns
400 Bad Request. Use the testnet equivalent for the chain you’re targeting.
Amount Cap
Per-transaction amounts in sandbox are capped at $2 USD per request. The cap applies to USD, USDC, and RD (all treated 1:1 to USD). USDT is not supported in sandbox at the moment — it will be enabled in a near-future release. Production has no cap and supports the full asset set. The cap applies at:POST /transactions/one-off— theamountfield. Rejected synchronously with400 Bad Request.POST /sandbox/simulate/inbound— theamountfield. Rejected synchronously with400 Bad Request.- Auto-account inbound deposits — when a sandbox crypto deposit lands on an auto-account’s source address and the converted USD value exceeds the cap, the auto-account transaction is created and then transitioned to
failedwith afailure_reasonindicating the cap was exceeded. The failure surfaces via the standardtransaction.auto.updatedwebhook (and onGET /auto-transactions/{id}); there is no synchronous rejection because the deposit has already settled on-chain.
"1.00", "2.00") in your sandbox test fixtures.
Simulation Endpoints
Simulate an Inbound Payment
POST /sandbox/simulate/inbound injects an inbound USD payment event (ACH or Fedwire) against an onramp account, mocking what would normally arrive from a real bank wire. The call is accepted synchronously; webhook callbacks fire asynchronously and match the production event shape exactly. Crypto deposits aren’t simulated — send real testnet crypto to the offramp/swap/one-off source_crypto_address directly.
type—ach_inboundorwire_inboundfor USD rails.account_id— required forach_inboundandwire_inbound. Use the onramp account ID.scenario—success_immediate(default) orsuccess_delayedwith adelay_secondsfield.simulation_id— your idempotency key for the simulation. Repeating the call with the same ID and identical params returns the original response; conflicting params return409.
Simulate an Onboarding Transition
POST /sandbox/simulate/onboarding drives KYB or KYC application status through a sandbox transition without waiting for real compliance review.
type values:
Full schema: Simulate an Onboarding State Transition.
Tracking Simulation State
Stateful scenarios (e.g.compliance_hold, manual_review, unconfirmed) pause partway through the lifecycle and wait for an explicit advance call:
GET /sandbox/simulations/{simulation_id}— returns current state and the callback delivery history.POST /sandbox/simulations/{simulation_id}/advance— unpauses with actionrelease,reject,approve, etc. (valid actions vary per scenario).
Sandbox Behavior Control Headers
Sandbox accepts a small set of HTTP request headers that override the default success path on a per-request basis. They let you exercise error branches and edge cases without contriving the upstream conditions. These headers are sandbox-only — they have no effect againstapi.platform.dakota.xyz. They are also intentionally not part of the OpenAPI spec; this section is the canonical reference.
Available Headers
X-Sandbox-Error-Status, X-Sandbox-Error-Message, and X-Sandbox-Error-Step work together — set all three to inject a custom error at a specific pipeline step. X-Sandbox-Scenario is the higher-level alternative: pick a named scenario and the platform fills in step, status, and message for you.
Scenarios
Valid values for theX-Sandbox-Scenario header. The same list is also available programmatically via GET /sandbox/scenarios.
TRM Compliance Mock Patterns
Sandbox runs a mock TRM Labs compliance client that returns deterministic risk classifications based on patterns in the address being screened. This lets you exercise high-risk and manual-review code paths without sourcing real flagged wallets.compliance_block scenario (set via X-Sandbox-Scenario) overrides the address-pattern logic and forces a RiskLevelCritical blocked response on every screening call — useful when you want to test the blocked-transaction branch without crafting a specific address.
Webhook Testing
Sandbox webhooks fire from the same delivery pipeline as production — same envelope, same signing key derivation, same retry behaviour. UseX-Dakota-Event-ID for idempotency and verify signatures the same way you will in production. See Webhooks for the full reference.
ngrok for Local Development
Webhook.site for Quick Testing
- Visit
https://webhook.siteand copy the unique URL. - Register it as a webhook target.
- Trigger a simulation; observe the live deliveries.
Required Headers
Rate Limit Testing
Sandbox enforces the same rate limits as production. Send a burst of read requests to verify your client’s backoff:429 responses once the per-key limit is hit.
Common Issues
HTTP 400 on object create with a *-mainnet network
The sandbox network restriction rejects mainnet network IDs. Use the testnet equivalent (ethereum-sepolia, base-sepolia, etc.) or evm for chain-agnostic destinations.
HTTP 400 on a one-off transaction or simulate inbound with amount > 2.00
The sandbox amount cap rejects per-request amounts above $2 USD. Cap your test fixtures at "1.00" or "2.00".
HTTP 400 on POST requests in general
X-Idempotency-Key is required on every POST request. Generate a fresh UUID per logical request.
Webhooks not received
Confirm your endpoint is publicly reachable, returns2xx within 30 seconds, and has been registered with POST /webhooks/targets. ngrok or webhook.site are the easiest local test loops.
Transactions stuck in processing
UsePOST /sandbox/simulate/inbound to push the lifecycle forward. For paused stateful scenarios, use POST /sandbox/simulations/{id}/advance.
Migration to Production
When you’re ready to switch:-
Update configuration — change the base URL to
https://api.platform.dakota.xyzand replace sandbox API keys with production keys. Update webhook URLs to your production receiver. -
Environment variables
-
Switch network IDs — replace testnet IDs (
*-sepolia,*-amoy,*-devnet) with their mainnet counterparts. Production rejects testnet IDs. - Remove cap-imposed amount limits — the $2 cap is sandbox-only. Use real transaction amounts in production.
- Roll out gradually — start with low-value transactions, monitor error rates, and have a rollback plan.
Next Steps
- Authentication — production security practices.
- Customer Onboarding — production KYB flows.
- Common Flows — onramp, offramp, swap, and wallet flows end-to-end.
- Webhooks — webhook signature verification and event reference.

