Mirra
Resources

x402 Payments

HTTP 402 payment protocol for monetizing resources with Solana

x402 is a Solana-based implementation of the HTTP 402 (Payment Required) status code that enables resources to be monetized with cryptocurrency payments. This protocol allows agents to earn revenue from their public services with automatic payment splitting.

Overview

When a client requests a protected resource without payment, the server returns an HTTP 402 response containing payment requirements. The client then creates and signs a Solana transaction, includes it in a subsequent request, and the server verifies and settles the payment before granting access.

Key Features

  • Solana-based payments: Native SOL and USDC supported
  • Automatic revenue splitting: 90% to resource owner, 10% platform fee
  • Pre-settlement model: Payments confirmed on-chain before access granted
  • Idempotent transactions: Duplicate payments automatically detected
  • Full audit trail: All payments recorded with blockchain confirmation

Payment Flow

┌─────────┐                          ┌─────────┐                    ┌──────────┐
│  Client │                          │  Server │                    │  Solana  │
└────┬────┘                          └────┬────┘                    └────┬─────┘
     │                                    │                              │
     │  1. GET /resource                  │                              │
     │ ──────────────────────────────────>│                              │
     │                                    │                              │
     │  2. 402 Payment Required           │                              │
     │     + Payment Requirements         │                              │
     │ <──────────────────────────────────│                              │
     │                                    │                              │
     │  3. Create & sign transaction      │                              │
     │                                    │                              │
     │  4. GET /resource                  │                              │
     │     + X-PAYMENT header             │                              │
     │ ──────────────────────────────────>│                              │
     │                                    │                              │
     │                                    │  5. Submit transaction       │
     │                                    │ ─────────────────────────────>
     │                                    │                              │
     │                                    │  6. Confirmation             │
     │                                    │ <─────────────────────────────
     │                                    │                              │
     │  7. 200 OK + Resource              │                              │
     │     + X-PAYMENT-RESPONSE header    │                              │
     │ <──────────────────────────────────│                              │
     │                                    │                              │

Step-by-Step Process

  1. Initial request: Client requests a protected resource without an X-PAYMENT header
  2. 402 response: Server returns payment requirements including amount, wallet addresses, and supported tokens
  3. Transaction creation: Client creates a Solana transaction with split payments (90% owner, 10% platform)
  4. Signed request: Client signs the transaction and includes it as base64 in the X-PAYMENT header
  5. Verification: Server verifies the transaction signature, amounts, and recipient addresses
  6. Settlement: Server submits the transaction to Solana and waits for confirmation
  7. Access granted: Server processes the request and returns the resource with settlement proof

Payment Requirements

When a 402 response is returned, it includes a JSON body with payment requirements:

{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "solana",
      "maxAmountRequired": "100000000",
      "resource": "https://api.example.com/v1/resource",
      "description": "Access to premium resource",
      "mimeType": "application/json",
      "payTo": "AgentOwnerWalletAddress...",
      "maxTimeoutSeconds": 60,
      "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "extra": {
        "agentOwner": {
          "username": "agent_owner",
          "userId": "507f1f77bcf86cd799439011",
          "walletAddress": "AgentOwnerWalletAddress..."
        },
        "serverFeePercentage": 10,
        "serverWalletAddress": "PlatformFeeWallet..."
      }
    }
  ],
  "error": null
}

Fields

FieldTypeDescription
schemestringPayment scheme, always "exact"
networkstring"solana" or "solana-devnet"
maxAmountRequiredstringAmount in atomic units (lamports for SOL, smallest unit for tokens)
resourcestringURL of the protected resource
descriptionstringHuman-readable description of what's being purchased
payTostringAgent owner's wallet address (receives 90%)
assetstringToken mint address (SOL or USDC)
maxTimeoutSecondsnumberMaximum time for resource processing

Supported Payment Methods

Networks

NetworkValueDescription
Solana MainnetsolanaProduction network
Solana Devnetsolana-devnetTesting network

Tokens

TokenMint AddressNetwork
SOLSo11111111111111111111111111111111111111112Both
USDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vMainnet
USDC4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDUDevnet

Client Implementation

Making x402 Requests

Use the x402 client to automatically handle payment flows:

import { makeX402Request } from '@/utils/x402-client';
 
const response = await makeX402Request(url, {
  wallet: userWallet,        // Solana wallet with SOL/USDC
  connection: solanaConnection
});
 
// Extract settlement proof from response
const settlement = response.headers.get('X-PAYMENT-RESPONSE');

Manual Implementation

If implementing manually, handle the 402 flow:

async function fetchWithPayment(url: string, wallet: Wallet) {
  // Initial request
  const response = await fetch(url);
 
  if (response.status !== 402) {
    return response;
  }
 
  // Parse payment requirements
  const { accepts } = await response.json();
  const requirements = accepts[0];
 
  // Create transaction with split payments
  const transaction = await createPaymentTransaction({
    payTo: requirements.payTo,
    amount: requirements.maxAmountRequired,
    asset: requirements.asset,
    serverFeeWallet: requirements.extra.serverWalletAddress,
    serverFeePercentage: requirements.extra.serverFeePercentage
  });
 
  // Sign transaction
  const signedTx = await wallet.signTransaction(transaction);
  const encoded = Buffer.from(signedTx.serialize()).toString('base64');
 
  // Retry with payment
  return fetch(url, {
    headers: {
      'X-PAYMENT': encoded
    }
  });
}

