Splitting Large Swaps: Limits, Risk and Real Cost
Measured: 180,000 USDT quotes fine while the error claims 175,277. Depth costs 0.078% from 20k to 175k, and every extra batch adds 2.13 USD plus a fresh 30-minute window.
At 06:01 UTC on 29 October 2026 I asked for a quote on 200,000 USDT-TRC20 into Monero. The API answered: amount above maximum, maxAmount 175,277.530607. Two minutes later the same pair, on the same page, quoted 180,000 at 299.54872164 XMR. The ceiling in the error sat 4,722 USDT below what the site would actually price. That is not a bug so much as a side effect of quoting several pools at once: the min and max in the error body come from the first route that failed, not from the venue as a whole. (XMR to USDT exit)
The ceiling belongs to the corridor, not the site
I probed three corridors with an obviously oversized amount and read the limits back. USDT-TRC20→XMR accepted 180,000 and rejected 181,000, and the rejection carried maxAmount 175,082.69597, itself 195 USDT lower than an hour earlier, because the figure is one pool's live limit rather than a constant. XMR→USDT tops out at 296.307762260273 XMR (floor 0.03008666), which at USD 590.75 is USD 175,044. BTC→XMR tops out at 2.18507345 BTC (floor 0.00017917), USD 175,138 at 80,152. ZEC→XMR stops at 60.79096903 ZEC (floor 0.02167768), USD 76,053 at 1,251.05, or 43% of the other two. So 175k is three corridors coincidentally landing in the same band. Plan a large ZEC batch on that number and the order is refused. (XMR to USDT exit)
On the amount axis there are only two costs
Nine quotes for USDT-TRC20→XMR at 06:01 UTC: 100 gave 0.14873867 XMR; 1,000 gave 1.64868; 5,000 gave 8.31170063; 20,000 gave 33.29237287; 50,000 gave 83.22767913; 100,000 gave 166.41787711; 150,000 gave 249.53778562; 175,000 gave 291.08189961; 180,000 gave 299.54872164. Using the 20,000 tier's effective rate of 0.0016646186 as the reference, the retained share runs 89.35%, 99.04%, 99.86%, 100.00%, 100.00%, 99.97%, 99.94%, 99.92%, 99.97%. (XMR to USDT exit)
That reads cleanly. A 100 USDT order pays about 10.65 USDT of fixed cost, 10.65% of the ticket. At 1,000 it is 0.96%, at 5,000 0.14%, and from 20,000 up it is effectively zero. Depth is a separate, much flatter curve: 0.078% between 20,000 and 175,000. Splitting 175,000 into two orders of 87,500 in the same minute did return 0.044% more (291.29782484 against 291.17025440 XMR, about USD 75), at the cost of one extra TRC20 deposit fee of 6.4285 TRX (USD 2.13). On paper the split wins; in practice 0.044% sits inside the price noise between two clicks. (XMR to USDT exit)
What each batch really costs: deposit fee, window, price lock (how Monero fees work)
A TRC20 transfer burns 64,285 energy, and at getEnergyFee = 100 sun that is 6.4285 TRX, USD 2.13 at 0.331084. If the destination is fresh, which it is for every order because each gets a newly generated deposit address and the first USDT credit writes a zero balance slot, it costs 130,285 energy, 13.0285 TRX, USD 4.31. Bitcoin is an order of magnitude cheaper per batch: 141 vB at 1 sat/vB is 141 sat, USD 0.11 (mempool 52,347 tx and 21.07 MvB at 06:03, every recommended tier at 1 sat/vB). Then the window: EXPIRE_MS is 30 minutes from creation, with a 6-hour look-back for late deposits and a 24-hour forced close. And the price: it is locked when the order is created, so every batch locks a different number. (XMR to USDT exit)
The quote lives 120 seconds; the order window lives 30 minutes
At 06:14:56 the quote carried validUntil 2026-10-29T06:16:56.831Z, exactly 120.0 seconds later. The 06:17:30 response said 06:19:30.522. So if you price six batches first and then create them one at a time, everything after the first is stale, and each order re-quotes server-side before it locks. Do not read the 30-minute order window as 30 minutes to think. The number you saw is good for two minutes.
The rate limit, not the curve, decides the batch count
The order endpoint allows 6 orders per hour per IP and 120 per hour globally, and rejects an identical pair, amount and address within 90 seconds without touching the upstream. 600,000 USDT as four orders of 180,000 fits inside one hourly window. The same amount as twelve orders of 50,000 needs two hours, two windows and twelve price locks. That limit is what usually decides how many batches are possible. (XMR to USDT exit)
Splitting does not clean up the source
Each order gets its own deposit address, but the paying address on TRC20 and the input set on Bitcoin are public. Upstream screening runs per order, so a flagged source split six ways produces six identical refusals and six records instead of one. Refund addresses multiply too: refunds go only to refundAddress, on the original asset and network, which makes N batches N chances to paste the wrong one. And because the 6-per-hour cap is per IP, the batches share one network fingerprint regardless.
Twenty-four minutes of drift: the noise is bigger than the depth
I sampled the 175,000 and 87,500 quotes every three minutes from 06:14:56 to 06:36:19 UTC, eight points. The 175,000 rate moved between 0.0016657209 and 0.0016694333 — a 0.223% range — and one three-minute gap alone moved 0.125%. The split advantage, meaning two 87,500 orders against one 175,000 order priced seconds apart, ran from -0.028% to +0.064% and changed sign on the very first pair of samples. Set that against the 0.078% depth cost the split is supposed to capture: one quote refresh is larger than the entire effect. Batching across minutes is not a price strategy. It is how you get around a ceiling, and the drift is a cost to budget for, not an edge to win.
When splitting is right, and when it is theatre
Three legitimate reasons: the amount exceeds the corridor ceiling (today, for USDT-TRC20, that is somewhere between 180,000 and 181,000); an upstream imposes a per-order risk limit, which surfaces as an explicit above-maximum error rather than a timeout; or you deliberately want time-weighted execution and accept that each batch locks its own price. Below the ceiling, between 5,000 and 180,000, splitting for the rate alone trades window risk and extra address handling for 0.04% of noise. (XMR to USDT exit)
Six steps, four mistakes
1) Probe the boundary with your target plus 5,000, then walk down using the error's number as a starting point, not a rule. 2) Keep every batch at or above 5,000 to stay out of the fixed-cost zone. 3) Create all batches inside one hourly window, six at most, and record each deposit address. 4) Give every batch its own refund address; subaddresses of one wallet are enough, reuse is not. 5) Fund in creation order, earliest first, so the oldest window is served first. 6) Save every order id, since late deposits are recovered by a 6-hour look-back. (recovering misdirected funds)
Four mistakes dominate. Reading six orders per hour as six per day. Sharing one refund address across all batches. Splitting into 1,000-sized pieces and paying roughly 1% per batch. And assuming batching hides anything from screening, which it does not: it multiplies the records. If your amount fits under the corridor ceiling, one order is cheaper and simpler; split when a ceiling or a risk limit forces you to, and price every batch at the moment you create it. (recovering misdirected funds)