Example Repositories
Clone and run these full example projects to see Vanta SDK in action:
Express Basic
Simple Express server with payment-protected endpoints.
Next.js API Routes
Payment middleware with Next.js App Router and API routes.
AI Agent Integration
Autonomous agent that pays for API access with budget controls.
Metered API
Usage-based billing with quota management and prepaid credits.
Minimal Server Example
The simplest possible server with a payment-protected endpoint:
server.ts
import express from 'express'
import { VantaMiddleware } from '@vanta/middleware'
const app = express()
const paywall = VantaMiddleware({
price: '0.001',
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
})
app.get('/api/data', paywall, (req, res) => {
res.json({ secret: 'premium data', timestamp: Date.now() })
})
app.listen(3000, () => console.log('Server on :3000'))Minimal Client Example
The simplest client that handles 402 responses automatically:
client.ts
import { VantaClient } from '@vanta/client'
import { ethers } from 'ethers'
const provider = new ethers.BrowserProvider(window.ethereum)
const client = new VantaClient({ provider })
// This will prompt for payment if needed
const response = await client.fetch('http://localhost:3000/api/data')
const data = await response.json()
console.log(data)Token-Based Access Pattern
Issue tokens after payment for session-based access:
token-server.ts
import express from 'express'
import { VantaMiddleware, VantaTokenIssuer } from '@vanta/middleware'
const app = express()
const tokenIssuer = new VantaTokenIssuer({
secret: process.env.TOKEN_SECRET!,
expiresIn: '1h',
})
const paywall = VantaMiddleware({
price: '0.01',
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
onPaymentVerified: async (payment, req, res) => {
const token = await tokenIssuer.issue(req)
res.setHeader('X-Vanta-Token', token)
},
})
// Use token or payment
const auth = tokenIssuer.middleware({ fallback: paywall })
app.get('/api/premium/*', auth)
app.get('/api/premium/data', (req, res) => {
res.json({ data: 'premium', user: req.vanta?.claims })
})
app.listen(3000)Webhook Notification Pattern
Notify external systems when payments are received:
webhook-server.ts
import express from 'express'
import { VantaMiddleware } from '@vanta/middleware'
const app = express()
const paywall = VantaMiddleware({
price: '0.001',
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
onPaymentVerified: async (payment, req) => {
// Notify your backend
await fetch('https://your-api.com/webhooks/payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
txHash: payment.transactionHash,
amount: payment.amount,
from: payment.from,
endpoint: req.path,
timestamp: new Date().toISOString(),
}),
})
},
})
app.get('/api/data', paywall, handler)Multi-Tier Pricing Pattern
Different prices for different endpoints or features:
tiered-server.ts
import express from 'express'
import { VantaMiddleware } from '@vanta/middleware'
const app = express()
// Basic tier - cheap
const basicPaywall = VantaMiddleware({
price: '0.0001',
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
memo: 'Basic API Access',
})
// Premium tier - more expensive, more features
const premiumPaywall = VantaMiddleware({
price: '0.01',
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
memo: 'Premium API Access',
})
// Dynamic pricing based on request
const dynamicPaywall = VantaMiddleware({
price: (req) => {
const complexity = req.query.complexity || 'simple'
const prices = { simple: '0.0001', medium: '0.001', complex: '0.01' }
return prices[complexity as keyof typeof prices] || '0.001'
},
recipient: process.env.WALLET_ADDRESS!,
network: 'base',
})
app.get('/api/basic/*', basicPaywall)
app.get('/api/premium/*', premiumPaywall)
app.get('/api/dynamic/*', dynamicPaywall)
app.listen(3000)