Skip to main content
Read endpoints (/networks, /quote, /sources, /destinations) are public — they work without a key. Send the key anyway so the environment and your app attribution are right. If auth fails: an invalid key returns 403 with {"error": {"code": "API_KEY_FORBIDDEN", "message": "Api key forbidden"}}. A missing key silently gives you public mainnet access — don’t mistake it for a working testnet setup.
1

Check the route and limits

Networks are identified by canonical ids like ETHEREUM_MAINNET — enumerate them with GET /networks, or use GET /sources / GET /destinations to see what’s routable from where.If the route doesn’t exist: 404{"error": {"code": "ROUTE_NOT_FOUND_ERROR", "message": "Route not found"}}. The pair isn’t currently supported; there is no partial success.If a parameter is malformed (bad enum value, missing required param): the API returns 400 with an empty body — no JSON. Treat empty-body 400s as validation failures and re-check parameter names and casing.
2

Get a quote

Every successful response is wrapped in data. Fee semantics live in Fees; avg_completion_time is a .NET-style duration string.
The quote response has no expiry field. What rate applies if the user deposits later, and how long a quote should be treated as indicative, is pending a product answer. Until then: do not present receive_amount as guaranteed.
If the amount is out of range: compare against the /limits response from step 1 — quotes for amounts outside min/max fail.
3

Create the swap

The response contains the swap (data.swap.id) and data.deposit_actions — the instructions for funding it. Store the id; it’s your handle for tracking.
When refund_address is required (routes involving a swap provider) and what error you get without it is unconfirmed. Recommendation until answered: always supply refund_address on the source network.
Whether reference_id deduplicates retries (idempotency) is unconfirmed — until then, guard against double-creating swaps on your side.
4

Fund the swap

Each entry in deposit_actions tells you where and how to send the funds — to_address, amount, amount_in_base_units, and for contract interactions call_data. For this direct transfer, have the user’s wallet send the exact amount to to_address on the source network.Other funding methods use the same swap object with different flags: Depository contract calls (use_depository) and gasless signatures (use_gasless).If the user sends an invalid amount: inspect fail_reason; the swap may enter the refund flow. If the user never sends: the swap moves to expired after six hours. See Swap lifecycle & statuses instead of inferring recovery behavior.
5

Track to completion

data.swap.status walks the lifecycle: user_transfer_pending → deposit detected → ls_transfer_pendingcompleted. Terminal failure states are failed, expired, and refunded. The full state machine is in Swap lifecycle & statuses; the separate PascalCase query vocabulary is in Track swaps.You can also look a swap up by its funding transaction: GET /swaps/by_transaction_hash/{hash}.
Recommended polling cadence and webhook delivery semantics are unconfirmed. Poll conservatively, back off on failures, and configure Webhooks in the Partner Dashboard.

Next steps