solana402-express
v0.1.0
Published
Express middleware for pay-per-request APIs using Solana payments
Downloads
99
Maintainers
Readme
@555x402/solana402-express
Express middleware for pay-per-request APIs using Solana payments
Overview
Turn any Express API into a paid API with one line of code. Users pay in USDC/SOL per request—no subscriptions, no accounts, instant settlement.
Based on the x402 protocol (HTTP 402 "Payment Required") adapted for Solana.
Features
- ✅ One-Line Integration: Add middleware, done
- ✅ Pay-Per-Request: Charge per API call, not monthly subscriptions
- ✅ Instant Settlement: Funds arrive in ~2 seconds
- ✅ Low Fees: 0.5-1% + minimal gas
- ✅ No User Accounts: Anonymous payments via Solana wallets
- ✅ Username Support: Accept payments to
@usernameor wallet address - ✅ Automatic Verification: Middleware handles all crypto complexity
- ✅ TypeScript: Full type safety
Installation
npm install @555x402/solana402-express @solana/web3.jsQuick Start
Basic Usage
import express from 'express';
import { solana402Middleware } from '@555x402/solana402-express';
import { PublicKey } from '@solana/web3.js';
const app = express();
// Protect specific routes
app.use('/api/premium', solana402Middleware({
apiKey: process.env.AGG_API_KEY!,
recipientAddress: 'your_wallet_or_@username',
endpoints: {
'GET /api/premium/data': {
price: '0.10', // $0.10 per request
mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
},
'POST /api/premium/generate': {
price: '0.50'
}
}
}));
// Your protected endpoints
app.get('/api/premium/data', (req, res) => {
// Payment already verified by middleware
res.json({ data: 'premium content' });
});
app.post('/api/premium/generate', (req, res) => {
// Payment verified
const result = expensiveComputation();
res.json(result);
});
app.listen(3000);With Route-Specific Pricing
app.use(solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: {
'GET /api/basic': { price: '0.01' }, // $0.01
'GET /api/premium': { price: '0.10' }, // $0.10
'POST /api/ai/generate': { price: '1.00' }, // $1.00
'GET /api/data/realtime': {
price: '0.05',
mint: 'So11111111111111111111111111111111111111112' // SOL
}
}
}));API Reference
solana402Middleware(options): RequestHandler
Express middleware that enforces payment for API access.
Options:
interface Solana402Options {
apiKey: string; // 555x402 AGG API key
apiBase?: string; // API base URL (optional)
recipientAddress: string; // Your wallet or @username
endpoints: Record<string, EndpointConfig>;
}
interface EndpointConfig {
price: string; // USD amount as string
mint?: string; // Token mint (defaults to USDC)
}Behavior:
- If request has valid
X-Paymentheader → verify and proceed - If no header → return
402 Payment Requiredwith price info - If invalid payment → return
402with error
Response Format (402):
{
"error": "X-Payment required",
"price": {
"amount": "0.10",
"asset": "USDC"
},
"recipient": "555Tm1cfV52SrBQmnxXiHMUMrpci8miW3CkLP1Qbmtd7"
}Examples
1. AI API with Token-Based Pricing
import express from 'express';
import { solana402Middleware } from '@555x402/solana402-express';
const app = express();
app.use(express.json());
// Different prices for different AI models
app.use('/api/ai', solana402Middleware({
apiKey: process.env.AGG_API_KEY!,
recipientAddress: process.env.TREASURY_WALLET!,
endpoints: {
'POST /api/ai/gpt4': { price: '0.50' }, // $0.50 per request
'POST /api/ai/claude': { price: '0.40' }, // $0.40 per request
'POST /api/ai/llama': { price: '0.10' }, // $0.10 per request
}
}));
app.post('/api/ai/gpt4', async (req, res) => {
// Payment verified - call OpenAI
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: req.body.messages
});
res.json(response);
});
app.post('/api/ai/claude', async (req, res) => {
// Payment verified
const response = await anthropic.messages.create(...);
res.json(response);
});2. Data API with Rate Limiting
import rateLimit from 'express-rate-limit';
// Free tier: 10 req/min
const freeLimiter = rateLimit({
windowMs: 60 * 1000,
max: 10
});
// Paid tier: no limit (enforced by payment)
app.get('/api/data/free', freeLimiter, (req, res) => {
res.json({ data: 'basic data' });
});
app.get('/api/data/premium',
solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: {
'GET /api/data/premium': { price: '0.05' }
}
}),
(req, res) => {
// No rate limit for paying users
res.json({ data: 'premium real-time data' });
}
);3. Webhook Notifications
import { solana402Middleware } from '@555x402/solana402-express';
app.use('/api/webhooks', solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: {
'POST /api/webhooks/register': { price: '0.01' }
}
}));
app.post('/api/webhooks/register', (req, res) => {
// User paid $0.01 to register webhook
const { url, events } = req.body;
// Store webhook configuration
await db.webhooks.create({
url,
events,
userId: req.payment.sender // Available after middleware
});
res.json({ status: 'registered' });
});4. Username-Based Recipients
// Accept payments to username instead of wallet
app.use(solana402Middleware({
apiKey: API_KEY,
recipientAddress: '@your_username', // ← Resolved to wallet automatically
endpoints: {
'GET /api/data': { price: '0.10' }
}
}));Configuration
Environment Variables
# Required
AGG_API_KEY=pk_live_your_api_key
# Your recipient wallet or username
TREASURY_WALLET=your_solana_wallet
# or
TREASURY_USERNAME=@your_username
# Optional
AGG_API_BASE=https://agg.rendernet.work/pub/v1USDC Mint Addresses
const USDC = {
mainnet: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
devnet: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'
};
// Use in endpoint config
endpoints: {
'GET /api/data': {
price: '0.10',
mint: USDC.mainnet
}
}Advanced Usage
Custom Error Handling
app.use(solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: { ... },
onPaymentError: (error, req, res) => {
// Custom error response
res.status(402).json({
error: 'Payment failed',
details: error.message,
retryAfter: 5
});
}
}));Access Payment Details
app.get('/api/data', (req, res) => {
// Middleware adds payment info to request
console.log('Paid by:', req.payment.sender);
console.log('Amount:', req.payment.amount);
console.log('Tx:', req.payment.txSignature);
res.json({ data: '...' });
});Dynamic Pricing
app.use((req, res, next) => {
// Set price based on user tier, time of day, etc.
req.customPrice = isPremiumUser(req) ? '0.05' : '0.10';
next();
});
app.use(solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: {
'GET /api/data': {
price: (req) => req.customPrice // Dynamic pricing
}
}
}));Client-Side Integration
Users make requests with the X-Payment header:
// Client-side (browser)
import { buildPaymentHeader } from '@555x402/client'; // Hypothetical client package
const paymentHeader = await buildPaymentHeader({
amount: 0.10,
recipient: 'recipient_wallet',
wallet: userWallet
});
const response = await fetch('https://api.example.com/api/premium', {
headers: {
'X-Payment': paymentHeader
}
});
if (response.status === 402) {
const { price } = await response.json();
console.log(`Payment required: $${price.amount}`);
} else {
const data = await response.json();
console.log('Success:', data);
}Error Handling
app.use((err, req, res, next) => {
if (err.name === 'PaymentError') {
return res.status(402).json({
error: err.message,
code: err.code
});
}
next(err);
});Best Practices
1. Price Optimization
// Too cheap: not worth tx fees
❌ { price: '0.001' } // $0.001 (less than minimal transaction fees)
// Good: covers fees + provides value
✅ { price: '0.01' } // $0.01 (minimum recommended)
✅ { price: '0.10' } // $0.10 (good for data APIs)
✅ { price: '1.00' } // $1.00 (good for AI/compute)2. Route Organization
// Group paid routes under /api/premium
app.use('/api/premium', solana402Middleware({...}));
app.use('/api/premium', premiumRouter);
// Keep free routes separate
app.use('/api/public', publicRouter);3. Logging
app.use(solana402Middleware({
apiKey: API_KEY,
recipientAddress: TREASURY,
endpoints: {...},
onPaymentSuccess: (payment, req) => {
logger.info('Payment received', {
sender: payment.sender,
amount: payment.amount,
endpoint: req.path
});
}
}));Troubleshooting
"Payment required" on every request
- Ensure client is sending
X-Paymentheader - Verify payment amount matches endpoint price
- Check payment signature is valid
"Invalid API key"
- Verify AGG_API_KEY is set correctly
- Check you're using the right environment (test vs live)
Slow response times
- Payment verification adds ~200ms latency
- Cache verified payments if same user makes multiple requests
- Consider webhooks for async settlement
Comparison with Traditional APIs
| Feature | Traditional Subscription | solana402-express | |---------|-------------------------|-------------------| | Setup Time | Days (Stripe integration, user accounts, billing) | Minutes (one middleware) | | User Onboarding | Sign up, card info, email verification | None (just wallet) | | Pricing Model | Monthly tiers | Pay-per-use | | Settlement Time | 7-30 days | 2 seconds | | Geographic Restrictions | Many (card processors) | None (crypto-native) | | Chargebacks | Yes (fraud risk) | No (instant finality) | | Privacy | Requires PII | Anonymous (wallet only) |
Changelog
v0.1.0 (2025-11-11)
- Initial release
- Express middleware
- Route-based pricing
- Username support
License
MIT © 555x402
Support
- Docs: https://docs.rendernet.work/solana402-express
- Issues: https://github.com/Render-Network-OS/555x402-solana-express/issues
Related
- @555x402/agg - Underlying payment client
- x402 Protocol - Standard specification
Monetize your API in 5 minutes ⚡
