SmallSwap SmallSwap

Getting started

Three calls and a confirmation. Most integrations are wired in an afternoon.

1. Pick a base URL

Clearnet for everything, onion when your stack has Tor. Same surface either way.

https://smallswap.io/api/v1
http://<onion>.onion/api/v1

Every response carries Onion-Location pointing at the onion equivalent. The two surfaces are byte-identical.

2. (Optional) Get a key

Anonymous calls work for reads and swap creation. Add a key for commission or higher rate limits.

  • Affiliate (aff_*) — self-serve from /affiliates. End-user commission on every swap routed through you.
  • Partner (prt_*) — issued out-of-band for wallet integrations and high-volume aggregators. Higher rate limits, webhook support.

3. Quote a swap

Source: 1 XMR. Destination: USDT on Tron.

curl 'https://smallswap.io/api/v1/new_rate?ticker_from=xmr&ticker_to=usdt&network_from=monero&network_to=tron&amount_from=1.0'

Response includes trade_id (the rate ID you'll pass to /new_trade), amount_to, rate, expires_at, and the fee breakdown. Full reference: /docs/api/new_rate.

4. Create the swap

Pass the user's destination address and an Idempotency-Key so retries don't double-create.

curl 'https://smallswap.io/api/v1/new_trade?ticker_from=xmr&ticker_to=usdt&network_from=monero&network_to=tron&amount_from=1.0&address=TXyourtronaddress' \
  -H 'Idempotency-Key: 01H...'

Response returns the same trade_id, plus address_provider (the XMR address your user sends to) and password (a recovery secret for the user; if no refund address was provided, this is how funds are recovered). Full reference: /docs/api/new_trade.

5. Poll status

curl 'https://smallswap.io/api/v1/trade?id=<trade_id>'

Status enum: awaiting_depositconfirmingprocessingsendingcompleted. Terminal states also include refunding / refunded, failed, expired. Poll every 10-30 seconds; partners can subscribe to webhooks instead.

Edge cases worth wiring early

  • Amount bounds. Every pair has a min and max. Below min returns 422 amount_below_min; above max returns 422 amount_above_max. Surface both with the details payload so users see actionable numbers.
  • Quote expiry. Quotes from /new_rate hold for 60 seconds. After that, /new_trade against an expired rate ID returns 409 quote_expired. Re-quote on the user's next action.
  • Address validation. Bad address → 422 address_invalid. Bitcoin addresses are checksum-validated; EVM/Tron/Solana use format checks. Validate client-side too — bad UX to round-trip for a typo.
  • Rate limits. Anonymous is 60 reads/min; affiliate is 300; partner is 6000. Exceed → 429 with Retry-After.

Full error catalog: /docs/api/errors.

Next