Skip to main content
Breaking change (March 2026): The crosschain payment flow has been redesigned. The old payment-intent signing flow (POST /v2/request/payment-intents/:paymentIntentId) has been removed. Crosschain payments now return executable transaction calldata directly. See updated steps below.

Overview

Crosschain payments allow users to pay a request using a stablecoin from a different blockchain network than the one specified on the request. For example, a payer can pay a request for USDC on Base using USDT from their Optimism wallet. Crosschain routing is powered by LiFi, which aggregates bridges and DEXs to find optimal routes.

Benefits

  • Flexibility: Payers can pay with their preferred stablecoin on any supported chain.
  • Cost-Effective: Automated routing balances cost and speed.
  • Time-Saving: Payers don’t need to swap or bridge tokens manually.
  • Simplified UX: Payment settlement requires only 1 or 2 transactions from the payer.

Crosschain Payments Supported Chains and Currencies

For crosschain (and samechain) payments, the Request Network API supports USDC and USDT on 4 chains.
Bridged USDC (USDC.e) is not supported for crosschain payments. Only native USDC is supported.

Supported Chains

  • Ethereum
  • Arbitrum One
  • Base
  • OP Mainnet

Supported Currencies

Crosschain payments work only with mainnet funds (real money). Test networks are not supported.
  • USDC
  • USDT

How It Works

1

Create the request

Create a request with a paymentCurrency in the supported stablecoins and networks. The amount must be greater than 1 USD equivalent (e.g., at least 1.01 USDC) β€” crosschain routes are not available for amounts under $1 due to bridge minimums.Create the request via POST /v2/request.
2

Fetch payment routes

Fetch available routes with GET /v2/request//routes.Required query parameters:
  • wallet β€” the payer’s wallet address
Optional query parameters:
  • feePercentage and feeAddress β€” for platform fee inclusion in route calculations
The API returns routes ranked by fees and speed. Each route includes:
  • chain and token β€” the source chain and token
  • fee β€” total fee as a decimal
  • feeBreakdown[] β€” detailed fee components (gas, crosschain, platform)
  • speed β€” "FAST" for same-chain, seconds estimate for crosschain
The API may also return samechain routes when the payer has funds on the same chain as paymentCurrency.
Example routes response
{
  "routes": [
    {
      "id": "REQUEST_NETWORK_PAYMENT",
      "fee": 0,
      "feeBreakdown": [],
      "speed": "FAST",
      "chain": "BASE",
      "token": "USDC"
    },
    {
      "id": "ARBITRUM_BASE_USDT_USDC",
      "fee": 0.001,
      "feeBreakdown": [
        {
          "type": "crosschain",
          "stage": "sending",
          "provider": "lifi",
          "amount": "0.001",
          "amountInUSD": "0.001",
          "currency": "USDT"
        }
      ],
      "speed": 300,
      "chain": "ARBITRUM",
      "token": "USDT"
    }
  ]
}
3

Get payment calldata

Once the payer selects a route, fetch executable transaction calldata with GET /v2/request//pay.Query parameters:
  • wallet β€” the payer’s wallet address
  • chain β€” the source chain from the selected route (e.g., ARBITRUM)
  • token β€” the source token from the selected route (e.g., USDT)
Both chain and token must be provided together for crosschain payments. Omit both for same-chain payments.
The API returns a transactions array with ready-to-execute calldata:
Example crosschain response
{
  "transactions": [
    {
      "data": "0x095ea7b3...",
      "to": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
      "value": "0x0"
    },
    {
      "data": "0xabcdef...",
      "to": "0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE",
      "value": "0x0"
    }
  ],
  "metadata": {
    "stepsRequired": 2,
    "needsApproval": true,
    "approvalTransactionIndex": 0,
    "paymentTransactionIndex": 1,
    "routeType": "crosschain",
    "quoteExpiresAt": 1742205771,
    "hasEnoughBalance": true,
    "sourceAmount": "10.02"
  }
}
Metadata fields:
  • stepsRequired β€” number of transactions to execute (1 or 2)
  • needsApproval β€” whether a token approval transaction is needed first
  • approvalTransactionIndex β€” index of the approval tx in the array (or null)
  • paymentTransactionIndex β€” index of the payment/bridge tx
  • routeType β€” "crosschain" or "samechain"
  • quoteExpiresAt β€” unix timestamp when the route quote expires
  • hasEnoughBalance β€” whether the payer has sufficient funds
  • sourceAmount β€” the amount the payer needs to send on the source chain (includes bridge fees)
The API always includes approval transactions in crosschain calldata responses, even if the payer already has sufficient token allowance. This ensures USDT-style tokens (which require resetting allowance to zero before setting a new one) work correctly.
4

Execute the transactions

Send each transaction in the transactions array as a standard eth_sendTransaction. If needsApproval is true, execute the approval transaction first and wait for confirmation before sending the payment transaction.
import { createWalletClient, custom } from "viem";
import { arbitrum } from "viem/chains";

const walletClient = createWalletClient({
  chain: arbitrum,
  transport: custom(window.ethereum),
});

const [account] = await walletClient.getAddresses();

// Step 1: Send approval transaction (if needed)
if (metadata.needsApproval && metadata.approvalTransactionIndex != null) {
  const approvalTx = transactions[metadata.approvalTransactionIndex];
  const approvalHash = await walletClient.sendTransaction({
    account,
    to: approvalTx.to,
    data: approvalTx.data,
    value: BigInt(approvalTx.value || 0),
  });
  // Wait for confirmation before proceeding
  await publicClient.waitForTransactionReceipt({ hash: approvalHash });
}

// Step 2: Send payment/bridge transaction
const paymentTx = transactions[metadata.paymentTransactionIndex];
const paymentHash = await walletClient.sendTransaction({
  account,
  to: paymentTx.to,
  data: paymentTx.data,
  value: BigInt(paymentTx.value || 0),
});
After the payer broadcasts the crosschain transaction, payment detection happens automatically. The API monitors the bridge execution and sends webhook notifications when the payment is confirmed on the destination chain.

Custom fee configuration

Custom fee configuration is available. See Platform Fees for setup details (feePercentage, feeAddress) and implementation examples.