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
Choose the Test Account
For user-targeted simulations, a valid API key or session cookie identifies the account, so you can omituser_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:
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. Simulatingpending 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
Example Fiat Deposit Simulation
Example Fiat Withdrawal Simulation
Example Stablecoin Withdrawal Simulation
cNGN Simulation (Development Only)
Use the crypto endpoints withchain: "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.
/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:
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 optionalblockchain_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:
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 acceptcurrencyofUSDTorUSDC, plusCNGNin development. Other values return400. - The stablecoin deposit request names the asset with
symbol; the stablecoin withdrawal request usescurrency. - 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 asid.
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. SendContent-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.