npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stellar-x402

v0.4.2

Published

Stellar Native x402 Payment Protocol

Readme

Stellar x402

HTTP 402 Payment Protocol SDK for Stellar Blockchain

npm version TypeScript Node.js

DocumentationAPI ReferenceExamples


Overview

Stellar x402 is a TypeScript SDK implementing the x402 payment protocol for the Stellar blockchain. Enable your APIs to require cryptocurrency payments before serving responses using the standardized HTTP 402 status code.

Built for machine-to-machine micropayments, this SDK provides zero-friction payment integration for Node.js and Express applications with automatic payment handling, cryptographic verification, and fast settlement times.

💰 Simple & Elegant: Enable real-time micropayments without payment processors, subscriptions, or API keys. Pay exactly for what you use.

Use Cases

| Use Case | Description | |----------|-------------| | Pay-per-API-Call | Monetize APIs without subscriptions or rate limits | | AI Agent Payments | Enable autonomous agents to pay for resources | | Metered Services | Charge exactly for what's consumed in real-time | | Micropayments | Enable sub-cent transactions economically | | Decentralized Access | Replace API keys with cryptographic payments |

Quick Start

Installation

npm install stellar-x402

Requirements

  • Node.js: 20.0.0 or higher
  • TypeScript: 5.x (recommended)
  • Stellar SDK: 13.0.0 or higher (included as dependency)

🛒 Client Integration (Consuming Paid APIs)

Access x402-protected APIs with zero configuration. The wrapFetchWithPayment client automatically detects payment requirements, builds transactions, and handles the entire payment flow.

Basic Usage

import { wrapFetchWithPayment } from 'stellar-x402/client-http';
import { Keypair } from '@stellar/stellar-sdk';

const keypair = Keypair.fromSecret(process.env.STELLAR_SECRET_KEY!);
const fetchWithPayment = wrapFetchWithPayment(fetch, keypair);

const response = await fetchWithPayment('https://api.example.com/premium/data');

// Access response data
console.log(response.status);
console.log(await response.json());

// Verify payment details
console.log('Headers:', response.headers.get('X-PAYMENT-RESPONSE'));

Supported HTTP Methods

// GET with parameters
const response = await fetchWithPayment(
  new Request('https://api.example.com/data?filter=active', {
    method: 'GET'
  })
);

// POST with body
const response = await fetchWithPayment(
  new Request('https://api.example.com/analyze', {
    method: 'POST',
    body: JSON.stringify({ text: 'Content to analyze' }),
    headers: { 'Content-Type': 'application/json' }
  })
);

// PUT, PATCH, DELETE
await fetchWithPayment(new Request(url, { method: 'PUT', body: data }));
await fetchWithPayment(new Request(url, { method: 'PATCH', body: updates }));
await fetchWithPayment(new Request(url, { method: 'DELETE' }));

Configuration Options

import { wrapFetchWithPayment } from 'stellar-x402/client-http';
import { Keypair } from '@stellar/stellar-sdk';

const keypair = Keypair.fromSecret(process.env.STELLAR_SECRET_KEY!);

// Basic usage with default settings
const fetchWithPayment = wrapFetchWithPayment(fetch, keypair);

// With custom max payment amount (in stroops)
// Default: 1,000,000 stroops = 0.1 USDC
const fetchWithPayment = wrapFetchWithPayment(
  fetch,
  keypair,
  BigInt(5_000_000)  // 0.5 USDC max
);

// Custom configuration
const fetchWithPayment = wrapFetchWithPayment(
  fetch,
  keypair,
  undefined,
  undefined,
  {
    stellarConfig: {
      rpcUrl: 'https://soroban-testnet.stellar.org'
    }
  }
);

How It Works

The client automatically handles the complete payment flow:

  1. Initial Request - Sends HTTP request to protected endpoint
  2. 402 Detection - Identifies payment requirement from response
  3. Transaction Building - Constructs Stellar payment transaction
  4. Client Signing - Signs transaction locally (keys never leave client)
  5. Payment Retry - Resubmits request with X-PAYMENT header
  6. Settlement - Server verifies and submits to blockchain
  7. Response - Receives data after confirmed payment

💎 Using Axios Client (x402axios)

For applications already using Axios, stellar-x402 provides a pre-configured Axios instance with automatic payment handling.

