At a glance
Swap real mainnet tokens for testnet funds in four API calls. Base URL https://drip.tools/api, JSON over HTTPS, no auth, open CORS. Pay from ten EVM mainnets, Solana or TON; receive on 30+ EVM, Solana, TON and Bitcoin testnets.
The flow
| # | Step | Call | You get |
|---|---|---|---|
| 1 | Discover | GET /api/chains?unwrap=true | FROM chains (isTestnet: false) with their pay target contracts.depository; TO chains (isTestnet: true; skip isEnabled: false) and tokens. |
| 2 | Quote | POST /api/quote { chainId, fromToken, sender, toChainId, toToken, recipients[], toAmounts[] } | quoteId, vault (= pay target), fromTotal, deadline, signature. Free, non-binding, valid 180 s. |
| 3 | Pay | one transaction on the FROM chain, exactly fromTotal, before deadline | EVM: pay(quoteId, deadline) on vault with msg.value = fromTotal (or payWithToken / payWithTokenPermit). Solana: transfer to vault + SPL memo = quoteId. TON: non-bounceable transfer to vault + comment = quoteId. |
| 4 | Track | GET /api/order?from_tx_hash=<ref> | one order per recipient; completed once to.txHash is set. ref = EVM tx hash, Solana signature, or the quoteId on TON. |
Ready-to-run scripts for every variant, in JavaScript and Python: Examples.
Endpoints
| Endpoint | Purpose |
|---|---|
GET /api/chains | Chains, tokens, pay targets. |
GET /api/quotes | TO-token rates and dispensable liquidity (not the quote endpoint). |
GET /api/prices · /prices/at | Live and historical FROM-token prices. |
POST /api/quote | Price and sign a swap. |
GET /api/order | Orders of one payment (from_tx_hash) or one order (id); &paginate=1 for big batches. |
GET /api/orders | A payer's history, view=batches for one row per payment. |
POST /api/orders/status | Bulk status by order id (≤ 500). |
GET /api/orders/load | Queue depth and your position (ETA). |
GET /api/orders/stream | Server-Sent Events when your orders change. |
Numbers to remember
| What | Value |
|---|---|
| Minimum order | $1 single recipient · $5 multisend |
| TO amount precision | 4 decimal places (whole sats on Bitcoin); ≥ 0.001 SOL per recipient on Solana |
| Quote lifetime | 180 s (deadline = expiry) |
| Recipients per quote | up to 10 000, one payment |
| Rate limits | 600 requests / min per IP · 10 quotes / min per IP · 30 quotes / min per sender |
| Amounts | base-unit integer strings (toAmounts, fromTotal); order history amounts are human decimals |
| Native coin | token address 0x0000000000000000000000000000000000000000 on every chain |
| Non-EVM FROM ids | Solana 1399811149 · TON 1667471768 (Solana testnet 1399811150, devnet 1399811151, TON testnet 1667471769) |
| Price | TO amount × listed rate, converted at the live Chainlink price; no extra fee. You pay the FROM chain's gas. |
Payment rules
Same payer as sender · same token as fromToken · exactly fromTotal · before deadline · one quoteId per payment. Anything else does not become an order — see Payment rules.
When something goes wrong
| You see | Meaning | Do |
|---|---|---|
400 BELOW_MIN_TOTAL | order under $1 / $5 | raise toAmounts |
400 NO_LIQUIDITY / 503 NO_TO_PRICE | that TO token can't be dispensed now | check GET /api/quotes, try later or another token |
429 RATE_LIMITED | too many requests / quotes | sleep Retry-After seconds |
503 WARMING_UP | backend restarting | retry in retryAfterSec |
revert Expired (EVM) | paid after deadline | request a new quote |
order failed | payout failed for that recipient | the FROM slice is refunded — see the refund field of the GET /api/order response |
| no order after paying | paid after deadline, or no usable quoteId in the memo / comment | a refund is recorded — refund on GET /api/order, or your history |
| no order, no refund | wrong payer / token / amount, or the same quote paid twice | Errors → held for review |
Every code with its fix: Errors.