Errors
chop returns plain HTTP status codes with a JSON body. Failures fall into three buckets: bad inputs, no route available, and upstream RPC issues.
Status codes
| Code | Meaning | Common cause |
|---|---|---|
200 | Success. | — |
400 | Bad input. | Malformed jetton master address; amountIn is zero or negative; missing required field. |
404 | No route. | Returned by /v1/tx when neither DEX has liquidity for the requested pair / size. |
503 | Upstream unhealthy. | The TON RPC client could not reach a recent block. Returned by /v1/health only. |
Error body
{ "error": "amountIn must be positive" }In development mode the response also includes a stack field. In production builds the stack is hidden.
Quote-vs-tx differences
/v1/quote never 404s. If no DEX can quote, it returns { quotes: [], bestRoute: null } with a 200 status. That makes it easy for UIs to distinguish “no route” from an actual error.
/v1/tx does 404 when no route exists. There’s no point returning success if there’s nothing to broadcast.
On-chain failures
Even after a successful broadcast, the swap can revert on-chain if the price moves outside the slippage window. The wallet receives the input back; you only pay gas. There is no API call required to detect this — observe the user’s output asset balance after broadcast.
// Pseudocode for verifying actual fill
const before = await getJettonBalance(USDT_MASTER, userAddress);
await sendTransaction(tx);
await waitForSeqno();
await sleep(15_000); // forwarded messages settle
const after = await getJettonBalance(USDT_MASTER, userAddress);
const filled = after - before;
if (filled === 0n) {
// Swap reverted (slippage hit or pool ran dry between build and settle)
}Rate limits
The public chop.ag API has no published rate limits, but we apply per-IP throttling to keep upstream RPC providers happy. If you exceed it you’ll see 429 responses; back off and retry. For high-volume integrations, self-host the API.