Error Response Format
All API errors return a consistent JSON response:
Code
Error Code Convention
Error codes follow the format {domain}-{YZZZ} where:
- domain identifies the resource area (e.g.,
accounts,payments,treasury) - Y indicates the HTTP status category
- ZZZ is the specific error number within that category
| Range | HTTP Status | Meaning |
|---|---|---|
| 1000–1999 | 404 | Not Found |
| 2000–2999 | 401 / 403 | Unauthorized / Forbidden |
| 3000–3999 | 400 | Bad Request |
| 4000–4999 | 429 | Too Many Requests |
| 5000–5999 | 502 / 503 | Bad Gateway / Service Unavailable |
Some domains (Circle, Idempotency) use legacy numbering that does not follow the range convention above.
Accounts
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
accounts-1000 | 404 | Account with id '{id}' not found | The specified account ID does not exist in this workspace |
accounts-1001 | 404 | Entity with id '{id}' not found | The tenant or counterparty specified does not exist |
accounts-2000 | 403 | The entity does not belong to your workspace | User tries to link an account to an entity that belongs to a different workspace |
accounts-3000 | 400 | Cannot provide both tenant_id and counterparty_id | User provides both tenant_id and counterparty_id when only one is allowed |
accounts-3001 | 400 | A workspace-level bank account already exists. Only one is allowed per workspace. | User tries to create a second workspace-level bank account |
accounts-3002 | 400 | wallet_address is required for unmanaged wallets (is_managed=false) | User creates an unmanaged wallet without providing a wallet_address |
accounts-3003 | 400 | Cannot determine network for wallet type '{type}' | The provided wallet type does not map to a known blockchain network |
accounts-3004 | 400 | signature is required for managed wallets (is_managed=true) | User creates a managed wallet without providing the required signature |
accounts-3005 | 400 | Invalid signature format. Expected base64-encoded JSON with body and stamp fields. | The signature parameter could not be decoded or is missing required fields |
accounts-3006 | 400 | Circle Mint ledgers require a tenant_id or counterparty_id. Workspace-level sub-ledgers are not supported. | User tries to create a Circle Mint ledger without linking it to a tenant or counterparty |
accounts-3007 | 400 | This entity already has a Circle Mint ledger. Only one Circle Mint ledger per tenant/counterparty is allowed. | User tries to create a duplicate Circle Mint ledger for the same entity |
accounts-3008 | 400 | A workspace-level Circle Mint master wallet ledger already exists. | User tries to create a second master wallet ledger for the workspace |
accounts-3009 | 400 | CIRCLE_MINT provider requires a tenant_id or counterparty_id | Circle Mint metadata preparation requires an entity to be linked |
accounts-3010 | 400 | CIRCLE_MINT provider requires a business entity (not individual) | Circle Mint only supports business-classified entities, not individuals |
accounts-3011 | 400 | Entity is missing required fields for Circle | The entity does not have all required business fields populated for Circle onboarding |
accounts-3012 | 400 | Cannot create VAN: compliance state is not ACCEPTED | Virtual account number creation requires the account to have ACCEPTED compliance state |
accounts-3013 | 400 | Cannot create VAN: circle_wallet_id is missing from account metadata | The ledger account does not have a Circle wallet ID configured |
accounts-3014 | 400 | No workspace-level bank account found. Please create a bank account first. | A workspace-level bank account is required but none exists |
accounts-3015 | 400 | No wire bank accounts found in Circle. Please register a bank account on Circle dashboard first. | Circle does not have any wire bank accounts registered for this workspace |
accounts-3016 | 400 | Multiple wire bank accounts found in Circle | Production requires exactly one bank account in Circle, but multiple were found |
accounts-3017 | 400 | Could not determine Circle bank ID | Failed to resolve the Circle bank ID needed for wire transfers |
accounts-3018 | 400 | Unsupported provider. Must be one of : CIRCLE_MINT, KRAKEN | The specified provider is not supported for this operation. Must be one of : CIRCLE_MINT, KRAKEN |
accounts-3019 | 400 | Account does not have a provider configured | The account metadata does not contain provider configuration |
accounts-3020 | 400 | Entity type must be 'counterparty' or 'tenant' | The referenced entity is not a valid type for account linking |
accounts-3022 | 400 | Signature body has unexpected activity type '{actual}', expected '{expected}' | The stamped Turnkey activity inside the signature is not the expected CREATE_WALLET activity |
accounts-3023 | 400 | Signature body organizationId does not match the authenticated workspace's Turnkey sub-organization | The caller stamped an activity targeting a sub-organization that does not belong to their workspace |
accounts-3024 | 400 | Signed wallet account addressFormat '{actual}' does not match type '{type}' (expected '{expected}') | The stamped CREATE_WALLET parameters describe an address format that does not match the dto.type |
accounts-3025 | 400 | Managed wallets are only supported for type 'stablecoin_ethereum' (got '{type}') | User attempted to create a managed (is_managed=true) wallet for a non-Ethereum wallet type |
accounts-3100 | 400 | account_name is required and must be between 1-255 characters | User provides an account name that doesn't meet length requirements |
accounts-3101 | 400 | tenant_id must be a valid UUID | User provides a tenant_id that is not a valid UUID |
accounts-3102 | 400 | counterparty_id must be a valid UUID | User provides a counterparty_id that is not a valid UUID |
accounts-3103 | 400 | bank_name is required and must be between 1-255 characters | User provides a bank name that doesn't meet length requirements |
accounts-3104 | 400 | bank_code_type must be one of: SWIFT, BIC, IBAN, ROUTING | User provides a bank_code_type that is not in the allowed enum |
accounts-3105 | 400 | bank_identifier_code is required | User creates a bank account without providing the bank identifier code |
accounts-3106 | 400 | bank_account_number is required | User creates a bank account without providing the account number |
accounts-3107 | 400 | type must be one of: stablecoin_ethereum, stablecoin_solana, stablecoin_stellar | User provides a wallet type that is not in the allowed enum |
accounts-3108 | 400 | wallet_address must be a valid blockchain address for the specified network | User provides a wallet address that doesn't match the expected format for the network |
accounts-3109 | 400 | Wallet signature is malformed or invalid | User provides a signature that is not properly formatted or cannot be verified |
accounts-3110 | 400 | provider must be one of: CIRCLE_MINT, KRAKEN | User provides a provider value that is not in the allowed enum |
accounts-5000 | 502 | Failed to create wallet. Please try again or contact support if the issue persists. | Turnkey or other wallet provider failed during wallet creation |
accounts-5001 | 502 | Failed to create Circle external entity | Circle API call to create the external entity failed |
accounts-5002 | 502 | Unable to create virtual account number (VAN) for this ledger account. | Circle API call to create the virtual account number failed |
accounts-5003 | 502 | Failed to retrieve entity business fields from vault | Basis Theory vault call to retrieve entity fields failed |
Counterparties
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
counterparties-1000 | 404 | Counterparty not found | The specified counterparty ID does not exist |
counterparties-1001 | 404 | Tenant with id '{id}' not found. Cannot assign counterparty to non-existent tenant. | User tries to assign a counterparty to a tenant_id that doesn't exist |
counterparties-2000 | 403 | You do not have access to this counterparty | User tries to access a counterparty that belongs to a different workspace |
counterparties-3002 | 400 | classification must be 'individual' or 'business' | User provides a classification value that is not 'individual' or 'business' |
counterparties-3003 | 400 | business_legal_name is required for business counterparties and must be 1-255 characters | User creates a business counterparty with missing or improperly formatted business_legal_name |
counterparties-3004 | 400 | business_address_country is required for business counterparties and must be a valid ISO 3166-1 alpha-2 country code | User provides a business_address_country that is not a valid 2-letter country code (e.g., "US", "GB") |
counterparties-3005 | 400 | individual_first_name is required for individual counterparties and must be 1-255 characters | User creates an individual counterparty with missing or improperly formatted first name |
counterparties-3006 | 400 | individual_last_name is required for individual counterparties and must be 1-255 characters | User creates an individual counterparty with missing or improperly formatted last name |
counterparties-3007 | 400 | individual_address_country is required for individual counterparties and must be a valid ISO 3166-1 alpha-2 country code | User provides an individual_address_country that is not a valid 2-letter country code |
counterparties-3008 | 400 | individual_date_of_birth must be a valid date in YYYY-MM-DD format | User provides a date_of_birth that doesn't match the required format or is not a valid date |
counterparties-3009 | 400 | tenant_id must be a valid UUID | User provides a tenant_id that is not a validly formatted UUID |
counterparties-3010 | 400 | individual_street_address1 is required for individual counterparties | User creates an individual counterparty without providing the street address |
counterparties-3011 | 400 | individual_city is required for individual counterparties | User creates an individual counterparty without providing the city |
counterparties-3012 | 400 | individual_postal_code is required for individual counterparties | User creates an individual counterparty without providing the postal code |
counterparties-3013 | 400 | business_street_address1 is required for business counterparties | User creates a business counterparty without providing the street address |
counterparties-3014 | 400 | business_city is required for business counterparties | User creates a business counterparty without providing the city |
counterparties-3015 | 400 | business_postal_code is required for business counterparties | User creates a business counterparty without providing the postal code |
Currencies
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
currencies-1000 | 404 | Currency not found | The specified currency code does not exist |
currencies-3000 | 400 | Invalid currency code format | User provides a currency code that is not a valid ISO 4217 format (e.g., USD, EUR, GBP) |
currencies-3001 | 400 | Currency is not supported for this operation | User attempts to use a currency that is valid but not supported for the requested operation |
currencies-3002 | 400 | Invalid currency pair for exchange | User attempts to exchange between currencies where the pair is not supported |
Networks
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
networks-1000 | 404 | Network not found | The specified network identifier does not exist |
networks-3000 | 400 | Invalid network identifier | User provides a network identifier that is not a valid format (e.g., ethereum, polygon, base) |
networks-3001 | 400 | Network is not supported for this operation | User attempts to use a network that is valid but not supported for the requested operation |
networks-3002 | 400 | Currency is not compatible with the specified network | User provides a currency/network combination that is not compatible (e.g., BTC on Ethereum network) |
networks-3003 | 400 | Network is currently unavailable or under maintenance | User attempts to use a network that is temporarily unavailable |
networks-3004 | 400 | Currency is not yet transactable on this network | The requested currency/network pair is supported for balance tracking but transactional flows (deposit, payment, rebalance) are not yet enabled. |
networks-5000 | 502 | Failed to connect to network RPC endpoint | Connection to the blockchain network RPC endpoint failed due to external service error |
Payments
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
payments-0006 | 500 | Could not resolve the account asset after a concurrent update | A concurrent insert reported a unique conflict but the racing account_assets row for account {account_id} {currency}/{network} could not be re-selected |
payments-0007 | 500 | Account asset balance is in an invariant-violating state | The stored account_assets row for {account_asset_id} has available_balance ({available}) greater than total_balance ({total}); refusing to mutate corrupt state |
payments-0008 | 500 | Balance mutation amount must be non-negative | BalanceService.{method} was called with a negative amount ({amount}); refusing to mutate |
payments-1000 | 404 | Payment not found | The specified payment ID does not exist |
payments-1001 | 404 | Payment transfer step not found with id '{id}' | The step does not exist or does not belong to this payment |
payments-1002 | 404 | Destination account not found | to_account did not resolve to an account in this workspace |
payments-3000 | 400 | from_network must equal to_network | User provides different networks for from_network and to_network |
payments-3001 | 400 | invalid from_amount or to_amount | from_amount and to_amount should be positive and be valid numbers |
payments-3002 | 400 | Either from_amount or to_amount must be provided. Cannot create payment without an amount. | User does not provide either from_amount or to_amount |
payments-3003 | 400 | Only one of from_amount or to_amount should be provided. The other will be calculated using the exchange rate. | User provides both from_amount and to_amount when only one should be provided |
payments-3004 | 400 | from_network is required for crypto-to-crypto payments | User creates a payment with stablecoin from_currency but does not provide from_network |
payments-3005 | 400 | to_network is required for crypto-to-crypto payments | User creates a payment with stablecoin to_currency but does not provide to_network |
payments-3006 | 400 | Onramp (fiat-to-crypto) payments are not yet supported. Coming soon! | User attempts to create an onramp payment which is not supported yet |
payments-3007 | 400 | Invalid from_currency | User provides a from_currency that is not supported |
payments-3008 | 400 | Invalid to_currency | User provides a to_currency that is not supported |
payments-3009 | 400 | funding_account_id not found | User provides a funding_account_id that does not exist |
payments-3010 | 400 | to_account_id not found | User provides a to_account_id that does not exist |
payments-3011 | 400 | from_account_id not found | User provides a from_account_id that does not exist |
payments-3012 | 400 | Missing input parameter is_approved | User submits a payment review without the required is_approved parameter |
payments-3015 | 400 | The exchange rate quote has expired. Please create a new payment to get a fresh quote. | User attempts to execute a payment with an expired exchange rate quote (valid for 24 hours) |
payments-3016 | 400 | Payment quote expiration data is missing. Please create a new payment to get a fresh quote. | Payment has an exchange rate but is missing expiration data, indicating a data integrity issue |
payments-3017 | 400 | to_account has not yet been risk approved by custodian | Beneficiary account has a Circle recipient that is still pending verification or has not been registered yet |
payments-3018 | 400 | from_account_id and to_account_id should not both be managed accounts for payments. Use /v1/treasury/rebalances instead. | Transfers between two managed accounts are treasury operations. Use /v1/treasury/rebalances instead. |
payments-3019 | 400 | Account asset not found for {from_account_id} | No matching account asset found for the from account with the specified currency and network |
payments-3020 | 400 | No {currency} balance found on network {network} for {to_account_id} | The to account does not have a balance for the specified currency and network |
payments-3021 | 400 | Amounts not yet calculated. Payment may still be processing. | Payment amounts have not been calculated yet, the payment may still be processing |
payments-3022 | 400 | Payment missing currency information | Payment is missing required currency or network data |
payments-3023 | 400 | Payment has not passed compliance screening. Cannot execute. | Payment has not been approved through compliance/risk screening |
payments-3024 | 400 | Payment does not have reserved balance. Cannot execute. | Payment balance has not been reserved prior to execution |
payments-3025 | 400 | No transfer step found for payment | Payment does not have a transfer step |
payments-3026 | 400 | Transfer step is already in status {status}. Cannot execute. | Transfer step is in a status that does not allow execution |
payments-3027 | 400 | Transfer step missing account asset IDs. Cannot execute. | Transfer step is missing the required from or to account asset IDs |
payments-3028 | 400 | Could not load accounts for execution | Failed to load the from or to account required for payment execution |
payments-3029 | 400 | Payment missing required data for step creation | Payment is missing required currency, amount, or network information for step creation |
payments-3030 | 400 | To asset is required for onchain payments | Onchain payment steps require a to account asset to be resolved |
payments-3031 | 400 | To account {id} is not a fiat account | The to account is not the expected fiat_bank type for offramp payments |
payments-3032 | 400 | Account {id} does not belong to workspace | The referenced account does not belong to the payment's workspace |
payments-3033 | 400 | Account not found for address {address} | No account found with the specified wallet address |
payments-3034 | 400 | Account {id} has no entity ID | The account is missing the required entity ID for payment processing |
payments-3035 | 400 | Fiat account {id} not found for workspace | The specified fiat account was not found in the workspace |
payments-3036 | 400 | Payment has not been updated with accounts. Please call PATCH /payments/ | Payment must be updated with account IDs before execution |
payments-3038 | 400 | Unsupported network for signing: {network} | The payment network is not supported for transaction signing |
payments-3040 | 400 | Cannot execute payment from external account {id} | External accounts support CRUD operations only. Use managed accounts for payment execution. |
payments-3041 | 400 | No payment execution provider available for this payment | No supported provider (Circle) could be resolved for this payment type and account combination |
payments-3042 | 400 | Source account asset not found | The source account asset could not be found for payment execution |
payments-3043 | 400 | Source account wallet address not found | The source account does not have a crypto wallet address |
payments-3044 | 400 | Destination account asset not found | The destination account asset could not be found for payment execution |
payments-3045 | 400 | Destination account wallet address not found | The destination account does not have a crypto wallet address |
payments-3047 | 400 | Wallet address mismatch | The provided wallet address does not match the account's wallet address |
payments-3048 | 400 | Amount mismatch between transfer step and provided amount | The provided amount does not match the transfer step amount |
payments-3049 | 400 | Transfer step missing from account asset ID | The transfer step does not have a from account asset ID set |
payments-3052 | 400 | direction must be 'inbound' or 'outbound' | GET /payments only filters transfers by direction; rebalance and other internal directions are rejected |
payments-3053 | 400 | Simulated inbound payments are not available in production | Inbound payment simulation is only available in staging environments |
payments-3054 | 400 | Unsupported network for inbound payment simulation | Inbound simulation supports only the BASE_SEPOLIA, ETHEREUM_SEPOLIA and POLYGON_AMOY testnets with USDC |
payments-3055 | 400 | Destination account cannot receive a simulated inbound | to_account exists but is not a managed stablecoin_ethereum wallet with an on-chain address |
payments-3060 | 400 | Payment step is not in a signable state | The step must be a turnkey step in 'signature_requested' state with a prepared unsigned transaction to accept a signature |
payments-3061 | 400 | Payment step is missing an unsigned transaction payload | The payment has not yet prepared an unsigned transaction — retry in a moment |
payments-3062 | 400 | Payment step is missing the source amount or currency | The step's estimated source amount and currency must be set before signing |
payments-3063 | 400 | Source wallet has insufficient on-chain balance | The live on-chain balance of the source wallet is below the payment amount; fund the wallet and retry before the payment expires |
payments-3064 | 400 | Turnkey could not produce a signed transaction | Turnkey rejected or failed the stamped sign_transaction activity. Verify the stamp matches the body bytes, the API key is registered in the sub-org, and the wallet exists in that sub-org. |
payments-3065 | 400 | Signature is invalid or could not be verified | The Turnkey stamp did not produce a valid signed transaction |
payments-3066 | 400 | Signed transaction does not match the payment details | The destination address or amount in the signed transaction does not match the prepared payment step |
payments-3067 | 400 | Signature is not a valid base64-encoded {body, stamp} envelope | The signature field must be base64-encoded JSON containing the Turnkey activity body and stamp header value |
payments-3068 | 400 | Currency is not supported for on-chain payment signing | Only currencies with a registered token contract on the payment network can be signed |
payments-3069 | 400 | Network is not supported for on-chain payment signing | The payment network has no registered on-chain signing configuration |
payments-3070 | 400 | Stamped activity type must be '{expected}', received '{actual}' | The stamped Turnkey activity must be ACTIVITY_TYPE_SIGN_TRANSACTION_V2 to sign a payment step |
payments-3071 | 400 | Stamped activity unsigned transaction does not match the payment step | The unsigned transaction inside the stamped Turnkey activity must equal the unsigned transaction prepared by the payment step |
payments-3072 | 400 | Stamped activity sign_with address does not match the payment source wallet | The sign_with parameter inside the stamped Turnkey activity must equal the source wallet's on-chain address |
payments-3073 | 400 | Stamped activity transaction type must be '{expected}', received '{actual}' | The transaction type inside the stamped Turnkey activity must match the payment network's Turnkey transaction type |
payments-3074 | 400 | Stamped activity organization does not match the workspace's Turnkey sub-organization | The stamped Turnkey activity's organization id must equal the workspace's configured Turnkey sub-org ID |
payments-3075 | 400 | Network '{network}' is not supported in this environment | Payments from managed wallets only support mainnet networks in production and their testnet counterparts in non-production environments |
payments-3076 | 400 | from_account_id '{from_account_id}' cannot fund outbound payments: no execution provider available for this account | The source account does not resolve to a payment execution provider. Outbound payments must be funded from a managed wallet or a provider-backed ledger account (e.g. the Circle Mint master ledger). |
payments-3077 | 400 | Required CPN compliance field {field} could not be resolved from the payment's counterparty/account data | The Circle Payments Network quote requires a travel-rule or beneficiary-account field for which no value (or no mapping) exists on the originator, beneficiary, beneficiary bank account, or OFI identity. Tesser validates existing data and fails fast rather than collecting new data. |
payments-3078 | 400 | Cross-currency payments are not supported. from_currency and to_currency must match. | User attempts a cross-currency payment; payments are same-currency stablecoin only |
payments-3079 | 409 | Payment accounts can no longer be changed; the payment has already been planned. | PATCH attempted account changes after the payment's steps were planned; accounts are frozen once planning runs |
Tenants
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
tenants-1000 | 404 | Tenant not found | The specified tenant ID does not exist |
tenants-2000 | 403 | You do not have access to this tenant | User tries to access a tenant that belongs to a different workspace |
tenants-3000 | 400 | business_legal_name is required to create a tenant | User creates a tenant without providing the required business_legal_name field |
tenants-3001 | 400 | business_legal_name is required and must be 1-255 characters | User provides a business_legal_name that doesn't meet length requirements |
tenants-3002 | 400 | business_address_country must be a valid ISO 3166-1 alpha-2 country code | User provides a business_address_country that is not a valid 2-letter country code |
tenants-3003 | 400 | webhook_url must be a valid HTTPS URL | User provides a webhook_url that is not a properly formatted HTTPS URL |
Treasury
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
treasury-1000 | 404 | Rebalance with id '{id}' not found | The specified rebalance ID does not exist |
treasury-1001 | 404 | Transfer step not found for rebalance with id '{id}' | The transfer step associated with the rebalance could not be found |
treasury-1002 | 404 | Account with id '{id}' not found | The specified account ID does not exist or does not belong to this workspace |
treasury-1100 | 404 | Deposit with id '{id}' not found | The specified deposit ID does not exist in this workspace |
treasury-1101 | 404 | Account with id '{id}' not found | The specified account ID does not exist or does not belong to this workspace |
treasury-1102 | 404 | Source account with id '{id}' not found | The source bank account for this deposit could not be found |
treasury-1103 | 404 | VAN account with id '{id}' not found | The virtual account number (VAN) account could not be found |
treasury-1200 | 404 | Withdrawal with id '{id}' not found | The specified withdrawal ID does not exist in this workspace |
treasury-1201 | 404 | Source account '{id}' not found | The withdrawal source account does not exist or does not belong to this workspace |
treasury-1202 | 404 | Destination bank account '{id}' not found | The withdrawal destination bank account does not exist or does not belong to this workspace |
treasury-1203 | 404 | Transfer step not found for withdrawal with id '{id}' | The transfer step associated with the withdrawal could not be found |
treasury-2100 | 409 | Deposit is still being planned. Wait for the deposit.created webhook before fetching instructions. | Instructions were requested while the deposit's async planning step is still running (steps array is empty). Retry after the deposit.created webhook fires. |
treasury-3000 | 400 | Unsupported rebalance direction. Supported: ledger→ledger, ledger→wallet, wallet→wallet | The source/destination account types are not a supported rebalance flow |
treasury-3001 | 400 | Network must not be specified for ledger accounts | Ledger-to-ledger rebalances operate without a blockchain network |
treasury-3002 | 400 | At least one of from_amount or to_amount must be provided | A rebalance requires at least one amount to determine the transfer size |
treasury-3003 | 400 | Invalid currency pair for rebalance | The specified from_currency and to_currency combination is not supported for Circle rebalancing |
treasury-3004 | 400 | from_amount and to_amount must be equal when currencies are the same | When both amounts are provided for same-currency rebalances, they must match |
treasury-3005 | 400 | Source or destination account is missing Circle wallet ID | The account does not have a Circle wallet ID configured, which is required for ledger transfers |
treasury-3006 | 400 | Transfer step is missing account asset IDs | The transfer step does not have the required from/to account asset references |
treasury-3007 | 400 | Network is required when rebalancing between wallet accounts | On-chain wallet-to-wallet rebalances need from_network and to_network to be set |
treasury-3008 | 400 | from_network and to_network must match for wallet-to-wallet rebalance | Cross-chain wallet-to-wallet rebalance is not supported yet; source and destination network must be identical |
treasury-3009 | 400 | Wallet account is missing a crypto wallet address | On-chain wallet-to-wallet rebalance requires both accounts to have a crypto wallet address |
treasury-3010 | 400 | Wallet-to-wallet rebalance is only supported between managed wallets | Both source and destination accounts must be Tesser-managed (is_managed = true) wallet accounts |
treasury-3011 | 400 | Currency '{currency}' is not supported for wallet-to-wallet rebalance | On-chain wallet-to-wallet rebalance currently supports USDC only |
treasury-3012 | 400 | Network '{network}' is not supported for wallet-to-wallet rebalance | On-chain wallet-to-wallet rebalance currently supports BASE and BASE_SEPOLIA only |
treasury-3013 | 400 | Rebalance step is not in a signable state | The step must be a turnkey step in 'signature_requested' state with a prepared unsigned transaction to accept a signature |
treasury-3014 | 400 | Rebalance step is missing an unsigned transaction payload | The rebalance has not yet prepared an unsigned transaction — retry in a moment |
treasury-3015 | 400 | Signature is invalid or could not be verified | The Turnkey stamp did not produce a valid signed transaction |
treasury-3016 | 400 | Signed transaction does not match the rebalance details | The destination address or amount in the signed transaction does not match the prepared rebalance step |
treasury-3017 | 400 | Destination wallet is not registered with Circle or compliance is not active | The destination managed wallet must have an active Circle business recipient registration before it can receive rebalance transfers |
treasury-3018 | 400 | to_network is required when destination is a managed wallet | Rebalances to a managed stablecoin wallet must specify the target blockchain network |
treasury-3019 | 400 | Network '{network}' is not supported in this environment | Rebalances to managed wallets only support BASE in production and BASE_SEPOLIA in non-production environments |
treasury-3020 | 400 | Signature is not a valid base64-encoded {body, stamp} envelope | The signature field must be base64-encoded JSON containing the Turnkey activity body and stamp header value |
treasury-3021 | 400 | Stamped activity type must be '{expected}', received '{actual}' | The stamped Turnkey activity must be ACTIVITY_TYPE_SIGN_TRANSACTION_V2 to sign a rebalance step |
treasury-3022 | 400 | Stamped activity unsigned transaction does not match the rebalance step | The unsignedTransaction inside the stamped Turnkey activity must equal the unsigned transaction prepared by the rebalance step |
treasury-3023 | 400 | Stamped activity signWith address does not match the rebalance source wallet | The signWith parameter inside the stamped Turnkey activity must equal the source wallet's on-chain address |
treasury-3024 | 400 | Stamped activity organizationId does not match the workspace's Turnkey sub-organization | The stamped Turnkey activity's organizationId must equal the workspace's configured Turnkey sub-org ID |
treasury-3025 | 400 | Turnkey could not produce a signed transaction | Turnkey rejected or failed the stamped sign_transaction activity. Verify the stamp matches the body bytes, the API key is registered in the sub-org, and the wallet exists in that sub-org. |
treasury-3026 | 400 | Stamped activity parameters.type must be '{expected}', received '{actual}' | The Turnkey transaction type inside parameters.type must match the network of the rebalance step (e.g. TRANSACTION_TYPE_ETHEREUM for BASE) |
treasury-3027 | 500 | OpenFX rebalance step is missing required metadata ({reason}) for id '{id}' | The transfer step or destination account is missing fields the OpenFX withdrawal trigger needs to dispatch the rebalance |
treasury-3028 | 409 | Source wallet has insufficient on-chain balance to sign | The wallet's live on-chain balance is below the rebalance amount at sign time. The balance is re-checked when you retry; rebalance.balance_updated fires with balance_status 'awaiting_funds'. |
treasury-3029 | 502 | Failed to generate an OpenFX quote for {fromCurrency} → {toCurrency} | OpenFX could not return a projection quote for the cross-currency rebalance swap leg. Retry; if it persists the pair may be unsupported by OpenFX. |
treasury-3030 | 400 | Destination wallet is registered with Circle on a different network than the requested one | Rebalance to a Circle-bound wallet whose registered recipient chain doesn't match the requested to_network. |
treasury-3031 | 400 | Destination wallet is not registered with OpenFX for the requested coin and network | Rebalance to a wallet that has no matching active OpenFX withdrawal address for the coin+network. |
treasury-3100 | 400 | Account '{id}' is not a ledger account | Deposits can only be made to ledger accounts |
treasury-3101 | 400 | Account '{id}' is not configured for deposits. No supported provider found | The destination account does not have a supported deposit provider configured |
treasury-3102 | 400 | Ledger '{id}' is missing Circle Mint metadata | The ledger account does not have the required Circle Mint configuration |
treasury-3103 | 400 | Circle compliance not yet accepted for ledger. Cannot create deposit | Circle compliance must be accepted before deposits can be created |
treasury-3104 | 400 | Source account '{id}' does not match the configured source bank for this ledger | The provided source account does not match the bank account configured for this ledger |
treasury-3105 | 400 | Source bank account '{id}' not found or is not a fiat bank account | The source bank account could not be found or is not the correct account type |
treasury-3106 | 400 | Ledger account '{id}' does not have a '{currency}' asset | The destination ledger account does not hold the requested currency |
treasury-3107 | 400 | Invalid currency combination for Circle deposit: {fromCurrency} → {toCurrency} | The specified from_currency and to_currency combination is not supported for Circle deposits |
treasury-3108 | 400 | Deposit '{id}' is already finalized. Wire instructions are no longer available | The deposit has already been finalized and instructions cannot be retrieved |
treasury-3109 | 400 | Deposit '{id}' has no transfer step | The deposit does not have the expected transfer step |
treasury-3110 | 400 | Deposit '{id}' transfer step has no source account | The deposit transfer step is missing its source account reference |
treasury-3111 | 400 | Deposit '{id}' transfer step has no destination account | The deposit transfer step is missing its destination account reference |
treasury-3112 | 400 | Source account '{id}' is missing required bank details | The source account does not have all required bank details (bank name, code type, identifier code, or account number) |
treasury-3113 | 400 | VAN account '{id}' missing virtual_account_number metadata | The VAN account does not have the required virtual account number metadata |
treasury-3114 | 400 | VAN account '{id}' is missing required field: {field} | The VAN account is missing a required field for wire instructions (e.g., bank name, account number, SWIFT code, beneficiary name) |
treasury-3115 | 400 | Simulated deposits are not available in production | Deposit simulation is only available in sandbox environments |
treasury-3116 | 400 | to_network is required when destination is a managed wallet | Deposits to a managed stablecoin wallet must specify the target blockchain network |
treasury-3117 | 400 | to_network must not be specified for ledger accounts | Deposits to ledger accounts operate without a blockchain network |
treasury-3118 | 400 | Network '{network}' is not supported in this environment | Deposits to managed wallets only support BASE in production and BASE_SEPOLIA in non-production environments |
treasury-3119 | 400 | Deposit '{id}' has no estimated source amount yet | The deposit's estimated.from.amount or estimated.from.currency is not populated. The estimate is filled in after planning; this can occur if instructions are requested before the deposit has been planned. |
treasury-3120 | 400 | No deposit provider can handle this configuration. Verify the source bank account, destination account compliance state, and currency pair. | getEligibleDepositProviders returned an empty array — no provider matches the deposit's source account, destination account, currency pair, or workspace provider configuration (e.g., missing Circle API key in the vault). |
treasury-3133 | 400 | Ledger '{id}' is missing OpenFX metadata | The destination ledger account does not have OpenFX configuration (metadata.openfx) |
treasury-3134 | 400 | Currency pair {fromCurrency} → {toCurrency} is not supported for OpenFX deposits | OpenFX deposits support same-currency fiat→fiat or fiat→stablecoin (on-ramp) pairs only |
treasury-3136 | 502 | Failed to obtain OpenFX quote for {fromCurrency} → {toCurrency} | OpenFX rejected or did not respond to the projection quote during deposit planning. The deposit cannot be created until OpenFX returns a valid rate. |
treasury-3137 | 502 | OpenFX trade failed for deposit '{id}' after retry budget | The swap leg of an OpenFX cross-currency deposit could not be executed within the retry budget. The swap step has been marked as failed. |
treasury-3138 | 502 | OpenFX quote expired before trade could execute | OpenFX rejected the trade because the quote had expired (HTTP 422). The next attempt will request a fresh quote. |
treasury-3139 | 400 | Wallet address '{address}' is not registered in OpenFX for {coin} on {network} | The wallet must be manually registered in the OpenFX dashboard before it can receive deposits |
treasury-3140 | 400 | Multiple OpenFX withdrawal addresses matched ({count}) — registration is ambiguous | More than one verified active withdrawal address matched; resolve via the OpenFX dashboard |
treasury-3141 | 400 | OpenFX coinNetworkName '{coinNetworkName}' is not a known Tesser network | The network returned by OpenFX does not map to a supported Tesser network identifier |
treasury-3142 | 400 | to_network is required for OpenFX wallet deposits | OpenFX wallet deposits must specify the target blockchain network via to_network |
treasury-3143 | 502 | OpenFX withdrawal failed for deposit '{id}' (reason: {reason}) | The wallet leg of an OpenFX deposit could not be submitted to OpenFX. The withdrawal step has been marked as failed. |
treasury-3144 | 400 | Source bank '{id}' is not registered with OpenFX (no fiatWithdrawalAddressId) | The funding bank account has no OpenFX fiatWithdrawalAddressId and lazy rematch failed. Register the bank in OpenFX (or fix the rematch) before retrying the deposit. |
treasury-3145 | 400 | Wallet account '{id}' is missing a crypto wallet address | The managed wallet has no on-chain address, so it cannot be matched to an OpenFX withdrawal address. This is a permanent data fault, not a transient error. |
treasury-3146 | 400 | Destination wallet is not an active Circle business recipient | Deposit to a Circle-bound wallet whose circleBusinessRecipientId is missing or whose status is not active. |
treasury-3147 | 400 | Destination wallet is registered with Circle on a different network than the requested one | Deposit to a Circle-bound wallet whose registered recipient chain doesn't match the requested to_network. |
treasury-3148 | 400 | Source bank is not activated with OpenFX yet | The funding bank account is registered with OpenFX but its fiat withdrawal address is not active yet (e.g. under review). Wait for OpenFX approval before retrying the deposit. |
treasury-3200 | 400 | from_currency must be a valid currency code | User provides an invalid from_currency value |
treasury-3201 | 400 | to_currency must be a valid currency code | User provides an invalid to_currency value |
treasury-3202 | 400 | from_amount must be a valid decimal string | User provides a from_amount that is not a valid number |
treasury-3203 | 400 | to_amount must be a valid decimal string | User provides a to_amount that is not a valid number |
treasury-3204 | 400 | from_account_id must be a valid UUID | User provides a from_account_id that is not a valid UUID |
treasury-3205 | 400 | to_account_id must be a valid UUID | User provides a to_account_id that is not a valid UUID |
treasury-3206 | 400 | from_network must be a valid network identifier | User provides an invalid from_network value |
treasury-3207 | 400 | to_network must be a valid network identifier | User provides an invalid to_network value |
treasury-3300 | 400 | from_amount must be provided | Withdrawals must specify the source amount in major units |
treasury-3301 | 400 | from_network must not be specified for ledger sources | Ledger-source withdrawals operate without a blockchain network; from_network is only valid for wallet-source withdrawals |
treasury-3302 | 400 | Currency pair {fromCurrency} → {toCurrency} is not supported for withdrawals | Only USDC → USD withdrawals are supported in this release |
treasury-3303 | 400 | Source account '{id}' must be a Circle USDC ledger for ledger-source withdrawals | Ledger-source withdrawals require a managed Circle Mint ledger account as the source |
treasury-3304 | 400 | Destination account '{id}' must be a workspace bank account | Withdrawals can only target a workspace-level bank account (type=fiat_bank, no entity_id) |
treasury-3305 | 400 | No master Circle USDC ledger found for this workspace | Wallet-source withdrawals route through the workspace's master Circle ledger, which is created when the Circle API key is configured |
treasury-3306 | 400 | Withdrawal step is not in a signable state | The step must be a turnkey step in 'signature_requested' state with a prepared unsigned transaction to accept a signature |
treasury-3307 | 400 | Withdrawal step is missing an unsigned transaction payload | The withdrawal has not yet prepared an unsigned transaction — retry in a moment |
treasury-3308 | 400 | Signature is invalid or could not be verified | The Turnkey stamp did not produce a valid signed transaction |
treasury-3309 | 400 | Signed transaction does not match the withdrawal details | The destination address or amount in the signed transaction does not match the prepared withdrawal step |
treasury-3310 | 400 | Signature is not a valid base64-encoded {body, stamp} envelope | The signature field must be base64-encoded JSON containing the Turnkey activity body and stamp header value |
treasury-3311 | 400 | Stamped activity type must be '{expected}', received '{actual}' | The stamped Turnkey activity must be ACTIVITY_TYPE_SIGN_TRANSACTION_V2 to sign a withdrawal step |
treasury-3312 | 400 | Stamped activity unsigned transaction does not match the withdrawal step | The unsignedTransaction inside the stamped Turnkey activity must equal the unsigned transaction prepared by the withdrawal step |
treasury-3313 | 400 | Stamped activity signWith address does not match the withdrawal source wallet | The signWith parameter inside the stamped Turnkey activity must equal the source wallet's on-chain address |
treasury-3314 | 400 | Stamped activity organizationId does not match the workspace's Turnkey sub-organization | The stamped Turnkey activity's organizationId must equal the workspace's configured Turnkey sub-org ID |
treasury-3315 | 400 | Turnkey could not produce a signed transaction | Turnkey rejected or failed the stamped sign_transaction activity. Verify the stamp matches the body bytes, the API key is registered in the sub-org, and the wallet exists in that sub-org. |
treasury-3316 | 400 | Stamped activity parameters.type must be '{expected}', received '{actual}' | The Turnkey transaction type inside parameters.type must match the network of the withdrawal step (e.g. TRANSACTION_TYPE_ETHEREUM for BASE) |
treasury-3317 | 400 | Currency '{currency}' is not supported for wallet-source withdrawal | On-chain wallet-source withdrawal currently supports USDC only |
treasury-3318 | 400 | Network '{network}' is not supported for wallet-source withdrawal | The network on the withdrawal step is not a supported EVM network for on-chain signing |
treasury-3319 | 409 | Source wallet has insufficient on-chain balance to sign | The wallet's live on-chain balance is below the withdrawal amount at sign time. The balance is re-checked when you retry; withdrawal.balance_updated fires with balance_status 'awaiting_funds'. |
treasury-3320 | 400 | No withdrawal provider can handle this configuration. Verify the source account, destination bank account, and currency pair. | getEligibleWithdrawalProviders returned an empty array — no provider matches the withdrawal's source account, destination bank account, currency pair, or workspace provider configuration (e.g., missing Circle API key in the vault). |
treasury-3321 | 400 | Deposit '{id}' has already received its funding wire. Wire instructions are no longer available | The funding wire has already been received and instructions cannot be retrieved |
treasury-3322 | 400 | Same-account rebalances are only supported for on-ledger FX swaps | A rebalance where source and destination are the same account is only valid as an on-ledger OpenFX FX swap |
treasury-3322 | 400 | Circle compliance not yet accepted for the source ledger. Cannot create withdrawal | Withdrawal source is a Circle ledger whose circleComplianceState is not ACCEPTED. |
treasury-3323 | 400 | Same-account rebalances require different currencies | A same-account OpenFX rebalance is an FX swap and cannot have matching from/to currencies |
treasury-3324 | 400 | Currency '{currency}' is not supported for a same-account swap | A same-account OpenFX swap settles on the ledger, so both currencies must be representable in the Tesser currency registry |
treasury-3325 | 400 | Destination bank '{id}' has no active OpenFX fiat withdrawal address for currency {currency} | OpenFX fiat withdrawals pay out to pre-registered, per-currency fiat withdrawal addresses. No active address matched the destination bank's account number for the payout currency. |
treasury-3326 | 400 | OpenFX could not quote the withdrawal pair {fromCurrency} → {toCurrency} | The plan-time OpenFX quote for the withdrawal's swap leg failed. Pair eligibility is quote-driven (no hardcoded whitelist), so a failed quote means the pair is unsupported or the provider is unavailable. |
treasury-3327 | 400 | Destination bank '{id}' is not activated with OpenFX yet (status: {status}) | The destination bank matched an OpenFX fiat withdrawal address, but none of its addresses are active yet (e.g. under review). Wait for OpenFX approval before retrying the withdrawal. |
treasury-3328 | 400 | OpenFX ledger '{id}' has no deposit address registered for {currency} on {network} | No OpenFX deposit address is registered for the requested asset and network, so the wallet-source withdrawal fails closed. |
treasury-3329 | 400 | Workspace '{workspaceId}' has no OpenFX-bound ledger | Wallet-source withdrawals settle through the workspace's OpenFX ledger, and none is bound to this workspace. |
treasury-3330 | 400 | Amount {amount} {currency} is below the OpenFX minimum on-chain deposit of {minimum} {currency} | OpenFX never credits on-chain deposits below its minimum — sub-minimum funds are not shown on the ledger and are unrecoverable, so wallet-source withdrawals below the minimum fail closed before anything is dispatched on-chain. |
Vault
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
vault-0001 | 500 | Failed to store sensitive data in vault | The vault provider failed to store the token. This may be due to a temporary outage or configuration issue. |
vault-0002 | 500 | Vault provider did not return a token ID | The vault provider accepted the data but did not return a token ID. This indicates an unexpected API response. |
vault-0003 | 400 | Unknown vault field | The specified field name is not configured for vault storage. Check the VaultFieldConfig for supported fields. |
vault-0004 | 400 | Invalid field type for operation | The operation does not match the field type. For example, trying to store text in a file-only field. |
vault-0005 | 409 | Vault record already exists for this resource and field | A create-only vault write found an existing record for the same (resourceId, fieldName). Rotate or delete the existing record instead. |
vault-0010 | 404 | Vault token not found | The specified token does not exist in the vault. It may have been deleted or never created. |
vault-0011 | 500 | Failed to retrieve token from vault | The vault provider failed to retrieve the token. This may be due to a temporary outage or authentication issue. |
vault-0012 | 500 | Failed to reveal token value | The vault provider failed to reveal the token value. The API key may not have sufficient permissions. |
vault-0020 | 500 | Failed to delete token from vault | The vault provider failed to delete the token. This may be due to a temporary outage or authentication issue. |
vault-0030 | 502 | Vault proxy request failed | The vault proxy failed to forward the request to the destination. Check the destination URL and authentication. |
vault-0031 | 502 | Vault proxy destination returned an error | The vault proxy successfully forwarded the request, but the destination returned an error response. |
vault-0040 | 503 | Vault provider is not configured | The vault provider API key is not configured. Contact support to enable vault functionality. |
vault-0041 | 400 | Liquidation provider not found | The specified liquidation provider is not configured. Check the available providers. |
vault-0050 | 502 | Failed to forward vaulted data to provider | The vaulted data could not be forwarded to the liquidation provider. This may be due to a provider outage or misconfiguration. |
vault-0051 | 422 | Provider rejected the forwarded data | The liquidation provider rejected the forwarded data. Check the data format and provider requirements. |
Circle
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
circle-1000 | 404 | Circle API key not configured for organization | The organization does not have a Circle Mint API key configured in the vault |
circle-2000 | 401 | Circle API key authentication failed | The configured Circle Mint API key failed authentication with Circle API |
circle-4290 | 429 | Cannot complete request because rate limited by provider Circle Mint | The Circle Mint API returned a 429 rate limit response |
circle-5000 | 502 | Circle Mint service error | An error occurred while communicating with the Circle Mint API |
circle-5001 | 503 | Circle Mint service temporarily unavailable | The Circle Mint API is temporarily unavailable |
Idempotency
| Error Code | HTTP Status | Error Message | Description |
|---|---|---|---|
idempotency-0001 | 409 | A request with this idempotency key is currently being processed. Please wait and retry. | Another request with the same idempotency key is still in progress |
idempotency-0002 | 400 | Keys for idempotent requests can only be used with the same parameters they were first used with. | The idempotency key was previously used with a different request body. Use a different key for different requests. |
Last modified on