Skip to main content

Documentation Index

Fetch the complete documentation index at: https://anypay-docs-sdk-0-15-0-updates.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Pay with Trails

Trails enables cross-chain 1-click payments — users pay with whatever token they hold, from any supported chain, and you receive exactly the amount and token you specify.
You settle inUser pays withTrails handles
USDC on PolygonETH on ArbitrumBridge + Swap
USDC on PolygonPOL on PolygonSwap
USDC on BaseUSDC on BaseNormal execution

Use cases

Pay flows are exact-output by default. You specify the amount the recipient receives, and Trails calculates what the user needs to send (including fees).
  • Purchase and mint an NFT from any chain
  • Accept crypto payments in an ecommerce flow
  • Transfer a fixed amount to a user
  • Make an x402 payment in any token from any chain
  • Execute smart contract calls with an attached payment

Examples

Accept USDC on Polygon

import { Pay } from '0xtrails/widget'

<Pay
  apiKey="YOUR_API_KEY"
  to={{
    recipient: "0xYourMerchantAddress",
    currency: "USDC",
    chain: "polygon",
    amount: "25",
  }}
  onPaymentSuccess={({ sessionId }) => {
    updateOrderStatus(orderId, 'paid', sessionId)
  }}
>
  <button>Pay $25</button>
</Pay>

Cross-chain USDC with CCTP

Use Circle’s CCTP for native USDC bridging:
<Pay
  apiKey="YOUR_API_KEY"
  to={{
    recipient: "0xYourMerchantAddress",
    currency: "USDC",
    chain: "polygon",
    amount: "500",
  }}
  bridgeProvider="CCTP"
  onPaymentSuccess={({ sessionId }) => processLargePayment(sessionId)}
>
  <button>Pay $500</button>
</Pay>

NFT purchase on Arbitrum

Users pay from any token; Trails converts to ETH and executes the mint:
import { Pay } from '0xtrails/widget'
import { encodeFunctionData } from 'viem'
import { nftABI } from './abi.ts'

export const CrossChainNFTPurchase = () => {
  const NFT_CONTRACT = "0xAA3df3c86EdB6aA4D03b75092b4dd0b99515EC83"

  const purchaseCalldata = encodeFunctionData({
    abi: nftABI,
    functionName: 'mint',
    args: ["0x97c4a952b46becad0663f76357d3776ba11566e1"],
  })

  return (
    <Pay
      apiKey="YOUR_API_KEY"
      to={{
        recipient: NFT_CONTRACT,
        currency: "ETH",
        chain: "arbitrum",
        amount: "0.00002",
        calldata: purchaseCalldata,
      }}
      onPaymentSuccess={({ sessionId }) => {
        console.log('NFT purchased:', sessionId)
      }}
      onPaymentError={({ sessionId, error }) => {
        console.error('Purchase failed:', sessionId, error)
      }}
    >
      <button>Buy NFT (0.00002 ETH)</button>
    </Pay>
  )
}

Merchant integration pattern

Complete ecommerce checkout with order verification:
import { Pay } from '0xtrails/widget'
import { useState } from 'react'

export function CheckoutButton({ order }) {
  const [status, setStatus] = useState('pending')

  return (
    <Pay
      apiKey={process.env.NEXT_PUBLIC_TRAILS_API_KEY}
      to={{
        recipient: process.env.NEXT_PUBLIC_MERCHANT_WALLET,
        currency: "USDC",
        chain: "polygon",
        amount: order.total.toString(),
      }}
      onPaymentStart={({ sessionId }) => {
        createPaymentRecord({ orderId: order.id, sessionId, status: 'processing' })
        setStatus('processing')
      }}
      onPaymentSuccess={async ({ sessionId }) => {
        const verified = await verifyPayment(sessionId)
        if (verified) {
          await fulfillOrder(order.id)
          setStatus('complete')
        }
      }}
      onPaymentError={({ sessionId, error }) => {
        logPaymentError(sessionId, error)
        setStatus('failed')
      }}
    >
      <button disabled={status === 'processing'}>
        {status === 'processing' ? 'Processing...' : `Pay $${order.total}`}
      </button>
    </Pay>
  )
}

Backend payment verification

Verify payments server-side before fulfilling orders:
// api/verify-payment.ts
import { Trails } from '@0xtrails/api'

const trails = new Trails({ accessKey: process.env.TRAILS_ACCESS_KEY })

export async function verifyPayment(sessionId: string, expectedAmount: string) {
  const receipt = await trails.getIntentReceipt({ intentId: sessionId })

  if (receipt.status !== 'COMPLETED') {
    return { verified: false, reason: 'Payment not completed' }
  }

  const receivedAmount = receipt.destinationTransaction?.amount
  if (receivedAmount !== expectedAmount) {
    return { verified: false, reason: 'Amount mismatch' }
  }

  return { verified: true, receipt }
}

API-based fee estimation

For server-side fee estimation or custom UIs:
const quote = await fetch('https://trails-api.sequence.app/rpc/Trails/QuoteIntent', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY',
  },
  body: JSON.stringify({
    ownerAddress: userWallet,
    originChainId: 137,
    originTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
    destinationChainId: 8453,
    destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    destinationToAddress: merchantAddress,
    destinationTokenAmount: '100000000', // 100 USDC (6 decimals)
    tradeType: 'EXACT_OUTPUT',
    options: { slippageTolerance: 0.005 },
  }),
})

const { intent } = await quote.json()

Next steps

Pay mode reference

Complete configuration options and props

Gasless payments

Let users pay fees in stablecoins

x402 payments

HTTP 402 payment flows with Trails