Hosts and auth
| Sandbox host | https://api.sandbox.conduit.financial |
| Production host | https://api.conduit.financial |
| Auth header | x-api-key: ck_sandbox_... or ck_live_... |
| Idempotency header | idempotency-key: <uuid> (required on every money-moving POST; replays for 30 days) |
Address format
- EVM: all-lowercase OR a correct EIP-55 checksum.
- Tron / Solana: Base58 verbatim.
Scenario suffixes
| Suffix | Chain | Forces | Observable on |
|---|---|---|---|
12517C00 | EVM, Tron, Solana | Wallet screening returns elevated risk score (below rejection threshold) | Withdrawal proceeds; status: completed (elevated-risk classification recorded for audit) |
503CA110 | EVM, Tron, Solana | Travel Rule provider temporarily unavailable | Withdrawal stays in status: processing while the Travel Rule provider retries run out, then fails pre-broadcast; status: failed, no failureCode |
5A4070ED | EVM, Tron, Solana | Wallet screening matches sanctions list | Withdrawal holds for a compliance decision; status: pending. Same reject-only exit as 5A4D4EE5. |
5A4D4E51 | EVM, Tron, Solana | compliance check returns elevated risk (routes as approved at medium threshold) | Withdrawal proceeds; status: completed |
5A4D4E5A | EVM, Tron, Solana | compliance check flags sanctions match | Withdrawal holds for a compliance decision; status: pending. Same reject-only exit as 5A4D4EE5. |
5A4D4E9E | EVM, Tron, Solana | compliance check passes but holds for manual review | Withdrawal pauses for compliance review; status: pending. Resolve via POST /v2/sandbox/transactions/:id/simulate/compliance-decision (approve → proceeds; reject → rejected). |
5A4D4EAA | EVM, Tron, Solana | compliance check passes (approved) | Withdrawal proceeds; status: completed |
5A4D4EE5 | EVM, Tron, Solana | compliance check fails (high-risk rejection) | Withdrawal holds for a compliance decision; status: pending. Reject it via POST /v2/sandbox/transactions/:id/simulate/compliance-decision to fail it (failureCode: compliance_review_rejected); approve is not available on an already-rejected review. |
5A4ED0DD | EVM, Tron, Solana | Travel Rule record created in a non-sendable state | Withdrawal fails pre-broadcast; status: failed, failureCode: travel_rule_rejected |
5A50AB1E | EVM, Tron, Solana | Wallet screening identifies destination as a known exchange | Travel Rule flow triggered; withdrawal proceeds if TR passes |
5E1F0577 | EVM, Tron, Solana | Wallet screening identifies destination as self-hosted | Travel Rule skipped; withdrawal proceeds normally |
94000000 | Fiat | Fiat withdrawal completes successfully | Withdrawal completed; status: completed |
94009001 | Fiat | Rail policy rejects (amount limit, frequency cap, or recipient restriction) | Withdrawal fails; status: failed, failureCode: rail_policy_rejected |
94009002 | Fiat | Insufficient funds at settlement (funds available at reservation) | Withdrawal fails; status: failed, failureCode: insufficient_funds_at_settle |
94009003 | Fiat | No viable rail available for the corridor | Withdrawal fails; status: failed, failureCode: rail_unavailable |
94009004 | Fiat | Bank timeout; settlement remains unknown | Withdrawal stays in progress with funds reserved; resolve through simulate/settled |
95000000 | Fiat | compliance check passes for inbound fiat deposit | Deposit credited; status: completed |
95009001 | Fiat | compliance check fails for inbound fiat deposit | Deposit holds for a compliance decision; status: pending. Reject it via POST /v2/sandbox/transactions/:id/simulate/compliance-decision to freeze (failureCode: compliance_hold); approve is not available on an already-rejected review. |
95009002 | Fiat | compliance check flags sanctions match on inbound fiat deposit | Deposit holds for a compliance decision; status: pending. Same reject-only exit as 95009001. |
95009003 | Fiat | compliance check returns elevated risk on inbound fiat deposit (routes as approved) | Deposit credited; status: completed |
AC6BC0DE | EVM, Tron, Solana | Receiving institution acknowledges transfer (informational only) | Withdrawal proceeds; status: completed |
ACCEEDED | EVM, Tron, Solana | Receiving institution accepts transfer (informational under FATF Rec. 16) | Withdrawal proceeds; status: completed |
BAD6A1A4 | EVM, Tron, Solana | Receiving institution rejects transfer | Pre-broadcast: status: failed, failureCode: travel_rule_rejected. Post-broadcast: withdrawal completes (on-chain transfer cannot be reversed). |
BAD7E517 | EVM, Tron, Solana | Travel Rule pre-send validation rejects the transfer | Withdrawal fails pre-broadcast; status: failed, failureCode: travel_rule_rejected |
D15CCAD0 | EVM, Tron, Solana | Wallet attestation conflict: customer attests the destination is their own wallet but screening identifies a VASP | Withdrawal fails; status: failed, failureCode: travel_rule_rejected |
DA171465 | EVM, Tron, Solana | Receiving institution requests additional information; auto-resolves to accepted | Withdrawal proceeds; Travel Rule row transitions to accepted post-broadcast. status: completed |
DE5E11F1 | EVM, Tron, Solana | Deposit parked at sender-info gate; auto-pilot fires deadline | Deposit paused; customer clears via POST /v2/sandbox/customers/:customerId/deposits/:depositId/simulate/sender-info |
DEAA49F1 | EVM, Tron, Solana | compliance check passes for inbound crypto deposit | Deposit credited; status: completed |
DEAA5A4D | EVM, Tron, Solana | compliance check flags sanctions match on inbound crypto deposit | Deposit holds for a compliance decision; status: pending. Same reject-only exit as DEAA8E51. |
DEAA8157 | EVM, Tron, Solana | compliance check returns elevated risk on inbound crypto deposit (routes as approved) | Deposit credited; status: completed |
DEAA8E51 | EVM, Tron, Solana | compliance check fails for inbound crypto deposit | Deposit holds for a compliance decision; status: pending. Reject it via POST /v2/sandbox/transactions/:id/simulate/compliance-decision to freeze (failureCode: compliance_hold); approve is not available on an already-rejected review. |
DEAA9E9E | EVM, Tron, Solana | compliance check passes but holds for manual review on inbound crypto deposit | Deposit pauses for compliance review; status: pending. Resolve via POST /v2/sandbox/transactions/:id/simulate/compliance-decision (approve → credited; reject → frozen). |
DEC11A1D | EVM, Tron, Solana | Receiving institution declines transfer | Pre-broadcast: status: failed, failureCode: travel_rule_rejected. Post-broadcast: withdrawal completes. |
Simulate endpoints
Signing simulators don’t apply on the sandbox. Crypto signs for real here, so
payouts/:id/simulate/cosign, orders/:id/simulate/cosign, payouts/:id/simulate-stamp, wallet-signers/:signerId/mark-enrolled, verifications/:token/simulate/ceremony-stamp and customers/:customerId/wallet-ceremonies/simulate-approval-gate return 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE. Sign with a real passkey, or a machine stamp at POST /v2/signing-requests/:id/approve — see Use a real testnet and Machine-signer stamping. A wallet provisioned before real testnet was enabled is refused with 422 LEGACY_MOCK_WALLET_UNSUPPORTED.| Endpoint | Drives | Body | Response | Errors |
|---|---|---|---|---|
POST /v2/sandbox/applications/:id/simulate/decision | Application -> APPROVED or REJECTED | { outcome: "approved" | "rejected", category?, field?, reason? } | 200 | APPLICATION_NOT_FOUND, REJECTION_CATEGORY_NOT_APPLICABLE |
POST /v2/sandbox/customers/:customerId/virtual-accounts/:virtualAccountId/deposits/simulate | Accepts a new fiat deposit for ingestion; outcome steers compliance branch. Returns — poll GET /v2/transactions?externalReference= | { outcome: "completed" | "frozen" | "returned" (default completed), assetAmount, senderInfo?, detectedAt?, externalReference?, reason? } | 202 | VALIDATION_ERROR, NOT_FOUND |
POST /v2/sandbox/customers/:customerId/deposits/:depositId/simulate/sender-info | Deposit’s sender-info gate -> RESOLVED | { senderInfo } | 200 | SANDBOX_SENDER_INFO_NOT_REQUIRED, NOT_FOUND |
POST /v2/sandbox/transactions/:id/simulate/terminal | Transaction -> COMPLETED or FAILED | { outcome: "completed" | "failed", utr?, reason? } | 200 | SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY, RESOURCE_TERMINAL, NOT_FOUND |
POST /v2/sandbox/transactions/:id/simulate/compliance-decision | Transaction parked for compliance review -> resumes (approve) or terminalizes at the type default (reject: deposit -> frozen, withdrawal -> rejected). Once rejected, approve is no longer available — a rejected case can only be terminalized via reject. | { outcome: "approve" | "reject" } | 202 | TRANSACTION_NOT_FOUND, VALIDATION_ERROR, CONFLICT |
POST /v2/sandbox/wallets/registered-addresses/:id/simulate/compliance-decision | Registered address parked pending_screening (0x999 review magic value) -> registered + deposits from the address that were awaiting registration resume (approve) or suspended as sanctions-blocked (reject); same decision replays 200, a conflicting one is 409 | { outcome: "approve" | "reject" } | 200 | REGISTERED_ADDRESS_NOT_FOUND, REGISTERED_ADDRESS_INVALID_TRANSITION, VALIDATION_ERROR |
POST /v2/sandbox/payouts/:id/simulate/confirm | Crypto payout -> chain-confirm | { outcome: "completed" | "failed", txHash?, reason? } (txHash required when outcome="completed") | 200 | PAYOUT_NOT_FOUND, SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY, RESOURCE_TERMINAL |
POST /v2/sandbox/payouts/:id/simulate/settled | Fiat payout -> rail settlement | { outcome: "completed" | "failed", utr?, reason? } | 200 | PAYOUT_NOT_FOUND, SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY, RESOURCE_TERMINAL |
POST /v2/sandbox/payouts/:id/simulate/counterparty-webhook | Travel-Rule counterparty resolution | { outcome: "acknowledged" | "approved" | "rejected" | "declined", reason? } | 200 | RESOURCE_TERMINAL, NOT_FOUND |
POST /v2/sandbox/payouts/:id/simulate/cosign | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the sandbox signs on a real testnet, so a synthesized approval would carry a signature no chain accepts. Approve with a real passkey on the verificationUrl from transaction.awaiting_signature, or a machine stamp at POST /v2/signing-requests/:id/approve | { outcome: "approved" | "declined", reason? } | 409 | PAYOUT_NOT_FOUND, RESOURCE_TERMINAL, NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/payouts/:id/simulate-review-approve | Payout review (document gate or compliance hold) -> released; payout resumes | {} | 200 | PAYOUT_NOT_FOUND, CONFLICT, RESOURCE_TERMINAL |
POST /v2/sandbox/payouts/:id/simulate-review-reject | Payout review (document gate or compliance hold) -> rejected; funds returned | {} | 200 | PAYOUT_NOT_FOUND, CONFLICT, RESOURCE_TERMINAL |
POST /v2/sandbox/payouts/:id/simulate-stamp | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the sandbox signs on a real testnet, so a synthesized approval would carry a signature no chain accepts. Each signer approves with a real passkey on the verificationUrl from transaction.awaiting_signature, or a machine stamp at POST /v2/signing-requests/:id/approve | { walletSignerId, outcome: "approved" | "declined" (default approved) } | 409 | PAYOUT_NOT_FOUND, NOT_IN_AWAITING_SIGNATURE, SIGNER_NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/wallet-signers/:signerId/mark-enrolled | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: a signer enrolled this way has no passkey and could never approve a payout. Enroll through the verificationUrl on wallet_signer.invited, or claim with a machine-signer roster | {} | 409 | SIGNER_NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/verifications/:token/simulate/ceremony-stamp | A call on a pending ceremony returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the signing provider releases a parked ceremony only on a real administrator’s passkey. An admin approves on the adminVerificationUrl | { outcome?: "approved" | "declined" (default approved) } | 409 | VERIFICATION_NOT_FOUND, VERIFICATION_TOKEN_INVALID, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/customers/:customerId/wallet-ceremonies/simulate-approval-gate | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the signing provider applies its own approval policy, and a parked ceremony is released only on a real administrator’s passkey on the adminVerificationUrl | { target: "signer_add" | "signer_remove" | "passkey_enrollment", requireApproval: boolean } | 409 | PROVIDER_ACCOUNT_NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/customers/:customerId/wallets/:walletId/simulate/setup-stamp | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the sandbox signs on a real testnet, so a synthesized approval would carry a signature no chain accepts. Each signer approves the Stellar wallet setup with a real passkey on the verificationUrl from wallet.awaiting_setup_signature, or a machine stamp at POST /v2/signing-requests/:id/approve | { outcome: "approved" | "declined", signerId? } | 409 | WALLET_NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/customers/:customerId/simulate-reset-claim | Single-shot reset of a customer’s wallet claim. Removes every signer, every wallet, and the crypto-wallet feature flag, so the next claim-non-custodial starts fresh. Refuses with 409 CLAIM_RESET_BLOCKED if any row still references this customer’s wallet setup. A reset cannot delete a record that still references this setup; on a non-custodial account, add or remove a signer on the roster to change who signs, which keeps the wallets and their deposit addresses. | {} | 200 | PROVIDER_ACCOUNT_NOT_FOUND, CLAIM_RESET_BLOCKED |
PATCH /v2/sandbox/customers/:customerId/house-account | Marks (or unmarks) one of your business customers as a house account — the only source a purpose: prefunding payout accepts. Every sandbox organization is seeded with one house account already; use this to prefund from a customer you onboarded yourself. On live, only Conduit can set the marker. | { isHouseAccount: boolean } | 200 | CUSTOMER_NOT_FOUND, HOUSE_ACCOUNT_BUSINESS_ONLY |
POST /v2/sandbox/orders/:id/simulate/rate-lock-expired | Order -> rate-lock-expired cancellation (about 1s) | {} | 200 | NOT_FOUND |
POST /v2/sandbox/orders/:id/simulate/conversion-failed | Order -> conversion-failed terminal | { reason? } | 200 | NOT_FOUND |
POST /v2/sandbox/orders/:orderId/deposits/simulate/compliance-decision | The compliance review holding a transfer into the order’s funding address -> resolved. approve releases it to fund the order; reject holds the funds permanently and the order goes unfunded | { outcome: "approve" | "reject" } | 202 | ORDER_NOT_FOUND, SANDBOX_ORDER_NOT_DEPOSIT_FUNDED, SANDBOX_ORDER_NO_PARKED_FUNDING, CONFLICT |
POST /v2/sandbox/orders/:id/simulate/cosign | Returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE: the sandbox signs on a real testnet, so a synthesized approval would carry a signature no chain accepts. Approve the source leg with a real passkey on the verificationUrl from transaction.awaiting_signature, or a machine stamp at POST /v2/signing-requests/:id/approve | { outcome: "approved" | "declined", signerId? } | 409 | ORDER_NOT_FOUND, NOT_IN_AWAITING_SIGNATURE, SIGNER_NOT_FOUND, SANDBOX_SIGNING_SIMULATION_UNAVAILABLE |
POST /v2/sandbox/whitelist-recipients/:id/simulate-approve | Whitelist recipient PENDING_REVIEW -> REGISTERED | {} | 200 | WHITELIST_RECIPIENT_NOT_FOUND, WHITELIST_INVALID_TRANSITION |
POST /v2/sandbox/whitelist-recipients/:id/simulate-reject | Whitelist recipient PENDING_REVIEW -> REJECTED | {} | 200 | WHITELIST_RECIPIENT_NOT_FOUND, WHITELIST_INVALID_TRANSITION |
Index by entity
| If you have a… | You can call… |
|---|---|
app_... (application) | POST /v2/sandbox/applications/:id/simulate/decision |
cus_... (customer) | PATCH /v2/sandbox/customers/:customerId/house-account (mark it as a prefunding source), POST /v2/sandbox/customers/:customerId/simulate-reset-claim |
vac_... (virtual account) | POST /v2/sandbox/customers/:customerId/virtual-accounts/:virtualAccountId/deposits/simulate |
wra_... (registered address) | POST /v2/sandbox/wallets/registered-addresses/:id/simulate/compliance-decision (when parked pending_screening via the 0x999 review magic value) |
dep_... (deposit) | POST /v2/sandbox/customers/:customerId/deposits/:depositId/simulate/sender-info |
txn_... (transaction / payout) | POST /v2/sandbox/transactions/:id/simulate/terminal; payouts also: .../payouts/:id/simulate/settled, .../simulate/counterparty-webhook, .../simulate-review-approve, .../simulate-review-reject |
ord_... (order) | POST /v2/sandbox/orders/:id/simulate/rate-lock-expired, .../simulate/conversion-failed, .../simulate/cosign (non-custodial conversion/offramp source leg), .../deposits/simulate/compliance-decision (deposit-funded orders — an order created with no source) |
Index by lifecycle state
Crypto signs and settles for real. At
pending_cosign, approve with a real passkey or a machine stamp at POST /v2/signing-requests/:id/approve; at broadcasting, wait for real on-chain finality (minutes). simulate/confirm returns 422 SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY on a crypto payout: there is no finality override. See Use a real testnet.| Payout state | What you can call |
|---|---|
pending_cosign | Approve for real (passkey, or POST /v2/signing-requests/:id/approve). simulate/counterparty-webhook drives a Travel Rule pre-broadcast reject. |
| parked at a review (a document the policy requires, or a compliance hold) | simulate-review-approve to release the payout, or simulate-review-reject to terminate it as failed (reserved funds returned). One pair of levers resolves whichever review holds the payout, because a payout never reports which review that is. transaction.under_review is the event that tells you a review opened. |
broadcasting | Wait for real on-chain finality (minutes) — no override. |
completed / failed | nothing; the review levers return 200 with the payout at the state it reached, while terminal-aware simulation levers return 409 RESOURCE_TERMINAL. See RESOURCE_TERMINAL playbook. |
| Deposit state | What you can call |
|---|---|
| (parked at sender-info gate) | simulate/sender-info |
terminal (completed / frozen / returned) | nothing; outcome was set at ingestion time |
| Order state | What you can call |
|---|---|
pending (rate-lock window open) | simulate/rate-lock-expired (cancels within ~1s) |
| any pre-terminal state with a conversion leg | simulate/conversion-failed |
| any state, deposit-funded orders only | Send real testnet funds from a registered address to the order’s funding address; see Deposit-Funded Orders. |
| deposit-funded orders, transfer held for review | deposits/simulate/compliance-decision {outcome: "approve" | "reject"} — the order identifies which funding transfer to resolve. 404 SANDBOX_ORDER_NO_PARKED_FUNDING when nothing is held. |
| Application state | What you can call |
|---|---|
pending | simulate/decision {outcome: "approved" | "rejected"} |
cancelled | simulate/decision {outcome: "approved" | "rejected"} — recovers an application whose prior simulate call cancelled its workflow but failed to write its own terminal status |
Index by error code
| If you got… | The call that produced it… |
|---|---|
RESOURCE_TERMINAL (409) | A terminal-aware simulate/* call against a terminal entity. The review levers instead return 200 with the payout at the state it reached. See playbook. |
SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY (422) | simulate/terminal, simulate/settled or simulate/confirm against a payout parked at a review (call simulate-review-approve first); also simulate/terminal with outcome: "completed" before a fiat route is selected, or on an onramp/offramp before its delivery has completed; also simulate/terminal or simulate/confirm against a payout in an in-progress phase with no transfer reference the simulation can drive yet (retry; read the transaction if it keeps refusing). See playbook. |
APPLICATION_NOT_FOUND (404) | simulate/decision when the application ID does not exist or does not belong to the org. |
REJECTION_CATEGORY_NOT_APPLICABLE (422) | simulate/decision with a category field on a non-KYB application. |
SANDBOX_SENDER_INFO_NOT_REQUIRED (409) | simulate/sender-info against a deposit not parked at the sender-info gate. |
Public failure codes
| Code | Terminal state | Channel | Description | Playbook |
|---|---|---|---|---|
chain_broadcast_failed | failed | webhook + polled | The signed payout could not be broadcast to the chain before reaching finality; no funds left the wallet | Playbook |
compliance_hold | failed | webhook + polled | Compliance review held the funds; manual remediation required | Playbook |
compliance_rejected | failed | webhook + polled | A compliance reviewer rejected the payout’s supporting documentation; reserved funds were returned (fires transaction.rejected, not transaction.failed) | Playbook |
compliance_review_rejected | failed | webhook + polled | Transaction rejected in regulatory compliance review; non-retryable | Playbook |
crypto_wallet_misconfigured | failed | webhook + polled | The source wallet is missing required signing configuration; the payout could not be signed | Playbook |
insufficient_funds | failed | webhook + polled | Source balance was insufficient to reserve the payout before broadcast; no funds moved | Playbook |
insufficient_funds_at_settle | failed | webhook + polled | Source funds were insufficient at the settlement attempt | Playbook |
insufficient_onchain_balance | failed | webhook + polled | The source wallet has insufficient real on-chain balance for the send, so the transfer could not be broadcast; no funds moved. Fund the wallet with real testnet crypto via an onramp or a faucet, then retry | Playbook |
provider_rejected | failed | webhook + polled | The crypto outbound provider declined the broadcast request before the transaction was submitted to the chain | Playbook |
rail_policy_rejected | failed | webhook + polled | The receiving rail rejected the payment per its policy | Playbook |
rail_unavailable | failed | webhook + polled | The chosen rail was temporarily unavailable | Playbook |
returned_by_sender | failed | webhook + polled | The inbound transfer was returned by the originating institution before it could be credited | Playbook |
roster_changed | failed | webhook + polled | A signer on the customer’s roster was removed (or demoted out of the signing pool) while the payout was awaiting signatures; the half-collected stamps were voided so the fintech can re-initiate | Playbook |
sender_info_timeout | failed | webhook + polled | Sender-information gate expired before resolution | Playbook |
source_account_unavailable | failed | webhook + polled | The source balance is held on a bank account that cannot move funds now, because the account is not active (for example suspended, closed, or still in approval); no funds moved. Contact support to make the balance available on an active account, then submit a new order | Playbook |
travel_rule_rejected | failed | webhook + polled | Counterparty rejected the Travel Rule request, or Travel Rule validation failed pre-broadcast | Playbook |
user_signature_declined | failed | webhook + polled | End user explicitly declined to sign | Playbook |
user_signature_expired | failed | webhook + polled | End user did not sign across the allowed signing windows; the request expired | Playbook |
user_signature_rejected_by_provider | failed | webhook + polled | Signing provider rejected the signature payload | Playbook |
user_signature_timeout | failed | webhook + polled | Payout timed out waiting in the wallet’s signing queue before it could start collecting signatures | Playbook |
Sandbox simulate endpoint errors
These codes are returned as HTTP errors by sandbox simulate endpoints. They are notfailureCode values on transactions.
| Code | HTTP status | Description | Playbook |
|---|---|---|---|
INVALID_ADDRESS_FORMAT | 400 | EVM address must be all-lowercase or a correct EIP-55 checksum | Playbook |
RESOURCE_TERMINAL | 409 | Tried to drive a simulate against an already-terminal entity | Playbook |
SANDBOX_SIGNING_SIMULATION_UNAVAILABLE | 409 | Called a signing simulator (simulate/cosign, simulate-stamp, ceremony-stamp, simulate-approval-gate, or mark-enrolled) on a sandbox that produces real signatures. Enroll a signer through the invite verificationUrl, approve a payout with a real passkey or a machine-signer stamp, and approve a parked ceremony with an administrator’s passkey on the adminVerificationUrl. Chain finality is not simulated either — wait for real on-chain confirmation | Playbook |
SANDBOX_TRANSACTION_NOT_FORCE_TERMINAL_READY | 422 | Called a sandbox simulate endpoint whose requested outcome is not viable in the transaction’s current phase (e.g. simulate/terminal, simulate/settled or simulate/confirm against a payout parked at the document-review gate, simulate/terminal with outcome:completed before a fiat route is selected, on an onramp/offramp before its delivery has completed, or simulate/terminal or simulate/confirm against a payout in an in-progress phase with no transfer reference the simulation can drive yet) | Playbook |
HTTP status code legend
| Code | Meaning |
|---|---|
| 200 | Mutation succeeded; resource returned |
| 202 | Accepted; work is in flight — see the route’s row for what comes back |
| 400 | Validation error; check the pointer in the response |
| 401 | Missing or invalid API key |
| 403 | API key lacks permission |
| 404 | Resource not found |
| 409 | Conflict; inspect type for the precise error |
| 429 | Rate limited |
| 500 | Server error |
Webhook event topics (most common)
application.approved/application.rejectedtransaction.created/transaction.completed/transaction.failed/transaction.cancelledtransaction.awaiting_sender_informationorder.failedcustomer.activatedvirtual_account.activated