Skip to content

Payment Integration

Payment Integration Guide

This guide covers how to integrate x402 payments with the Bridge402 API.

Overview

Bridge402 uses the x402 payment protocol to bridge Web2 APIs to Web3. All API endpoints require payment verification through the X-PAYMENT header, enabling crypto-native access to premium APIs that traditionally required subscriptions or credit cards.

Why x402 Payments? - AI Agent Friendly: Autonomous agents can make payments programmatically - No Subscriptions: Pay-per-use model perfect for intermittent access - Multi-chain: Supports both Base (EVM) and Solana networks - Micro-payments: Small, granular payments enable cost-effective access

Payment Flow

1. Request Payment Requirements

Make a request without the X-PAYMENT header to get payment requirements:

curl -X POST "https://bridge402.tech/connect" \
  -d "duration_min=10"

Response (402 Payment Required):

{
  "x402Version": 1,
  "error": "X-PAYMENT header is required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "10000",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0x745221d90e41193ee85c9d4679e40a9B57898A47",
      "resource": "https://bridge402.tech/stream",
      "description": "Access to Bridge402 crypto news stream for 10 minute(s)",
      "mimeType": "application/json",
      "maxTimeoutSeconds": 120,
      "extra": {
        "name": "USD Coin",
        "version": "2",
        "product": "Bridge402 News — 10 min",
        "minutes": 10,
        "resourcePath": "/stream"
      }
    }
  ]
}

2. Generate Payment

Use the x402-python library to generate payment authorization:

from x402 import X402Client
from x402.schemes.exact import ExactScheme

# Initialize client
client = X402Client(private_key, network="base")

# Create payment
payment = client.create_payment(
    scheme=ExactScheme(),
    amount=10000,  # 0.01 USDC in atomic units
    asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    pay_to="0x745221d90e41193ee85c9d4679e40a9B57898A47",
    resource="https://bridge402.tech/stream",
    description="Access to Bridge402 crypto news stream for 10 minute(s)"
)

# Encode payment
payment_b64 = payment.encode()

3. Submit Payment

Include the payment in the X-PAYMENT header:

curl -X POST "https://bridge402.tech/connect" \
  -H "X-PAYMENT: <base64-encoded-payment>" \
  -d "duration_min=10"

Payment Requirements

Supported Networks

  • Base Mainnet (EVM): base
  • USDC Asset: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
  • Uses EIP-3009 authorization flow

  • Solana Mainnet: solana or sol

  • USDC Mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  • Uses transaction-based payments with feePayer support

Pricing

  • News Stream: $0.0035 USDC per minute
  • 5 minutes: $0.0175 USDC (17,500 atomic units)
  • 10 minutes: $0.035 USDC (35,000 atomic units)
  • 60 minutes: $0.21 USDC (210,000 atomic units)
  • Earnings Transcripts: $0.05 USDC per document (50,000 atomic units)
  • Minimum Purchase: 5 minutes ($0.0175 USDC)

Amount Calculation

def calculate_amount(minutes: int) -> int:
    """Calculate payment amount in USDC atomic units"""
    rate_per_minute = 0.0035  # USDC per minute
    usdc_decimals = 6
    return int(minutes * rate_per_minute * (10 ** usdc_decimals))

# Examples:
# 5 minutes = 17,500 atomic units (0.0175 USDC)
# 10 minutes = 35,000 atomic units (0.035 USDC)
# 60 minutes = 210,000 atomic units (0.21 USDC)

Payment Schemes

Exact Scheme

Bridge402 uses the "exact" payment scheme, which requires:

  • Exact Amount: Payment must match exactly (no overpayment)
  • Network: Base mainnet (EVM) or Solana mainnet
  • Asset: USDC with 6 decimals (same on both networks)
  • Timeout: 120 seconds for payment verification
  • Solana-Specific: Requires feePayer address (provided in invoice extra.feePayer)

Payment Payload Structure

Base (EVM) Payment:

{
  "x402Version": 1,
  "scheme": "exact",
  "network": "base",
  "payload": {
    "signature": "0x...",
    "authorization": "0x...",
    "transaction": "0x..."
  }
}

Solana Payment:

{
  "x402Version": 1,
  "scheme": "exact",
  "network": "solana",
  "payload": {
    "transaction": "base64-encoded-partially-signed-transaction"
  }
}

Note: Solana payments only require a transaction field in the payload. The transaction must be partially signed (payer signs, facilitator completes).

Integration Examples

Python Integration

import asyncio
import httpx
from x402 import X402Client
from x402.schemes.exact import ExactScheme

