Crosschain Payments
Pay requests using stablecoins from any supported network, without manual bridging or token swaps.
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.
Benefits
Flexibility: Payers can pay with their preferred currency.
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 signatures from the Payer.
Supported Networks
Crosschain payments are supported on the following blockchain networks:
Base
Optimism
Arbitrum
Ethereum
Supported Stablecoins
Warning: Crosschain payments work only with mainnet funds (real money). Test networks are not supported.
The following stablecoins are supported for crosschain payments on both the sending and receiving networks.
USDC
USDT
DAI
How it works
1. Request creation
To enable crosschain payments, the request must be created with the following parameters:
paymentCurrency
included in the Supported Stablecoins and Supported Networks.amount
greater than 1 - executing crosschain payments under 1 stablecoins is not allowed, even though creating requests has no restrictions onamount
.
For more details about creating requests, please see the POST /v2/request endpoint.
2. Payment route fetching
To display a list of possible routes for a given request and payer address, use the GET /v2/request/{requestId}/routes endpoint. It returns all of the possible routes based on the payer's token balances.
Route Ranking
The API automatically ranks available payment routes based on the following factors:
Transaction fees
Processing speed
Routes that offer a balanced combination of lower fees and faster processing times are ranked higher in the results.
Fee breakdown
When fetching payment routes, each route displays the total estimated fees in the payment currency. This fee represents the combined costs associated with processing the transaction, including:
Gas Fees:
The total fee includes all gas costs incurred by the payment processor wallet for processing the transaction. This covers:
- Transferring tokens from the payer's wallet.
- Approving the payment execution smart contract.
- Executing the crosschain payment transaction.
For tokens supporting EIP-2612:
- The payment processor wallet also covers for the onchain permit transaction.
For tokens that do not support EIP-2612:
- The payer must perform an onchain approval transaction and pay for the gas fee directly. This fee is not included in the total fee shown for the route.
Service Fees:
The total fees also include any service fees charged by the crosschain infrastructure for facilitating transfers or swaps between different blockchains.
Samechain routes
The API may return samechain routes if the payer address has supported currencies on the same chain as the paymentCurrency
.
Example:
paymentCurrency
is USDC on Base, and the payer has USDT on BaseGasless transactions - the transaction fees are added on top of the request amount
No native token (ETH, etc..) needed for gas
Get the payment routes for a request
The requestId of the request
01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb
The wallet address of the payer
0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7
The amount to pay, in human readable format
Fee percentage to apply at payment time (e.g., '2.5' for 2.5%)
Address to receive the fee
API key for authentication
GET /v2/request/{requestId}/routes HTTP/1.1
Host: api.request.network
x-api-key: text
Accept: */*
{
"routes": [
{
"id": "REQUEST_NETWORK_PAYMENT",
"fee": 0,
"speed": "FAST",
"price_impact": 0,
"chain": "MAINNET",
"token": "REQ"
}
]
}
3. Getting payment calldata
Once the route is selected, the payer needs to fetch the unsigned payment calldata or intents.
If the selected route is a crosschain payment, the GET /v2/request/{requestId}/pay endpoint returns an unsigned payment intent. It will also return an unsigned approval permit or unsigned approval calldata, depending on whether the paymentCurrency
supports EIP-2612 Permit. For crosschain payments, this endpoint is NOT approval aware - it will return an approval permit or approval calldata even if approval has already been granted.
If the selected route is a direct payment, the GET /v2/request/{requestId}/pay returns an unsigned payment calldata. It may also return an approval calldata. For direct payments, this endpoint IS approval aware - it will omit the approval calldata if sufficient approval has already been granted.
Get the calldata needed to pay a request. For cross-chain payments, returns a payment intent that needs to be signed. For same-chain payments, returns transaction calldata. For off-ramp payments, use the query parameters clientUserId and paymentDetailsId.
The requestId of the request
01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb
The wallet address of the payer.
0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7
The source chain of the cross chain payment
The source token of the cross chain payment
The amount to pay, in human readable format
Optional client user ID for off-ramp payments
user-123
Optional payment details ID for off-ramp payments
fa898aec-519c-46be-9b4c-e76ef4ff99d9
Fee percentage to apply at payment time (e.g., '2.5' for 2.5%)
0.02
Address to receive the fee
0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7
API key for authentication
GET /v2/request/{requestId}/pay HTTP/1.1
Host: api.request.network
x-api-key: text
Accept: */*
{
"transactions": [
{
"data": "0xb868980b...00",
"to": "0x11BF2fDA23bF0A98365e1A4e04A87C9339e8687",
"value": {
"type": "BigNumber",
"hex": "0x038d7ea4c68000"
}
}
],
"metadata": {
"stepsRequired": 1,
"needsApproval": false,
"approvalTransactionIndex": null,
"hasEnoughBalance": true,
"hasEnoughGas": true
}
}
4. Signing the payment intent
The intents and calldata returned by the GET /v2/request/{requestId}/pay endpoint in the previous step must be signed by the payer's wallet to authorize the crosschain payment. The process for signing the approval varies depending on whether the paymentCurrency
supports EIP-2612 Permit, indicated by the metadata
response parameter.
"metadata": {
"supportsEIP2612": true
}
If the token does not support EIP-2612 Permit, the payer must sign and submit a standard ERC20 approval transaction.
import { ethers } from "ethers";
const ethersProvider = new ethers.providers.Web3Provider(
// Connected wallet provider
walletProvider as ethers.providers.ExternalProvider,
);
const signer = await ethersProvider.getSigner();
// Response from the `GET /request/{requestId}/pay` endpoint
const response = ...
const paymentIntent = JSON.parse(paymentData.paymentIntent);
const supportsEIP2612 = paymentData.metadata.supportsEIP2612;
let approvalSignature = undefined;
let approval = undefined;
if (supportsEIP2612) {
approval = JSON.parse(paymentData.approvalPermitPayload);
approvalSignature = await signer._signTypedData(
approval.domain,
approval.types,
approval.values,
);
} else {
const tx = await signer.sendTransaction(paymentData.approvalCalldata);
await tx.wait();
}
const paymentIntentSignature = await signer._signTypedData(
paymentIntent.domain,
paymentIntent.types,
paymentIntent.values,
);
const signedData = {
signedPaymentIntent: {
signature: paymentIntentSignature,
nonce: paymentIntent.values.nonce.toString(),
deadline: paymentIntent.values.deadline.toString(),
},
signedApprovalPermit: approvalSignature
? {
signature: approvalSignature,
nonce: approval.values.nonce.toString(),
deadline: approval?.values?.deadline
? approval.values.deadline.toString()
: approval.values.expiry.toString(),
}
: undefined,
};
5. Sending the signed data
Finally, the signed payment intent (and possibly the signed approval permit) are sent back to execute the crosschain payment via the POST /v2/request/payment-intents/{paymentIntentId} endpoint. It will handle all the necessary steps to complete the payment. A payment.complete
event will be sent to the platform's webhooks when the payment is completed.
Send a payment intent
The payment intent ID
01JNZYZPK7B4YBPD44TM72NDNJ
API key for authentication
POST /v2/request/payment-intents/{paymentIntentId} HTTP/1.1
Host: api.request.network
x-api-key: text
Content-Type: application/json
Accept: */*
Content-Length: 154
{
"signedPaymentIntent": {
"signature": "text",
"nonce": "text",
"deadline": "text"
},
"signedApprovalPermit": {
"signature": "text",
"nonce": "text",
"deadline": "text"
}
}
No content
Custom fee configuration
It will be possible in the future to add a custom fee to the payment, this is currently under development.
Last updated
Was this helpful?