Skip to main content
Simulation endpoints are available only outside production. Use them to test integration behavior without moving real funds.
Simulated withdrawals are sandbox records for integration testing and never move funds. Production Partner API withdrawal quote and submit calls use the signed request flow described in Withdrawals.

How To Use Simulation Safely

Simulation is for exercising your client behavior:
  • deposit credit handling
  • transaction timeline reconciliation
  • failed or pending record handling
  • KYB status rendering and automatic approval in development/staging
  • notification rendering and delivery tests
Do not reuse simulation payloads as production assumptions. Production money movement can have additional timing and review states.

Choose the Test Account

For user-targeted simulations, a valid API key or session cookie identifies the account, so you can omit user_id. Without credentials, include user_id as in the examples below. Replace the example UUID with your staging account user ID. If you provide both credentials and user_id, the ID must match the authenticated account. Invalid credentials are rejected instead of falling back to the supplied ID. If you send both an API key and a session cookie, they must identify the same account. Signed API keys also require their normal request-signature headers. For example, using an authenticated staging session cookie:
Set STABYL_SESSION_COOKIE to the session cookie header value from your staging login. The deposit targets that authenticated account.

Automatic KYB Approval

Every user is automatically KYB-approved in development and staging, including login responses, KYB status, and REST/WebSocket trading admission. You do not need to call the KYB simulator to start trading in these environments. This automatic approval does not change saved KYB applicant records. Simulating pending or rejected can test status rendering, but does not block admission in development or staging. Production still requires completed KYB. Simulated withdrawals run through the real balance check, so simulate a deposit into the same wallet first or the withdrawal returns 402 INSUFFICIENT_BALANCE.

Example Stablecoin Deposit Simulation

After creating a simulated deposit, verify that your reconciliation process upserts the resulting wallet transaction by transaction ID. Simulation records do not replace testing a staging workflow that produces the webhook events your integration subscribes to.

Example Fiat Deposit Simulation

Example Fiat Withdrawal Simulation

Example Stablecoin Withdrawal Simulation

Withdrawal simulations create non-production transaction records. They do not perform a payout and must not be used to infer production timing or finality.

cNGN Simulation (Development Only)

Use the crypto endpoints with chain: "evm" and symbol: "CNGN" for a deposit, or currency: "CNGN" for a withdrawal. The simulator selects Base. cNGN simulation returns 403 in staging and production and 400 for other chains.
POST this to your development API’s /v1/simulate/crypto/deposits. With the initial 2 bps fee, it credits NGN 99,980 to the existing NGN wallet. Reusing the same cNGN deposit key and payload returns the original transaction and frozen fee; changing the amount with that key is rejected. Conversion capacity also applies in development. Credit can include funds in locked while capacity is exhausted. Use the pool and conversion endpoints in the NGN guide to check the result. To withdraw, POST the following to /v1/simulate/crypto/withdrawals:
At 2 bps, a withdrawal funded entirely by ordinary NGN debits NGN 1,000.20. The restricted portion of a CNGN return has no withdrawal fee. The simulated withdrawal completes asynchronously without sending an on-chain payout. Fees use the configured cNGN policy; the NGN wallet must cover principal plus fees. Simulation works while live cNGN routes are disabled.

Test the normal wallet flow with custom cNGN fees

In development, GET /v1/wallets/chains?currency=NGN and the /v1/partner/wallets/chains alias expose an enabled cNGN Base route. Include the user’s session cookie to see their effective deposit_fee_bps, withdrawal_fee_bps, and minimum_deposit_amount; anonymous requests show the global defaults. Ask your Stabyl administrator to configure custom deposit and withdrawal rates for the test user. Use the existing POST /v1/simulate/crypto/deposits endpoint above with symbol: "CNGN" and chain: "evm" to fund the user’s NGN test balance. Simulation does not require a deposit-address request. The existing wallet and Partner address APIs keep their current parameters and behavior. Then use the signed Partner withdrawal quote and submission APIs with currency: "NGN", settlement_rail: "CNGN", and a Base EVM destination. The quote is available in development subject to balance and account limits; submission debits principal plus the applicable fee and completes asynchronously. The normal idempotency and authentication requirements still apply. No on-chain transfer occurs, including after retries. Staging and production do not automatically enable this development flow. For example, a 100,000 cNGN simulated deposit at 3 bps credits 99,970 NGN. A 100,000 NGN withdrawal funded entirely by ordinary NGN at 7 bps requires 100,070 NGN and delivers 100,000 simulated cNGN. Fund enough to cover both fees when testing a round trip. Restricted returns use the zero-fee treatment above.

Match crypto simulations by transaction hash

All simulated crypto deposits and withdrawals accept an optional blockchain_tx_hash. Supply the hash you need to match in your integration, or omit it to receive a generated synthetic hash. For example, to match a cNGN deposit to a HyperFX fill, use the fill’s transaction hash:
The simulation response returns data.blockchain_tx_hash. Once the transaction completes, the same value appears in transaction detail at data.settlement_details.blockchain_tx_hash and in the transaction webhook at data.transaction.settlement_details.blockchain_tx_hash. Supplied hashes retain their exact spelling, including letter case. These are test identifiers; no on-chain transaction is submitted or verified. Send the same idempotency_key and request body when retrying. The transaction ID and hash remain stable; changing a supplied hash with the same key is rejected. A deposit retry may omit its previously supplied hash and still returns the original hash. Without an idempotency key, each request creates a new simulation. Invalid hashes return 400 before money movement. These fields apply to USDT, USDC, and cNGN simulations on their supported chains. Existing environment restrictions still apply: cNGN is development-only, and all simulation endpoints are disabled in production.

Field Notes

  • Fiat deposits accept currency: "NGN" only. Stablecoin withdrawals accept currency of USDT or USDC, plus CNGN in development. Other values return 400.
  • The stablecoin deposit request names the asset with symbol; the stablecoin withdrawal request uses currency.
  • Both deposit simulations and crypto withdrawals accept an optional idempotency_key. Fiat withdrawals generate their own key.
  • The fiat deposit response returns the new record as transaction_id; the stablecoin deposit response returns it as id.

Example KYB Status Simulation

status is one of approved, rejected, or pending. The response echoes user_id and status and adds decision, one of approved, denied, or unknown, derived from the stored simulated status. This fixture decision does not override automatic KYB admission in development/staging.

Required Headers

Simulation endpoints are public in non-production environments. Send Content-Type: application/json for JSON request bodies. Optionally send X-Api-Key or a session cookie to infer the target account instead of supplying user_id. Signed keys must also include their request-signature headers.

Common Failures

Use simulation responses to verify your reconciliation and notification handling before production access.