What happened
You called asimulate/* endpoint against an entity (a payout, transaction, order, or deposit) that has already reached a terminal state. This returns HTTP 409 with error code RESOURCE_TERMINAL.
The first simulate call wins. Once an entity is terminal (succeeded, failed, or cancelled), no further simulation is possible on that entity.
Common causes
- Replay of a successful simulate call — the simulate call succeeded earlier and you called it again (e.g., a retry loop that did not check the prior response)
- Race between simulate and the mock chain — in sandbox, the mock chain confirms a transfer on its own a few seconds after broadcast; if it confirms before your next simulate call, the entity is already terminal
- Simulate called on an already-terminal entity — the entity reached a terminal state through a different path (e.g., a
simulate/terminalcall or an earlier auto-terminate)
Recovery
1. Re-fetch the entity to see its terminal statefailureCode (for failed states) or status to understand how it reached the terminal state. If a prior simulate call or the mock chain drove it to an unexpected state, that is the root cause to address.
Prevention
- Check the response from each simulate call — treat a 200 response as authoritative; if the entity is already terminal, the response body will show the terminal state
- Do not retry simulate calls in a loop — simulate calls are idempotent at the semantic level: once the entity is terminal, the first call’s outcome stands
- Account for automatic chain confirmation — after approving a cosign, the mock chain confirms the transfer on its own; a follow-up
simulate/confirmcall is only for a customtxHashor a failed outcome
Related endpoints
- GET /v2/payouts/:id — read payout state
- GET /v2/transactions/:id — read transaction state
- GET /v2/orders/:id — read order state
- POST /v2/sandbox/transactions/:id/simulate/terminal — force a transaction terminal (will return RESOURCE_TERMINAL if already done)