X-API-Key).
Base, Arbitrum, Avalanche and Celo are newly supported. They work the same way as the
other EVM chains (native coin + USDC/USDT), but have had less production traffic than
ETH/BSC/POL — test with small amounts first.
Base URL:
https://api.rach.finance/api/v1/ · Auth: X-API-KeyWhat you can hold on each chain
GET /wallet/assets returns the exact asset list configured for your current
environment — read it at runtime rather than hard-coding this table. It also returns
transfers_enabled, which is false on a test key.
Numbers in brackets are the asset’s decimals.
BASE, ARB, AVAX, CELO and XRP have no sandbox. They exist on live keys only, so build
those flows against a live key and small amounts. A test key asking for them is refused with
… is not configured for this environment.ETHEREUM, POLYGON, MATIC, BNB, TRON, SOLANA,
BITCOIN, LITECOIN, RIPPLE, ARBITRUM and AVALANCHE all resolve to the codes above.
1. Create a customer wallet
One wallet per customer (idempotent percustomer_id).
Response
2. Derive a deposit address
Create a receive address on a specific chain. Setenable_monitoring: true to have Rach
watch it for deposits and fire webhooks.
Response
network is one of BTC BCH LTC ETH BSC POL TRX SOL XRP BASE ARB AVAX CELO. Share address with your
customer to receive funds.
3. Read balances
Balances are served from Rach’s database, which our monitor keeps in step with the chain (raising it on deposits, lowering it on spends). Reading them is free and instant, so you can poll this as often as your UI needs.Response
as_of is when we last read that figure from the chain, and source is database or
chain.
Refreshing
?refresh=true does not block on a chain read — it returns right away and schedules
the refresh, replying with refresh_requested: true and refresh_eta_seconds. Poll again
after that interval to see the updated figure. Many concurrent refresh requests collapse
into a single chain read, so a “pull to refresh” button is safe to wire directly to it.Spendable vs balance
spendable is what can actually be sent right now, and it is not always equal to balance:
- XRP —
spendableexcludes the locked ~1 XRP base reserve. - BTC / LTC / BCH — with
?live=trueyou also getconfirmed;balancemay include unconfirmed (0-conf) funds that cannot be spent yet. - Everything else —
spendableequalsbalance.
4. Quote a transfer
POST /wallet/{customer_id}/transfer-quote takes the same body as the transfer and
returns what would happen, without sending anything. Use it to show your customer the
real delivered figure before they confirm.
Response
Quote amounts come back in base units (
unit: "base"), whatever unit you sent — divide
by 10^decimals to display them. recipient_amount is gross_amount minus your
WaaS fee; the TRON sponsorship fee below is applied separately at
settlement.fee_quote_hash back on the transfer and the send is refused with
409 and code: "quote_changed" if your fee configuration moved in between. Omit it and
the transfer proceeds at whatever the fee is when it lands.
5. Send crypto out
amount is a string; unit is decimal (whole coins, default) or base (wei/satoshi).
Response
XRP transfers accept a
destination_tag. For chains that need it, gas/fees are handled
by Rach and reported back in fee_amount / gas_fee.6. Check a transfer’s status
A transfer’s HTTP response tells you it was submitted, not that it confirmed. Read the outcome back with theIdempotency-Key you sent:
Response
WaaS fee collection
You can charge your own fee on every customer transfer. Rach deducts it from the transfer amount and sends it on-chain directly to your address — Rach never holds it.
USD figures (
fee_cap_usd, flat_fee_usd) are converted to the asset at the current market
rate; stablecoins convert 1:1. On UTXO chains (BTC/LTC/BCH) the fee is an extra output in the
same transaction, so fee_tx_hash is empty. On every other chain it is a second transaction.
Read your earnings with GET /wallet/earnings.
Sending USDT on TRON without TRX
TRON does not work like the EVM chains, and this trips up nearly every integration:- A TRON address does not exist on-chain until it receives something. An unactivated address cannot send anything at all, no matter how much USDT it holds.
- A USDT (TRC-20) transfer costs ENERGY. Without it, the sender burns TRX — often 13–30 TRX per transfer. A customer holding only USDT is otherwise stuck.
This is a platform-level fee for TRON network costs. It is separate from — and additional
to — any WaaS fee you configure for yourself.
More endpoints
Full schemas are in the Payments API Reference under
WaaS. Deposits are detected automatically — see 24/7 Monitoring.

