Skip to main content
A cross-chain transfer is one transaction on the source chain and one outcome on the destination chain. You quote it, build its calldata, and send a single transaction from your wallet on the source chain. A cross-chain provider runs the rest of the route: the bridge, plus any swaps it needs on either side. You follow the result with 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’s aggregatorId 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
In 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.
Don’t use a cross-chain estimatedGas or gasLimit as the gas limit of your transaction. The unit varies by provider. Estimate gas with eth_estimateGas on the source chain and add a buffer, as described in Gas and fees.

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 the dexHash 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 /swap the quote’s params unchanged, plus account and the quote’s aggregatorId.
  • Persist the source hash, source chain ID and lowercase dexHash the moment you broadcast. Without them you can’t track the transfer.
  • Show the bridge name, minimumReceived in destination-token units and estimatedTime when the provider reports it.
  • Poll until a success or failure value, and treat TX_STATUS_ERROR as “not known yet”.

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.