class Bridge402Client:
    def __init__(self, api_url: str, private_key: str):
        self.api_url = api_url
        self.x402_client = X402Client(private_key, network="base")

    async def create_payment(self, minutes: int, resource_path: str) -> str:
        """Create x402 payment for specified duration"""
        amount = int(minutes * 0.0035 * 1_000_000)  # USDC atomic units

        payment = self.x402_client.create_payment(
            scheme=ExactScheme(),
            amount=amount,
            asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
            pay_to="0x745221d90e41193ee85c9d4679e40a9B57898A47",
            resource=f"{self.api_url}{resource_path}",
            description=f"Bridge402 access for {minutes} minutes"
        )

        return payment.encode()

    async def connect(self, minutes: int) -> dict:
        """Connect to Bridge402 with payment"""
        payment_data = await self.create_payment(minutes, "/stream")

        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.api_url}/connect",
                params={"duration_min": minutes},
                headers={"X-PAYMENT": payment_data}
            )

            if response.status_code == 200:
                return response.json()
            else:
                raise Exception(f"Payment failed: {response.text}")

JavaScript Integration

// Note: JavaScript x402 integration would require a library
// This is a conceptual example

class Bridge402Client {
  constructor(apiUrl, privateKey) {
    this.apiUrl = apiUrl;
    this.privateKey = privateKey;
  }

  async createPayment(minutes, resourcePath) {
    // In production, use a proper x402 JavaScript library
    const amount = minutes * 0.002 * 1_000_000; // USDC atomic units

    const payment = {
      x402Version: 1,
      scheme: "exact",
      network: "base",
      payload: {
        signature: "0x...", // Generated by x402 library
        authorization: "0x...", // Generated by x402 library
      }
    };

    return btoa(JSON.stringify(payment));
  }

  async connect(minutes) {
    const paymentData = await this.createPayment(minutes, "/stream");

    const response = await fetch(`${this.apiUrl}/connect`, {
      method: 'POST',
      headers: {
        'X-PAYMENT': paymentData,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ duration_min: minutes })
    });

    if (response.ok) {
      return await response.json();
    } else {
      throw new Error(`Payment failed: ${response.statusText}`);
    }
  }
}

Error Handling

Payment Errors

402 Payment Required
{
  "x402Version": 1,
  "error": "X-PAYMENT header is required",
  "accepts": [...]
}
402 Payment Verification Failed
{
  "detail": "Payment verification failed: invalid signature"
}
402 Payment Settlement Failed
{
  "detail": "Payment must be settled: insufficient funds"
}

Error Handling Strategy

async def handle_payment_error(response):
    """Handle payment-related errors"""
    if response.status_code == 402:
        data = response.json()

        if "accepts" in data:
            # Payment required - show payment requirements
            print("Payment required:")
            for accept in data["accepts"]:
                print(f"  Amount: {accept['maxAmountRequired']} atomic units")
                print(f"  Asset: {accept['asset']}")
                print(f"  Pay To: {accept['payTo']}")
        else:
            # Payment verification failed
            print(f"Payment failed: {data.get('detail', 'Unknown error')}")

    elif response.status_code == 400:
        print("Bad request - check parameters")

    else:
        print(f"Unexpected error: {response.status_code}")

Testing Payments

Test Environment

For testing, you can use:

  • Testnet: Base Sepolia testnet
  • Test USDC: Use test USDC tokens
  • Mock Payments: Use mock payment data (development only)

Mock Payment (Development Only)

def create_mock_payment(minutes: int) -> str:
    """Create mock payment for testing (NOT for production)"""
    mock_payment = {
        "x402Version": 1,
        "scheme": "exact",
        "network": "base",
        "payload": {
            "signature": "0x" + "0" * 130,
            "authorization": "0x" + "0" * 130,
        }
    }

    import base64
    import json
    return base64.b64encode(json.dumps(mock_payment).encode()).decode()

Security Considerations

Private Key Management

  • Never hardcode private keys in source code
  • Use environment variables for sensitive data
  • Implement key rotation for production systems
  • Use hardware wallets for high-value transactions

Payment Validation

  • Verify payment amounts before submission
  • Check network compatibility (Base mainnet)
  • Validate asset addresses (USDC contract)
  • Implement timeout handling for payment verification

Rate Limiting

  • Limit payment attempts to prevent abuse
  • Implement exponential backoff for failed payments
  • Monitor payment patterns for suspicious activity

Production Checklist

Before deploying to production:

  • Use real x402-python library (not mock payments)
  • Configure proper private key management
  • Set up monitoring for payment failures
  • Implement proper error handling
  • Test with small amounts first
  • Verify network connectivity to Base
  • Set up logging for payment events
  • Implement retry logic for failed payments
  • Test session extension flows
  • Verify WebSocket reconnection logic