Getting Started with Axios

import { x402axios } from 'stellar-x402/client-axios';
import { Keypair } from '@stellar/stellar-sdk';

// Initialize with your keypair
const keypair = Keypair.fromSecret(process.env.STELLAR_SECRET_KEY!);
x402axios.withSigner({
  publicKey: keypair.publicKey(),
  signTransaction: async (transaction) => {
    // Sign transaction with your keypair
    return keypair.sign(transaction);
  }
});

// Now use it like normal axios - payments happen automatically!
const response = await x402axios.get('https://api.example.com/premium/weather');

// Access response data
console.log(response.data);

// Check payment confirmation
console.log('Payment:', response.headers['x-payment-response']);

All HTTP Methods Supported

// GET
const data = await x402axios.get('https://api.example.com/data');

// POST
const result = await x402axios.post('https://api.example.com/analyze', {
  text: 'Content to analyze'
});

// PUT
await x402axios.put('https://api.example.com/resource/123', {
  status: 'updated'
});

// PATCH
await x402axios.patch('https://api.example.com/resource/123', {
  field: 'new_value'
});

// DELETE
await x402axios.delete('https://api.example.com/resource/123');

Multiple Requests with Chaining

// Configure once, use for multiple requests
x402axios.withSigner({
  publicKey: keypair.publicKey(),
  signTransaction: async (tx) => keypair.sign(tx)
});

// All these requests share the same signer
const [weather, stocks, news] = await Promise.all([
  x402axios.get('https://api.example.com/weather'),
  x402axios.get('https://api.example.com/stocks'),
  x402axios.get('https://api.example.com/news')
]);

console.log('Weather:', weather.data);
console.log('Stocks:', stocks.data);
console.log('News:', news.data);

Comparison: Fetch vs Axios

| Feature | Fetch | Axios | |---------|-------|-------| | API Style | Functional (wrapFetchWithPayment()) | OOP (.withSigner()) | | Setup | Per-request function wrapping | Configure once, reuse | | Best For | Minimal dependencies, edge functions | Large applications, familiar API | | Request | new Request() objects | Simple URL strings | | Chainable | No | Yes (.withSigner().get()) | | Community | Native, standard | Popular, widely used |

Both methods are equally secure and provide the same payment functionality. Choose based on your application's existing HTTP client patterns.


🏪 Server Integration (Monetizing Your APIs)

Protect Express.js API routes with x402 middleware - zero payment code required in your route handlers.

Step 1: Configure Environment

Create .env in your project root:

PAYMENT_RECIPIENT_ADDRESS=GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
FACILITATOR_URL=https://facilitator.example.com

Getting a Wallet Address:
Generate with stellar-x402 or use the Stellar CLI: stellar account create

Step 2: Create Middleware

Create your Express app with x402 payment middleware:

import express from 'express';
import { paymentMiddleware } from 'stellar-x402/server';

const app = express();

// Apply payment middleware to protected routes
app.use(
  paymentMiddleware(
    process.env.PAYMENT_RECIPIENT_ADDRESS!,
    {
      '/api/premium/weather': {
        price: '1000000',  // 0.1 USDC
        network: 'stellar-testnet',
        config: {
          description: 'Premium weather data access',
          mimeType: 'application/json'
        }
      },
      '/api/premium/stocks': {
        price: '5000000',  // 0.5 USDC
        network: 'stellar-testnet',
        config: { description: 'Real-time stock data' }
      }
    },
    { 
      url: process.env.FACILITATOR_URL!
    }
  )
);

