Request body is not valid JSON. | 400 | The body could not be parsed at all, so the endpoint’s own validation never ran. |
Request body is too large. | 400 | The body is over the size limit. Every request on this API is a small JSON object. |
assetId is required | 400 | You omitted assetId. Send it explicitly on every call. |
X-Request-Id header is required for /send — reuse the same value when retrying a transfer | 400 | /send needs a client-supplied idempotency key. |
Invalid X-Request-Id — 1-64 characters of A-Za-z0-9._- | 400 | The header is present but malformed. |
Unknown assetId: 51 | 400 | Not a supported asset — or one that is not available on your endpoint. The offending id is included in the message. See Asset IDs. |
Wallet not found for user on this chain. | 400 | That user has no wallet on the asset’s chain — usually because the chain was unavailable when the user was created. Backfill with /extend. |
Missing/Invalid userId | 400 | userId must be a 24-character hex id. |
Invalid amount | 400 | amount must be a decimal string like "0.5" — not a float, not base units, not negative. |
Amount below minimum of 0.0001ETH | 400 | Native EVM sends have a floor of 0.0001 (ETH, BNB, POL). |
Minimum send amount is 0.00001 BTC | 400 | Bitcoin’s floor. |
Amount must be greater than zero. | 400 | Token sends cannot be zero. |
Amount has more than 6 decimal places | 400 | More precision than the asset’s decimals allow. |
Missing/Invalid address | 400 | A malformed recipient (or sender on /fee). |
Sender and recipient must differ | 400 | Self-transfers are rejected. |
Missing/Invalid password | 400 | /send on Bitcoin with no password in the body. A wrong password is 401 Invalid credentials. |
Unauthorized | 401 | No bearer token, or a malformed Authorization header. |
Invalid or expired token | 401 | The access token expired or does not verify. Call /refresh. |
Missing refresh token | 401 | /refresh was called without a refreshToken in the body. |
Invalid refresh token | 401 | The refresh token expired, was already consumed, or was revoked by a replay. Go back to /auth. |
Invalid credentials | 401 | Bad api key on /auth, a deactivated api client on /refresh, or the wrong keystore password on /send / /extend (Ethereum, BSC, Polygon, Tron and Solana) — including a /create that resolves to a wallet set the password does not open. |
Insufficient native funds. | 402 | Not enough of the native coin for the transfer. |
Insufficient native for gas. | 402 | The token balance is fine, but there is no native coin to pay the gas. |
Insufficient token balance | 402 | Not enough of the token. |
Do not send X-USER-ID to a platform endpoint — it always acts as the platform wallet. | 400 | /platform/* endpoints resolve their wallet from your credentials; drop the header. |
The platform wallet is not reachable from user endpoints. | 403 | The platform wallet is only served under the /platform prefix — use the twin endpoint. |
This platform has no wallet. | 404 | Your api client has no platform wallet yet — the service operator provisions it. |
Seed does not match this user. | 403 | The mnemonic sent to /extend does not derive that user’s stored address. |
Transaction not found | 404 | Unknown hash, or a broadcast that has not propagated yet. |
Address not found | 404 | On Bitcoin, the address is not one the indexer knows. Check the assetId and the user’s wallet. |
Transaction history is temporarily unavailable | 503 | History could not be read for Ethereum, BSC or Polygon. Transient — retry with backoff. An empty list now always means “no transactions”, never a failure. |
Failed to get BTC balance | 502 | The Bitcoin indexer did not answer. Transient — retry with backoff. |
Wallet already exists. | 409 | A derived address is already registered. |
A transfer with this X-Request-Id is already in progress — check /transactions before retrying. | 409 | The original attempt has not resolved yet. Back off and retry with the same id. |
Another transfer from this wallet is in progress — retry shortly. | 409 | On Ethereum, BSC and Polygon, transfers from one wallet are serialised. Retry with the same id after a short backoff. |
Transfer is being prepared — retry shortly with the same X-Request-Id. | 409 | The transfer is being set up and the outcome is not yet certain. Retry with the same id — never a new one, and never assume nothing went out. |
This transfer cannot be covered for you right now — retry shortly with the same X-Request-Id. | 409 | On assets where transfers are covered for you, the cover was momentarily unavailable. Retry with the same id after a backoff. If it persists, the wallet can still send by holding the chain’s native coin itself. |
This X-Request-Id was already used for a different transfer. | 422 | You reused an id with a different assetId, recipient or amount. A new transfer needs a new id. |
Amount does not cover the network fee. | 422 | On a native send the fee is taken out of the amount — and this amount is smaller than the fee. |
Transaction was rejected by the network. | 502 | Tron refused the broadcast. Nothing went out. |
Provide exactly one of fiatAmount or cryptoAmount | 400 | A quote fixes one leg and derives the other — send one, not both or neither. |
Amount must be greater than zero | 400 | A quote cannot be for nothing. |
Quoted amount rounds to zero — increase the amount | 400 | The derived leg is smaller than one base unit at the current price. |
Unsupported fiat: JPY | 400 | Settlement currency must be one of USD, EUR, GBP, CAD, AUD, SEK, DKK, PLN, BRL or AED. |
Missing/Invalid tradeId | 400 | tradeId must be a 24-character hex id, as returned by /order or /sell. |
Trade not found | 404 | No trade with that id for that user. |
Quote has expired — request a new one. | 409 | You approved after quote.expiresAt. The trade is now expired. |
This trade is already being filled — poll /trade before retrying. | 409 | The order is placed and the outcome is not yet confirmed. Never approve again. |
Trade cannot be approved from status: expired | 409 | Already expired, failed or cancelled — quote again. |
Trade cannot be cancelled from status: approved | 409 | Only an open quote can be cancelled. |
Trade is no longer open | 409 | Another request approved or cancelled it first. |
This trade can no longer be settled — request a new quote. | 409 | The terms the trade was quoted under no longer apply. Nothing traded — quote again. |
Order rejected: the order could not be filled | 502 | The order was refused; nothing traded and the trade is now failed. The text after Order rejected: varies. |
Pricing is temporarily unavailable — try again shortly. | 502 / 504 | No usable price. On /order and /sell nothing was quoted; on /trade/approve see the 504 row above. |
Trading is temporarily unavailable | 503 | Trading is not available for that asset right now. Transient — retry with backoff; contact your operator if it persists. |