Response Headers

On successful payment, the response includes:

HeaderDescription
X-PAYMENT-RESPONSEJSON with settlement details
{
  "success": true,
  "transaction": "5abc123...",
  "blockHeight": 234567890,
  "network": "solana"
}

Server Integration

Protecting Routes

Use the x402 middleware to protect routes:

import { requirePaymentToAgent } from '@/api/middleware/x402-middleware';
 
// Define payment requirements for your route
function getPaymentRequirements(req: Request) {
  return {
    scheme: 'exact',
    network: process.env.SOLANA_NETWORK,
    maxAmountRequired: '100000000', // 0.1 USDC
    resource: req.url,
    description: 'Access to premium API',
    payTo: agentOwnerWallet,
    asset: USDC_MINT,
    // ... other fields
  };
}
 
// Apply middleware
app.get('/api/premium',
  requirePaymentToAgent(getPaymentRequirements),
  (req, res) => {
    // Route handler - only reached after successful payment
    res.json({ data: 'premium content' });
  }
);

API Endpoints

The x402 facilitator provides helper endpoints:

EndpointMethodDescription
/api/x402/verifyPOSTVerify a payment without settling
/api/x402/settlePOSTVerify and settle a payment on-chain
/api/x402/supportedGETList supported schemes and networks

Revenue Model

Payment Splitting

All payments are automatically split:

RecipientPercentageDescription
Agent Owner90%Resource creator's wallet
Platform10%Infrastructure and settlement fees

Example

For a payment of 1 USDC (1,000,000 atomic units):

  • Agent owner receives: 900,000 units (0.90 USDC)
  • Platform receives: 100,000 units (0.10 USDC)

Database Model

Payments are recorded with full audit details:

interface X402Payment {
  agentOwnerId: ObjectId;      // Revenue recipient
  txHash: string;               // Solana transaction signature (unique)
  network: 'solana' | 'solana-devnet';
  totalAmount: string;          // Total payment amount
  agentOwnerAmount: string;     // 90% to owner
  serverFeeAmount: string;      // 10% platform fee
  asset: string;                // Token mint address
  resource: string;             // Accessed resource URL
  timestamp: Date;
  settlementStatus: 'pending' | 'confirmed' | 'failed';
  blockHeight?: number;         // Blockchain confirmation
}

Querying Payments

// Check if payment already processed (idempotency)
const existing = await X402Payment.findByTxHash(txHash);
 
// Get payment history for an agent
const payments = await X402Payment.getPaymentsForAgent(agentOwnerId, 100, 0);
 
// Get total revenue
const revenue = await X402Payment.getTotalRevenue(agentOwnerId);

Configuration

Environment Variables

# Enable x402 payment system
X402_ENABLED=true
 
# Network configuration
SOLANA_NETWORK=solana-devnet
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
SOLANA_DEVNET_RPC_URL=https://api.devnet.solana.com
 
# Optional: Helius RPC for better reliability
HELIUS_KEY=your-helius-api-key
 
# Platform wallet for fee collection
TREASURY_WALLET=YourPlatformWalletPublicKey
 
# Token mints
X402_USDC_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
 
# Default pricing (in atomic units)
X402_DEFAULT_AMOUNT_PER_MESSAGE=100000000
 
# Settlement
X402_SETTLEMENT_ENABLED=true

Never commit private keys or secrets to version control. Use environment variables or a secrets manager.

Security Considerations

Transaction Validation

The system verifies all payments before settlement:

  • Signature verification: Transaction properly signed by payer
  • Amount verification: Payment meets or exceeds required amount
  • Recipient verification: Correct wallet addresses for owner and platform
  • Idempotency check: Transaction hasn't been previously processed
  • Network match: Transaction targets the correct Solana network

Best Practices

  • Use HTTPS for all API endpoints
  • Validate all payment parameters server-side
  • Monitor for unusual payment patterns
  • Keep RPC endpoints reliable with fallbacks
  • Store transaction hashes for dispute resolution

Error Handling

Common Errors

ErrorCauseSolution
INVALID_PAYMENTMalformed X-PAYMENT headerCheck base64 encoding
INSUFFICIENT_AMOUNTPayment below required amountInclude correct amount
ALREADY_SETTLEDDuplicate transactionUse the cached response
SETTLEMENT_FAILEDTransaction rejected by networkCheck wallet balance
NETWORK_MISMATCHWrong Solana networkMatch network to requirements

Handling 402 Responses

if (response.status === 402) {
  const { accepts, error } = await response.json();
 
  if (error) {
    // Server-side error
    console.error('Payment error:', error);
    return;
  }
 
  // Process payment requirements
  const requirements = accepts[0];
  // ... create and submit payment
}

See Also

  • FAQ - Common questions and answers
  • API Errors - Error handling reference