Cross-chain bridge
Bridge tokens between chains — non-custodial settlement via Across.
Orkid's bridge endpoints proxy Across for cross-chain settlement between Ethereum, Base, Arbitrum, and Polygon. The flow is non-custodial: Orkid never receives or holds user funds. The user signs the approval and deposit transactions directly against canonical Across contracts from their own wallet.
How it works
GET /api/v1/bridge/chains— supported chains (all four Orkid chains)GET /api/v1/bridge/tokens?chainId=— curated bridgeable assets per chainPOST /api/v1/bridge/quote— executableapprovalTxns+swapTxthe user signsGET /api/v1/bridge/status— deposit lifecycle (pending → filled / expired / refunded)POST /api/v1/bridge/track— register a submitted deposit for tracking
Unlike same-chain swaps, bridging does not use Permit2 and is not gasless in v1 — the user pays origin-chain gas and submits plain approve + deposit transactions.
Honest risk note: after the deposit transaction confirms, funds sit in Across escrow until a relayer fills (usually seconds). If a deposit can't be filled, it is refunded to the depositor's wallet on the origin chain — refunds can take a few hours. Orkid has zero custody at every step, but bridge settlement time is protocol-inherent.
GET /api/v1/bridge/chains
List the chains that support bridging. The list is filtered server-side to Orkid's production chains.
GET https://orkidlabs.xyz/api/v1/bridge/chains
X-ORKID-API-Key: <key>{
"ok": true,
"chains": [
{ "chainId": 1, "name": "Ethereum", "publicRpcUrl": "...", "explorerUrl": "https://etherscan.io", "logoUrl": "..." },
{ "chainId": 8453, "name": "Base", "publicRpcUrl": "...", "explorerUrl": "https://basescan.org", "logoUrl": "..." },
{ "chainId": 42161, "name": "Arbitrum", "publicRpcUrl": "...", "explorerUrl": "https://arbiscan.io", "logoUrl": "..." },
{ "chainId": 137, "name": "Polygon", "publicRpcUrl": "...", "explorerUrl": "https://polygonscan.com", "logoUrl": "..." }
]
}GET /api/v1/bridge/tokens
List curated bridgeable assets on a chain. Bridging is restricted to major assets — arbitrary tokens are rejected.
GET https://orkidlabs.xyz/api/v1/bridge/tokens?chainId=8453
X-ORKID-API-Key: <key>| Parameter | Type | Required | Description |
|---|---|---|---|
chainId | number | Yes | 1, 8453, 42161, or 137 |
{
"ok": true,
"tokens": [
{ "chainId": 8453, "address": "0x833589fc...", "symbol": "USDC", "name": "USD Coin", "decimals": 6 },
{ "chainId": 8453, "address": "0x42000000...", "symbol": "WETH", "name": "Wrapped Ether", "decimals": 18 }
]
}POST /api/v1/bridge/quote
Get an executable bridge quote. Returns the transactions the user must sign — ERC20 approvalTxns first (if required), then the swapTx deposit.
Every returned transaction is validated server-side before reaching you: canonical Across contract targets only, depositor and recipient embedded in calldata, refund pinned to the depositor on the origin chain, quote expiry enforced, and upstream simulation must succeed.
Request
POST https://orkidlabs.xyz/api/v1/bridge/quote
Content-Type: application/json
X-ORKID-API-Key: <key>
{
"originChainId": 8453,
"destinationChainId": 1,
"inputToken": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"outputToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"amount": "25000000",
"depositor": "0xYourWalletAddress"
}| Field | Type | Required | Description |
|---|---|---|---|
originChainId | number | Yes | Chain the funds leave from |
destinationChainId | number | Yes | Chain the funds arrive on (must differ) |
inputToken | string | Yes | Origin token address or symbol (curated set) |
outputToken | string | Yes | Destination token address or symbol (curated set) |
amount | string | Yes | Raw base-unit amount as a decimal string |
depositor | string | Yes | User wallet — signs the txs, receives refunds |
recipient | string | No | Destination recipient (defaults to depositor) |
tradeType | string | No | exactInput (default), minOutput, exactOutput |
slippage | number | "auto" | No | Defaults to auto |
Response
{
"ok": true,
"quote": {
"id": "0x…",
"inputToken": { "symbol": "USDC", "decimals": 6, "…": "…" },
"outputToken": { "symbol": "USDC", "decimals": 6, "…": "…" },
"inputAmount": "25000000",
"expectedOutputAmount": "24875000",
"minOutputAmount": "24850000",
"expectedFillTime": 7,
"quoteExpiryTimestamp": 1730000000,
"fees": { "…": "per-facet breakdown including the Orkid app fee" },
"checks": {
"allowance": { "balance": "…", "token": "…", "spender": "…" },
"balance": { "balance": "…", "token": "…" }
},
"approvalTxns": [
{ "chainId": 8453, "to": "0x833589fc…", "data": "0x095ea7b3…" }
],
"swapTx": {
"chainId": 8453,
"to": "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64",
"data": "0x…",
"value": "0",
"simulationSuccess": true
},
"recipient": "0xYourWalletAddress",
"refundAddress": "0xYourWalletAddress",
"refundOnOrigin": true
}
}Executing
- For each
approvalTxns[i], send{ to, data }fromdepositoronchainIdand wait for confirmation. - Send
swapTx({ to, data, value }) fromdepositor— this is the Across deposit. - Poll
/api/v1/bridge/statusuntilfilled.
Reject and re-quote if simulationSuccess is false or Date.now() / 1000 >= quoteExpiryTimestamp.
Fees
Bridge quotes carry an Orkid app fee of 10 bps (appFee=0.001), taken in the output token on the destination chain and disclosed inside fees in the response. Relayer and LP fees from Across are itemized there as well.
GET /api/v1/bridge/status
Track a deposit through its lifecycle.
| Parameter | Type | Required | Description |
|---|---|---|---|
depositTxnRef | string | Either/or | Origin deposit transaction hash |
originChainId + depositId | number + string | Either/or | Across deposit id pair |
GET https://orkidlabs.xyz/api/v1/bridge/status?depositTxnRef=0x…
X-ORKID-API-Key: <key>{
"ok": true,
"deposit": {
"status": "filled",
"depositId": "…",
"depositTxHash": "0x…",
"fillTx": "0x…",
"destinationChainId": 1
}
}| Status | Meaning |
|---|---|
pending | Deposit seen, waiting for a relayer fill |
filled | Funds delivered on the destination chain (fillTx) |
expired | Fill deadline passed — refund will process on origin |
refunded | Refund executed to the depositor's origin wallet |
POST /api/v1/bridge/track
Register a submitted deposit for status reconciliation and volume attribution. Metadata only — call after the origin transaction confirms.
POST https://orkidlabs.xyz/api/v1/bridge/track
Content-Type: application/json
X-ORKID-API-Key: <key>
{
"originChainId": 8453,
"destinationChainId": 1,
"depositor": "0x…",
"recipient": "0x…",
"inputToken": "0x833589fc…",
"outputToken": "0xa0b86991…",
"amountInRaw": "25000000",
"expectedOutRaw": "24875000",
"quoteId": "0x…",
"originTxHash": "0x…"
}{ "ok": true, "settlementId": "…" }Error responses
| Code | Cause |
|---|---|
MALFORMED_REQUEST | Invalid chain ids, token addresses, amounts, or addresses |
UNSUPPORTED_CHAIN | Origin/destination outside the four supported chains |
UNSUPPORTED_TOKEN | Token outside the curated bridge set |
QUOTE_EXPIRED | Quote expiry passed — re-quote |
SIMULATION_FAILED | Across could not simulate the deposit — check balance/allowance and retry |
UPSTREAM_ERROR | Across API failure — safe to retry |