POST /tx-status until the provider reports success or failure.
The lifecycle
1
Confirm the source chain
Transfers can start on Ethereum, Optimism, BNB Chain, Polygon, Arbitrum and Avalanche. See Where a transfer can start.
2
Quote the transfer
POST /quotes with mode: "cross-chain" and fromChainId, toChainId (integers), inTokenAddress, outTokenAddress, amount and slippage. The quote names the provider in aggregatorId, the bridge in bridgeInfo, and the expected and minimum amounts on the destination chain. Unknown top-level keys are rejected with 400.3
Build the transaction
POST /swap with mode: "cross-chain", the aggregatorId from the quote, the account that sends on the source chain and receives on the destination chain, and the same chains, tokens, amount and slippage. Don’t send dryRun: cross-chain requests reject it with 400. The response returns to, calldata, value, contractToApprove and dexHash.4
Send on the source chain
For ERC-20 input, approve
contractToApprove for the exact input amount. Estimate gas yourself, then send {to, data: calldata, value, gas} from account on the source chain, right after /swap. A 200 from /swap doesn’t guarantee that the calldata executes: if eth_estimateGas reverts while the allowance and the balance are in order, don’t send it. Request a new quote and build again.5
Track to completion
POST /tx-status with the source transaction hash, the source chainId and the dexHash from /swap. Poll with backoff until status is a success or failure value.Field names across endpoints
The quote, the swap and the status call use these fields:Single-chain swaps return the calldata as
data; cross-chain swaps return it as calldata. Map it to the data field of the transaction you send.Providers and bridges
The quote’saggregatorId names the cross-chain provider. Signed requests from API accounts are quoted and built with okx or rango. Pass the value to /swap unchanged.
The provider picks the bridge. bridgeInfo.displayName names it, and bridgeInfo.icon is a logo URL that can be empty. Show the bridge name to your users: it tells them which protocol carries their funds between chains.
middlewareRoute lists the swaps around the bridge: chainFrom on the source chain before bridging, and chainTo on the destination chain after it. Each entry names its fromAsset and toAsset with address, decimals and symbol. In this quote for 10 USDT on Polygon to USDT on Ethereum, the provider is rango and the bridge is BOB Gateway. chainFrom is empty, and chainTo holds one entry, from USDT on Polygon to USDT on Ethereum. integratorFeeBreakdown reports the Olympex protocol fee in base units of the source token:
Quote
middlewareRoute, a native token can appear as 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE or as the zero address, 0x0000000000000000000000000000000000000000, depending on the provider. Treat both as native, and compare addresses case-insensitively.
Amounts, costs and timing
In the quote above, 10 USDT on Polygon returns
toTokenAmount "9985000" and minimumReceived "9885149". USDT on Ethereum has 6 decimals, so the user expects 9.985 USDT on Ethereum and receives at least 9.885149. The protocol fee, protocolFeeAmount "15000", is in the source token: 0.015 USDT on Polygon, 0.15% of the input.
Where a transfer can start
A transfer can start on Ethereum (1), Optimism (10), BNB Chain (56), Polygon (137), Arbitrum (42161) and Avalanche (43114). Base (8453) and Linea (59144) support single-chain swaps but can’t start a transfer. Whether a specific pair has a route depends on the providers at the time you ask, so request a quote to confirm it. Supported chains has the full matrix.
Tracking a transfer
Store three values as soon as you broadcast: the source transaction hash, the source chain ID and thedexHash from /swap. They are all POST /tx-status needs:
chainId is an integer, and dexHash goes in lowercase. The response always carries status, detailStatus, fromChainId and toChainId, and adds fromTxHash, toTxHash, fromAmount, toAmount, fromTokenAddress, toTokenAddress and bridgeHash when the provider reports them. fromAmount and toAmount are as the provider reports them, and their unit isn’t normalized: check it before you do arithmetic. errorMsg is always null in a 200 response: provider errors surface as 500 with TX_STATUS_ERROR instead. Show detailStatus to users, not errorMsg.
status is the provider’s own value, so match it against both lists exactly:
detailStatus is the provider’s sub-status or message; show it, but don’t branch on it.
POST /tx-status returns 500 with TX_STATUS_ERROR when the provider has no status for the transfer yet, which is common right after broadcast, and for transfers the provider marks as failed. Treat it as “status unknown”, not as a final answer. Keep polling with backoff, for example every 15 to 30 seconds. If the status stays unknown, check the source transaction on a block explorer, then contact partners@olympex.io with the meta.requestId of your last call and the source transaction hash.
For a single-chain swap, or the source transaction of a transfer, the transaction receipt is the result: read it from your RPC or poll GET /transactions/{hash}. That endpoint reads the receipt on one chain, not the bridge.
What this means for your integration
- Send
/swapthe quote’sparamsunchanged, plusaccountand the quote’saggregatorId. - Persist the source hash, source chain ID and lowercase
dexHashthe moment you broadcast. Without them you can’t track the transfer. - Show the bridge name,
minimumReceivedin destination-token units andestimatedTimewhen the provider reports it. - Poll until a success or failure value, and treat
TX_STATUS_ERRORas “not known yet”.
Related
Cross-chain swap end-to-end
The full walkthrough, from quote to destination.
Track a swap to finality
Polling, backoff and final states.
Get cross-chain transfer status
The
POST /tx-status reference.Supported chains
Chains, chain IDs and token addresses.