// Your protected routes
app.get('/api/premium/weather', (req, res) => {
  // Execution only reaches here AFTER successful payment settlement
  
  res.json({
    location: 'San Francisco',
    temperature: 72,
    condition: 'Sunny',
    forecast: '7-day detailed forecast data...'
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Middleware Behavior

| Scenario | Response | |----------|----------| | No payment header | 402 Payment Required with payment instructions | | Invalid payment | 403 Forbidden with error details | | Valid payment | Verifies → Settles → Executes route → 200 OK |

Price Configuration

Stellar uses stroops as the smallest unit (like satoshis or wei):

1 XLM = 10,000,000 stroops
1 USDC = 10,000,000 stroops (7 decimal places)

Common prices:
  0.001 XLM = 10,000 stroops
  0.01 XLM  = 100,000 stroops
  0.1 XLM   = 1,000,000 stroops
  1 XLM     = 10,000,000 stroops

Testing Your Integration

Start your development server and verify payment protection:

npm run dev

# Test without payment (should return 402)
curl http://localhost:3000/api/premium/weather

Expected 402 response:

{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "stellar-testnet",
    "maxAmountRequired": "1000000",
    "payTo": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
    "description": "Premium weather data access",
    "resource": "http://localhost:3000/api/premium/weather"
  }]
}

Test with payment using the client:

import { wrapFetchWithPayment } from 'stellar-x402/client-http';
import { Keypair } from '@stellar/stellar-sdk';

const keypair = Keypair.fromSecret(process.env.STELLAR_SECRET_KEY!);
const fetchWithPayment = wrapFetchWithPayment(fetch, keypair);

const response = await fetchWithPayment('http://localhost:3000/api/premium/weather');
console.log(await response.json());

Architecture

Protocol Flow

┌──────────┐                 ┌──────────┐              ┌────────────┐         ┌────────────┐
│  Client  │                 │   API    │              │ Facilitator│         │  Stellar   │
│  (Buyer) │                 │ (Seller) │              │  Service   │         │ Blockchain │
└────┬─────┘                 └────┬─────┘              └─────┬──────┘         └─────┬──────┘
     │                            │                          │                      │
     │ GET /api/premium/data      │                          │                      │
     │───────────────────────────>│                          │                      │
     │                            │                          │                      │
     │ 402 Payment Required       │                          │                      │
     │<───────────────────────────│                          │                      │
     │ {scheme, amount, payTo}    │                          │                      │
     │                            │                          │                      │
     │ [Build & Sign Transaction] │                          │                      │
     │ (Client-side, offline)     │                          │                      │
     │                            │                          │                      │
     │ GET /api/premium/data      │                          │                      │
     │ X-PAYMENT: <signed_tx>     │                          │                      │
     │───────────────────────────>│                          │                      │
     │                            │                          │                      │
     │                            │ POST /verify             │                      │
     │                            │─────────────────────────>│                      │
     │                            │ {isValid: true}          │                      │
     │                            │<─────────────────────────│                      │
     │                            │                          │                      │
     │                            │ POST /settle             │                      │
     │                            │─────────────────────────>│                      │
     │                            │                          │ Submit Transaction  │
     │                            │                          │────────────────────>│
     │                            │                          │ Confirmed           │
     │                            │                          │<────────────────────│
     │                            │ {success, txHash}        │                      │
     │                            │<─────────────────────────│                      │
     │                            │                          │                      │
     │ 200 OK + Data              │                          │                      │
     │<───────────────────────────│                          │                      │
     │ X-PAYMENT-RESPONSE: {...}  │                          │                      │
     │                            │                          │                      │

Components

| Component | Responsibility | Location | |-----------|----------------|----------| | Client | Request resources, sign transactions | Your application/agent | | Middleware | Intercept requests, enforce payment | Your Express server | | Facilitator | Verify & settle payments | Shared service or self-hosted | | Stellar Blockchain | Final settlement & verification | Decentralized network |

Key Design Principles

  • Client-Side Signing - Private keys never leave the client
  • Stateless Protocol - No sessions, cookies, or stored state
  • Atomic Operations - Payment settles or request fails (no partial states)
  • Transparent - All transactions verifiable on-chain
  • HTTP Native - Uses standard status codes and headers

API Reference

Server-Side API

paymentMiddleware()

Creates Express middleware for x402 payment enforcement.

Signature:

function paymentMiddleware(
  payTo: string,
  routes: RoutesConfig,
  facilitator?: FacilitatorConfig
): (req: Request, res: Response, next: NextFunction) => Promise<void>

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | payTo | string | Stellar wallet address to receive payments | | routes | RoutesConfig | Map of route paths to payment configs | | facilitator | FacilitatorConfig | Facilitator service configuration |

RouteConfig:

interface RouteConfig {
  price: string;                           // Amount in stroops
  network?: 'stellar-testnet' | 'stellar'; // Default: 'stellar-testnet'
  config?: {
    description?: string;                  // Human-readable description
    mimeType?: string;                     // Response content type
    outputSchema?: object;                 // Optional JSON schema
    maxTimeoutSeconds?: number;            // Request timeout
  };
}

FacilitatorConfig:

interface FacilitatorConfig {
  url: string;  // Base URL (e.g., 'https://example.com/api/facilitator')
}

Client-Side API

wrapFetchWithPayment()

Wraps the Fetch API with automatic x402 payment handling.

Signature:

function wrapFetchWithPayment(
  fetch: typeof globalThis.fetch,
  stellarKeypair: Keypair,
  maxValue?: bigint,
  paymentRequirementsSelector?: typeof selectPaymentRequirements,
  config?: X402Config
): (input: RequestInfo, init?: RequestInit) => Promise<Response>

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | fetch | typeof globalThis.fetch | Fetch function to wrap | | stellarKeypair | Keypair | Stellar keypair for signing | | maxValue | bigint | Max payment in stroops (default: 1,000,000) | | paymentRequirementsSelector | function | Custom requirement selector | | config | X402Config | Optional configuration |

Returns: Wrapped fetch function that handles 402 responses automatically

Usage:

import { wrapFetchWithPayment } from 'stellar-x402/client-http';
import { Keypair } from '@stellar/stellar-sdk';

const keypair = Keypair.fromSecret('SXXX...');
const fetchWithPayment = wrapFetchWithPayment(fetch, keypair);

const response = await fetchWithPayment('https://api.example.com/paid');

TypeScript Types

Import types for full type safety:

import type {
  RouteConfig,
  RoutesConfig,
  FacilitatorConfig,
  PaymentRequirements,
  PaymentPayload,
  X402Config,
  Network
} from 'stellar-x402/types';

Advanced Usage

Manual Payment Flow

For full control over the payment process:

import { Keypair } from '@stellar/stellar-sdk';

async function manualPaymentFlow(url: string, secretKey: string) {
  // 1. Request without payment
  let response = await fetch(url);
  
  if (response.status === 402) {
    const paymentReqs = await response.json();
    const requirement = paymentReqs.accepts[0];
    
    // 2. Build and sign transaction
    const keypair = Keypair.fromSecret(secretKey);
    // ... build Stellar transaction ...
    
    // 3. Create payment header
    const paymentHeader = transaction.toXDR();
    
    // 4. Retry with payment
    response = await fetch(url, {
      headers: {
        'X-PAYMENT': paymentHeader
      }
    });
  }
  
  return await response.json();
}

Examples & Demo

Example Projects

| Example | Description | Location | |---------|-------------|----------| | Express Server | Basic middleware setup | examples/typescript/ | | Full Stack | Complete client + server | examples/typescript/fullstack/ |

Testing Locally

# Install dependencies
npm install

# Start development server
npm run dev

# In another terminal, test with the client
npx ts-node examples/test-client.ts

FAQ

  • No secrets to manage, rotate, or leak
  • True pay-per-use with no subscriptions
  • Decentralized with no auth server
  • Instant monetization without payment processors
  • Works with any blockchain

| Operation | Time | |-----------|------| | Verification | < 100ms | | Settlement | 3-5 seconds | | Total | ~3-6 seconds |

Times depend on Stellar network congestion

| Party | Cost | |-------|------| | Client | Gas (~$0.00001) + API price | | Server | Facilitator hosting only | | Protocol | Free, open source |

Yes, with proper testing:

  • Start on testnet for development
  • Thorough testing before mainnet
  • Monitor facilitator health
  • Implement error handling

This SDK is Stellar-specific. The x402 protocol supports any blockchain. Other implementations coming soon.

Sellers: Need wallet address to receive payments (no private key on server)
Buyers: Need funded wallet to make payments

Generate testnet wallets with:

stellar account create

Agents can autonomously make payments:

const keypair = Keypair.fromSecret(process.env.AGENT_KEY);
const fetchWithPayment = wrapFetchWithPayment(fetch, keypair);
const data = await fetchWithPayment(apiUrl);

No human intervention required.

try {
  const response = await fetchWithPayment(url);
  if (response.status === 402) {
    console.log('Payment required but not completed');
  }
} catch (error) {
  console.error('Payment error:', error.message);
}

Resources

Links

Support

Contributing

Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.


Built for the Stellar Ecosystem

DocumentationGitHubNPM