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

CodeMeaningCommon cause
200Success.
400Bad input.Malformed jetton master address; amountIn is zero or negative; missing required field.
404No route.Returned by /v1/tx when neither DEX has liquidity for the requested pair / size.
503Upstream unhealthy.The TON RPC client could not reach a recent block. Returned by /v1/health only.

Error body

json
{ "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.

ts
// 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.