Rails
What is a rail?
A rail is a payment network adapter. It takes a verified, signed spend envelope and routes the payment through a specific financial infrastructure: Airwallex, Wise, Stripe, USDC on Base, or x402.
Envelopes are rail-agnostic. You declare which rails are allowed (allowedRails), and at dispatch time, the SDK selects the appropriate adapter.
Available rails
| Rail | ID | Best for | Settlement |
|---|---|---|---|
| Airwallex | airwallex | ACH, international wire, cross-border | 1–3 business days |
| Wise | wise | International wire, multi-currency accounts | 1–2 business days |
| Stripe | stripe | Card payments, Stripe-connected merchants | Instant (card) |
| USDC on Base | usdc-base | Crypto vendors, on-chain payables | ~2 seconds (Base L2) |
| x402 | x402 | HTTP-native AI-to-AI micropayments | Instant |
Rail selection
const envelope = createSpendEnvelope({ allowedRails: ['airwallex', 'wise'], // Envelope permits either // ...})
// At dispatch, specify which rail to use:const result = await executeAgentPayment(signed, { recipient: 'vendor@example.com', amount: 100, rail: 'wise', // Must be in envelope.allowedRails})If rail is omitted from executeAgentPayment(), the SDK uses PQSAFE_DEFAULT_RAIL from your environment config.
Rail-specific configuration
Each rail requires API credentials in your environment:
# AirwallexAIRWALLEX_CLIENT_ID=...AIRWALLEX_API_KEY=...
# WiseWISE_API_TOKEN=...WISE_PROFILE_ID=...
# StripeSTRIPE_SECRET_KEY=sk_live_...
# USDC on BaseWALLET_PRIVATE_KEY=0x...BASE_RPC_URL=https://mainnet.base.org
# x402X402_FACILITATOR_URL=https://x402.org/facilitatorError handling across rails
Rail failures are typed and recoverable:
import { executeAgentPayment, PQSafeError } from '@pqsafe/agent-pay'
try { const result = await executeAgentPayment(signed, { recipient, amount })} catch (err) { if (err instanceof PQSafeError) { switch (err.code) { case 'RAIL_TIMEOUT': // Retry with exponential backoff break case 'INSUFFICIENT_BALANCE': // Notify operator — rail account needs top-up break case 'RECIPIENT_REJECTED': // Recipient bank/wallet rejected the transfer break case 'RAIL_NOT_ALLOWED': // Envelope doesn't permit this rail break } }}