From npm init to a deployed API that accepts USDC payments from AI agents. Complete code. No filler.
Hono
12KB
x402-core
Types + Validation
x402-hono
Middleware
x402-solana
Verification
USDC
Solana + Base
A paid web scraping API that accepts USDC payments from AI agents via the x402 protocol. An agent sends a request, gets a 402 response with payment terms, pays on Solana or Base, and receives scraped data through a Proxies.sx mobile proxy. Zero accounts. Zero API keys. Pure HTTP + crypto.
TypeScript-first, 12KB, runs on Node/Deno/Bun/Workers
x402Middleware verifies USDC before granting access
Fetches through real 4G/5G IPs via Proxies.sx
Cloudflare Workers or any Node runtime
Node.js 18+
node --version to check
npm or pnpm
Package manager
A Solana or Base wallet
To receive USDC payments
Proxies.sx account (optional)
For the scraping endpoint demo
curl or httpie
To test locally
Cloudflare account (optional)
For edge deployment
Three commands. Under 30 seconds.
mkdir my-paid-api && cd my-paid-api && npm init -ynpm i hono @proxies-sx/x402-core @proxies-sx/x402-hono @proxies-sx/x402-solanahonoUltrafast web framework. 12KB gzipped. TypeScript-first. Runs on Node.js, Deno, Bun, Cloudflare Workers, AWS Lambda, and Vercel Edge Functions. Think of it as Express but 40x smaller with native TypeScript support.
@proxies-sx/x402-coreCore types and utilities. Exports the PaymentRequirement type (defines what a 402 response contains), createPaymentRequirement() (builds a standards-compliant payment requirement object), and validatePaymentSignature() (verifies that an X-PAYMENT header contains a valid cryptographic signature).
@proxies-sx/x402-honoHono middleware. Exports x402Middleware() which intercepts requests, checks for payment proof, returns 402 with PaymentRequirement if missing, and calls your verify function to validate on-chain payments before allowing access.
@proxies-sx/x402-solanaSolana payment verification. Exports verifySolanaPayment() which takes a transaction signature, connects to the Solana RPC, fetches the parsed transaction, checks for a USDC SPL token transfer (mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v), verifies the amount meets the price, and confirms the recipient matches your wallet.
If you also want Base (Ethereum L2) payment verification, install @proxies-sx/x402-base. This tutorial focuses on Solana, but we show multi-network configuration in Step 3.
Strict mode, ESM output, Node 18 target.
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"resolveJsonModule": true,
"isolatedModules": true,
"types": ["node"]
},
"include": ["src/**/*"]
}Also update your package.json to add "type": "module" and a dev script:
{
"name": "my-paid-api",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "npx tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
},
"dependencies": {
"hono": "^4.7.0",
"@proxies-sx/x402-core": "^1.0.0",
"@proxies-sx/x402-hono": "^1.0.0",
"@proxies-sx/x402-solana": "^1.0.0"
},
"devDependencies": {
"tsx": "^4.0.0",
"typescript": "^5.5.0",
"@types/node": "^22.0.0"
}
}npm i -D tsx typescript @types/nodeThis is the core of your paid API. Every line is annotated.
// src/index.ts
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { serve } from '@hono/node-server'
import {
type PaymentRequirement,
createPaymentRequirement,
validatePaymentSignature,
} from '@proxies-sx/x402-core'
import { x402Middleware } from '@proxies-sx/x402-hono'
import { verifySolanaPayment } from '@proxies-sx/x402-solana'
// ─── Configuration ───────────────────────────────────────────────
// Your Solana wallet that receives USDC payments
const SOLANA_RECIPIENT = '6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv'
// Your Base (Ethereum L2) wallet (optional, for multi-network)
const BASE_RECIPIENT = '0xF8cD900794245fc36CBE65be9afc23CDF5103042'
// USDC token addresses
const SOLANA_USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
const BASE_USDC = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'
// Proxies.sx credentials (from client.proxies.sx dashboard)
const PROXY_HOST = process.env.PROXY_HOST || 'us.proxies.sx'
const PROXY_PORT = parseInt(process.env.PROXY_PORT || '5057')
const PROXY_USER = process.env.PROXY_USER || 'your_username'
const PROXY_PASS = process.env.PROXY_PASS || 'your_password'
// ─── Hono App ────────────────────────────────────────────────────
const app = new Hono()
// Global middleware
app.use('*', cors())
app.use('*', logger())
// ─── Health Check (free, no payment required) ────────────────────
app.get('/', (c) => {
return c.json({
service: 'my-paid-api',
version: '1.0.0',
protocol: 'x402',
endpoints: {
'/api/scrape': {
method: 'POST',
price: '$0.05 per request',
payment: 'USDC on Solana or Base',
description: 'Scrape any URL through a real 4G/5G mobile proxy',
},
'/api/bulk-scrape': {
method: 'POST',
price: '$0.20 per request (up to 10 URLs)',
payment: 'USDC on Solana or Base',
description: 'Batch scrape multiple URLs',
},
},
docs: 'https://agents.proxies.sx/marketplace/',
})
})
// ─── x402 Middleware for /api/* routes ────────────────────────────
//
// x402Middleware() configuration:
//
// price: number
// Amount in micro-units. 1 micro-unit = $0.000001.
// 50000 = $0.05, 200000 = $0.20, 5000000 = $5.00
//
// recipient: string
// Your wallet address that receives payment.
//
// networks: string[]
// Which blockchains to accept. Options: 'solana', 'base'.
// The agent picks which one to use based on its funding.
//
// description: string
// Human-readable description shown in the 402 response body.
//
// verify: (paymentHeader: string, requirement: PaymentRequirement) => Promise<boolean>
// Your custom verification function. Called when the client
// retries with an X-PAYMENT header. Must return true if the
// on-chain payment is valid.
//
// resource: string (optional)
// Identifies the resource being purchased. Included in the
// PaymentRequirement for the agent's reference.
// ─── Single Scrape Endpoint ($0.05/request) ──────────────────────
app.use(
'/api/scrape',
x402Middleware({
price: 50000, // $0.05 in micro-units (50000 * $0.000001)
recipient: SOLANA_RECIPIENT,
networks: ['solana', 'base'],
description: 'Scrape a URL through a real 4G/5G mobile proxy',
resource: '/api/scrape',
verify: async (paymentHeader: string, requirement: PaymentRequirement) => {
// Step 1: Validate the cryptographic signature on the header
const signatureValid = validatePaymentSignature(paymentHeader)
if (!signatureValid) return false
// Step 2: Verify the on-chain payment
// Parse the payment header to get the transaction signature
const payment = JSON.parse(
Buffer.from(paymentHeader, 'base64').toString()
)
if (payment.network === 'solana') {
const result = await verifySolanaPayment({
txSignature: payment.txSignature,
expectedRecipient: SOLANA_RECIPIENT,
expectedAmount: requirement.price,
usdcMint: SOLANA_USDC,
})
return result.verified
}
// For Base verification, use @proxies-sx/x402-base
// (similar pattern, checks ERC20 Transfer event)
return false
},
})
)
// ─── Bulk Scrape Endpoint ($0.20/request, up to 10 URLs) ─────────
app.use(
'/api/bulk-scrape',
x402Middleware({
price: 200000, // $0.20 in micro-units
recipient: SOLANA_RECIPIENT,
networks: ['solana'],
description: 'Batch scrape up to 10 URLs through mobile proxies',
resource: '/api/bulk-scrape',
verify: async (paymentHeader: string, requirement: PaymentRequirement) => {
const signatureValid = validatePaymentSignature(paymentHeader)
if (!signatureValid) return false
const payment = JSON.parse(
Buffer.from(paymentHeader, 'base64').toString()
)
const result = await verifySolanaPayment({
txSignature: payment.txSignature,
expectedRecipient: SOLANA_RECIPIENT,
expectedAmount: requirement.price,
usdcMint: SOLANA_USDC,
})
return result.verified
},
})
)
// ─── Route Handlers ──────────────────────────────────────────────
// POST /api/scrape — single URL scrape
app.post('/api/scrape', async (c) => {
const body = await c.req.json<{ url: string; headers?: Record<string, string> }>()
if (!body.url) {
return c.json({ error: 'missing_url', message: 'Provide a "url" field' }, 400)
}
try {
// Build proxy URL for fetch (SOCKS5 via Proxies.sx)
const proxyUrl = `http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`
// Fetch through mobile proxy
const response = await fetch(body.url, {
headers: {
'User-Agent':
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15',
...body.headers,
},
// @ts-ignore — proxy support varies by runtime
proxy: proxyUrl,
})
const html = await response.text()
return c.json({
success: true,
url: body.url,
status: response.status,
content_length: html.length,
content: html,
proxy: {
provider: 'proxies.sx',
type: '4G/5G mobile',
country: 'US',
},
payment: {
protocol: 'x402',
amount: '$0.05',
currency: 'USDC',
},
})
} catch (err) {
return c.json(
{
error: 'scrape_failed',
message: err instanceof Error ? err.message : 'Unknown error',
},
500
)
}
})
// POST /api/bulk-scrape — up to 10 URLs
app.post('/api/bulk-scrape', async (c) => {
const body = await c.req.json<{ urls: string[] }>()
if (!body.urls || !Array.isArray(body.urls)) {
return c.json({ error: 'missing_urls', message: 'Provide a "urls" array' }, 400)
}
if (body.urls.length > 10) {
return c.json({ error: 'too_many_urls', message: 'Maximum 10 URLs per request' }, 400)
}
const proxyUrl = `http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`
const results = await Promise.allSettled(
body.urls.map(async (url) => {
const response = await fetch(url, {
headers: {
'User-Agent':
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15',
},
// @ts-ignore
proxy: proxyUrl,
})
const html = await response.text()
return { url, status: response.status, content_length: html.length, content: html }
})
)
return c.json({
success: true,
total: body.urls.length,
results: results.map((r, i) =>
r.status === 'fulfilled'
? r.value
: { url: body.urls[i], error: (r.reason as Error).message }
),
payment: { protocol: 'x402', amount: '$0.20', currency: 'USDC' },
})
})
// ─── Start Server ────────────────────────────────────────────────
const port = parseInt(process.env.PORT || '3000')
serve({ fetch: app.fetch, port }, (info) => {
console.log(`
┌─────────────────────────────────────────────┐
│ x402 Paid API running on port ${info.port} │
│ │
│ Free: GET / │
│ Paid: POST /api/scrape ($0.05) │
│ Paid: POST /api/bulk-scrape ($0.20) │
│ │
│ Payment: USDC on Solana or Base │
│ Recipient: ${SOLANA_RECIPIENT.slice(0, 8)}... │
└─────────────────────────────────────────────┘
`)
})Micro-unit pricing
price: 50000 means $0.05. The formula is price * $0.000001. This avoids floating-point issues. For $5.00, set price: 5000000.
Multi-network support
networks: ['solana', 'base'] tells the agent it can pay on either chain. The 402 response includes payment requirements for each network with the appropriate recipient address and token contract.
Verify function
Called when the client retries with X-PAYMENT header. First validates the signature with validatePaymentSignature(), then checks the actual on-chain transfer with verifySolanaPayment(). Both must pass for access to be granted.
PaymentRequirement type
Exported from @proxies-sx/x402-core. Contains price, recipient, network, token, description, and resource. The middleware automatically serializes this into the 402 response body.
Understanding the type system that powers every x402 transaction.
// Types exported by @proxies-sx/x402-core
/**
* PaymentRequirement — the data structure returned in a 402 response.
* This tells the paying agent exactly what to do.
*/
export interface PaymentRequirement {
/** Price in micro-units. 1 = $0.000001. Integer only. */
price: number
/** Wallet address that should receive the payment */
recipient: string
/** Blockchain network: 'solana' | 'base' */
network: string
/** Token contract address (USDC) */
token: string
/** Human-readable description of what the payment is for */
description: string
/** The API resource/endpoint being purchased */
resource?: string
/** ISO 8601 expiry timestamp for this payment requirement */
expiry?: string
/** Unique nonce to prevent replay attacks */
nonce?: string
}
/**
* createPaymentRequirement() — builds a PaymentRequirement with
* sensible defaults (generates nonce, sets 5-minute expiry).
*
* You rarely call this directly because x402Middleware does it
* for you, but it is useful for custom 402 responses.
*/
export function createPaymentRequirement(opts: {
price: number
recipient: string
network: string
token?: string // defaults to USDC address for the network
description?: string
resource?: string
expiryMinutes?: number // default: 5
}): PaymentRequirement
/**
* validatePaymentSignature() — checks the X-PAYMENT header.
* The header is a base64-encoded JSON object containing:
* - txSignature: the on-chain transaction hash
* - network: which chain the tx is on
* - timestamp: when the payment was made
* - signature: cryptographic signature over the above fields
*
* Returns true if the signature is mathematically valid.
* Does NOT check the blockchain — that is what
* verifySolanaPayment() or verifyBasePayment() does.
*/
export function validatePaymentSignature(
paymentHeader: string
): boolean// @proxies-sx/x402-solana — Solana verification
import { Connection, ParsedTransactionWithMeta } from '@solana/web3.js'
export interface SolanaPaymentResult {
/** Whether the payment was verified successfully */
verified: boolean
/** The parsed Solana transaction (if found) */
transaction?: ParsedTransactionWithMeta
/** Transfer amount in USDC (human-readable, e.g. "0.05") */
amount?: string
/** Sender wallet address */
sender?: string
/** Error message if verification failed */
error?: string
}
/**
* verifySolanaPayment() — the core verification function.
*
* 1. Connects to Solana RPC (mainnet-beta by default)
* 2. Fetches the parsed transaction by signature
* 3. Looks for a USDC SPL token transfer instruction
* 4. Checks the transfer destination matches expectedRecipient
* 5. Checks the transfer amount >= expectedAmount (in micro-units)
* 6. Returns SolanaPaymentResult with verified: true or false
*/
export async function verifySolanaPayment(opts: {
/** Transaction signature (hash) from the X-PAYMENT header */
txSignature: string
/** Your Solana wallet that should have received USDC */
expectedRecipient: string
/** Required amount in micro-units (same as PaymentRequirement.price) */
expectedAmount: number
/** USDC SPL token mint address */
usdcMint?: string // default: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
/** Custom Solana RPC URL */
rpcUrl?: string // default: https://api.mainnet-beta.solana.com
/** Max retries for RPC calls */
maxRetries?: number // default: 3
/** Require transaction to be finalized (vs confirmed) */
requireFinalized?: boolean // default: false
}): Promise<SolanaPaymentResult>Solana
USDC (SPL Token)
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vProxies.sx Recipient
6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnvBase (Ethereum L2)
USDC (ERC20)
0x833589fcd6edb6e08f4c7c32d4f71b54bda02913Proxies.sx Recipient
0xF8cD900794245fc36CBE65be9afc23CDF5103042Start the server, hit the endpoint, and see the 402 flow in action.
First, start the development server:
npm run devIn another terminal, hit the health endpoint (free, no payment):
curl http://localhost:3000/
# Response:
# {
# "service": "my-paid-api",
# "version": "1.0.0",
# "protocol": "x402",
# "endpoints": {
# "/api/scrape": {
# "method": "POST",
# "price": "$0.05 per request",
# "payment": "USDC on Solana or Base"
# }
# }
# }Now hit the paid endpoint without payment:
curl -s -w "\nHTTP Status: %{http_code}\n" \
-X POST http://localhost:3000/api/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# HTTP Status: 402
#
# Response body:
# {
# "status": 402,
# "message": "Payment Required",
# "paymentRequirements": [
# {
# "price": 50000,
# "recipient": "6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv",
# "network": "solana",
# "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
# "description": "Scrape a URL through a real 4G/5G mobile proxy",
# "resource": "/api/scrape",
# "expiry": "2026-02-08T12:05:00.000Z",
# "nonce": "a1b2c3d4e5f6"
# },
# {
# "price": 50000,
# "recipient": "0xF8cD900794245fc36CBE65be9afc23CDF5103042",
# "network": "base",
# "token": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
# "description": "Scrape a URL through a real 4G/5G mobile proxy",
# "resource": "/api/scrape",
# "expiry": "2026-02-08T12:05:00.000Z",
# "nonce": "a1b2c3d4e5f6"
# }
# ]
# }The 402 response is machine-readable. An AI agent parses this, picks a network, submits a USDC transfer, and retries with the X-PAYMENT header. Here is what each field means:
price: 50000$0.05 in micro-units (50000 * $0.000001)recipientYour wallet. The agent sends USDC here.network"solana" or "base" — which chain to pay ontokenUSDC contract address on that chainexpiryPayment must arrive before this timestamp (5 min default)nonceUnique per-request; prevents replay of old paymentsOnce an agent pays on-chain and gets a transaction signature, it retries with the X-PAYMENT header:
# After the agent pays USDC on Solana and gets tx signature:
PAYMENT_HEADER=$(echo -n '{
"txSignature": "5KtP...real_solana_tx_signature...vN3",
"network": "solana",
"timestamp": "2026-02-08T12:01:30.000Z",
"signature": "base64_ed25519_signature_here"
}' | base64)
curl -s -X POST http://localhost:3000/api/scrape \
-H "Content-Type: application/json" \
-H "X-PAYMENT: $PAYMENT_HEADER" \
-d '{"url": "https://example.com"}'
# HTTP Status: 200
#
# Response:
# {
# "success": true,
# "url": "https://example.com",
# "status": 200,
# "content_length": 1256,
# "content": "<!doctype html>...",
# "proxy": {
# "provider": "proxies.sx",
# "type": "4G/5G mobile",
# "country": "US"
# },
# "payment": {
# "protocol": "x402",
# "amount": "$0.05",
# "currency": "USDC"
# }
# }The flow is: request -> 402 -> agent pays on-chain -> retry with proof -> 200 with data. This entire round-trip takes under 3 seconds on Solana (most of that is transaction confirmation).
Hono runs natively on Workers. Zero config changes to your app code.
Hono was designed for edge runtimes. Your src/index.ts works on Cloudflare Workers with a single change to the entry point. First, install Wrangler and create the config:
npm i -D wrangler# wrangler.toml
name = "my-paid-api"
main = "src/worker.ts"
compatibility_date = "2026-02-01"
[vars]
PROXY_HOST = "us.proxies.sx"
PROXY_PORT = "5057"
# Secrets (set via wrangler secret put):
# PROXY_USER, PROXY_PASSCreate the Workers entry point. The only difference from the Node version is the export format:
// src/worker.ts
// Cloudflare Workers entry point for Hono
//
// Your app code in src/index.ts stays identical.
// This file just re-exports the Hono app in the
// format Workers expects.
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import {
type PaymentRequirement,
validatePaymentSignature,
} from '@proxies-sx/x402-core'
import { x402Middleware } from '@proxies-sx/x402-hono'
import { verifySolanaPayment } from '@proxies-sx/x402-solana'
type Bindings = {
PROXY_HOST: string
PROXY_PORT: string
PROXY_USER: string
PROXY_PASS: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.use('*', cors())
app.use('*', logger())
// Health check
app.get('/', (c) => {
return c.json({
service: 'my-paid-api',
version: '1.0.0',
protocol: 'x402',
runtime: 'cloudflare-workers',
})
})
const SOLANA_RECIPIENT = '6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv'
const SOLANA_USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
// x402 middleware for paid endpoints
app.use(
'/api/scrape',
x402Middleware({
price: 50000,
recipient: SOLANA_RECIPIENT,
networks: ['solana'],
description: 'Scrape a URL through a real 4G/5G mobile proxy',
resource: '/api/scrape',
verify: async (paymentHeader: string, requirement: PaymentRequirement) => {
const signatureValid = validatePaymentSignature(paymentHeader)
if (!signatureValid) return false
const payment = JSON.parse(
Buffer.from(paymentHeader, 'base64').toString()
)
const result = await verifySolanaPayment({
txSignature: payment.txSignature,
expectedRecipient: SOLANA_RECIPIENT,
expectedAmount: requirement.price,
usdcMint: SOLANA_USDC,
})
return result.verified
},
})
)
app.post('/api/scrape', async (c) => {
const body = await c.req.json<{ url: string }>()
if (!body.url) {
return c.json({ error: 'missing_url' }, 400)
}
const { PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS } = c.env
// On Workers, use fetch with cf.proxy or a tunnel
const response = await fetch(body.url, {
headers: {
'User-Agent':
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15',
},
})
const html = await response.text()
return c.json({
success: true,
url: body.url,
status: response.status,
content_length: html.length,
content: html,
proxy: { provider: 'proxies.sx', type: '4G/5G mobile' },
payment: { protocol: 'x402', amount: '$0.05', currency: 'USDC' },
})
})
export default appSet your secrets and deploy:
# Set secrets (not stored in code)
wrangler secret put PROXY_USER
wrangler secret put PROXY_PASS
# Deploy
wrangler deploy
# Output:
# Uploaded my-paid-api (1.42 sec)
# Published my-paid-api (0.31 sec)
# https://my-paid-api.your-subdomain.workers.dev
# Test it:
curl https://my-paid-api.your-subdomain.workers.dev/Hono runs anywhere. The same src/index.ts works on:
Node.js
npm startUses @hono/node-server
Deno
deno run src/index.tsNative Deno support
Bun
bun src/index.tsFastest startup
AWS Lambda
sst deployVia @hono/aws-lambda
Vercel Edge
vercelEdge Functions
Docker
docker runAny container platform
List your API on agents.proxies.sx/marketplace/ so AI agents can discover and pay for it.
The Proxies.sx marketplace is a directory of x402-enabled services. When you list your API, agents can discover it programmatically, read the pricing, and start paying. Create a service manifest following the spec at agents.proxies.sx/marketplace/submit.md:
# x402 Service Manifest
# Submit this to agents.proxies.sx/marketplace/
service:
name: "Mobile Proxy Scraper API"
version: "1.0.0"
description: >
Scrape any URL through real 4G/5G mobile proxies.
Returns full HTML content with US mobile IP.
Powered by Proxies.sx infrastructure.
url: "https://my-paid-api.your-subdomain.workers.dev"
protocol: "x402"
payment:
currency: "USDC"
networks:
- name: "solana"
recipient: "6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv"
token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
- name: "base"
recipient: "0xF8cD900794245fc36CBE65be9afc23CDF5103042"
token: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"
endpoints:
- path: "/api/scrape"
method: "POST"
price: 50000 # $0.05 in micro-units
description: "Scrape a single URL through mobile proxy"
input:
content_type: "application/json"
schema:
url: "string (required)"
headers: "object (optional)"
output:
content_type: "application/json"
- path: "/api/bulk-scrape"
method: "POST"
price: 200000 # $0.20 in micro-units
description: "Batch scrape up to 10 URLs"
input:
content_type: "application/json"
schema:
urls: "string[] (required, max 10)"
output:
content_type: "application/json"
category: "web-scraping"
tags:
- scraping
- mobile-proxy
- 4g-5g
- data-extraction
contact:
email: "you@example.com"
website: "https://your-website.com"
sla:
uptime: "99.5%"
avg_response_time: "2s"
rate_limit: "100 requests/minute"Push your YAML to agents.proxies.sx/marketplace/. The team reviews and approves within 24 hours.
AI agents query the marketplace directory, find your API by category or tag, and read the pricing.
Payments go directly to your wallet. No middleman fees. No invoices. Just on-chain USDC.
What happens when an AI agent calls your API.
Agent sends POST /api/scrape
Standard HTTP request with JSON body. No authentication headers needed.
x402Middleware checks for X-PAYMENT header
Header missing? Return 402 with PaymentRequirement array (one per network).
Agent parses 402 response
Reads price (50000 micro-units = $0.05), recipient wallet, token address, network options.
Agent submits USDC transfer on Solana
SPL token transfer to 6eUdVws... for 0.05 USDC. Gets transaction signature in ~400ms.
Agent retries with X-PAYMENT header
Header contains base64-encoded JSON: txSignature, network, timestamp, signature.
Middleware calls your verify function
validatePaymentSignature() checks header integrity. verifySolanaPayment() checks the blockchain.
Route handler executes, returns 200
Your scrape logic runs, fetches through Proxies.sx mobile proxy, returns data to the agent.
When the middleware defaults are not enough, use createPaymentRequirement() directly.
Scenarios where you need manual control: dynamic pricing based on input size, metered endpoints where price depends on parameters, or multi-tier access where the same endpoint has different price levels.
import {
createPaymentRequirement,
type PaymentRequirement,
} from '@proxies-sx/x402-core'
// Dynamic pricing: charge per URL in bulk requests
app.post('/api/dynamic-scrape', async (c) => {
const body = await c.req.json<{ urls: string[] }>()
const urlCount = body.urls?.length || 1
// Check for payment header first
const paymentHeader = c.req.header('X-PAYMENT')
if (!paymentHeader) {
// Calculate dynamic price: $0.03 per URL
const pricePerUrl = 30000 // $0.03 in micro-units
const totalPrice = pricePerUrl * urlCount
// Build custom PaymentRequirement
const requirement = createPaymentRequirement({
price: totalPrice,
recipient: '6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv',
network: 'solana',
description: `Scrape ${urlCount} URLs at $0.03 each = $${(totalPrice / 1000000).toFixed(2)}`,
resource: '/api/dynamic-scrape',
expiryMinutes: 10, // 10 min expiry for bulk jobs
})
return c.json(
{
status: 402,
message: 'Payment Required',
paymentRequirements: [requirement],
pricing: {
per_url: '$0.03',
url_count: urlCount,
total: `$${(totalPrice / 1000000).toFixed(2)}`,
},
},
402
)
}
// Verify payment and proceed...
// (same verify logic as before)
})// Example: Tiered access with different prices
import { createPaymentRequirement } from '@proxies-sx/x402-core'
// Premium tier: residential proxy + JS rendering
// Standard tier: mobile proxy, HTML only
app.post('/api/premium-scrape', async (c) => {
const paymentHeader = c.req.header('X-PAYMENT')
if (!paymentHeader) {
// Offer two payment tiers
const standard = createPaymentRequirement({
price: 50000, // $0.05
recipient: '6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv',
network: 'solana',
description: 'Standard: mobile proxy, HTML only',
resource: '/api/premium-scrape?tier=standard',
})
const premium = createPaymentRequirement({
price: 250000, // $0.25
recipient: '6eUdVwsPArTxwVqEARYGCh4S2qwW2zCs7jSEDRpxydnv',
network: 'solana',
description: 'Premium: residential proxy + JavaScript rendering',
resource: '/api/premium-scrape?tier=premium',
})
return c.json({
status: 402,
message: 'Payment Required',
paymentRequirements: [standard, premium],
}, 402)
}
// Verify and determine which tier was paid for...
})Make your x402 API production-ready.
import { verifySolanaPayment } from '@proxies-sx/x402-solana'
// Production verify function with comprehensive error handling
async function productionVerify(
paymentHeader: string,
requirement: PaymentRequirement
): Promise<boolean> {
try {
// 1. Validate header format
let payment: {
txSignature: string
network: string
timestamp: string
signature: string
}
try {
payment = JSON.parse(
Buffer.from(paymentHeader, 'base64').toString()
)
} catch {
console.error('[x402] Invalid payment header encoding')
return false
}
// 2. Check required fields
if (!payment.txSignature || !payment.network || !payment.timestamp) {
console.error('[x402] Missing required payment fields')
return false
}
// 3. Check timestamp freshness (reject payments older than 5 min)
const paymentTime = new Date(payment.timestamp).getTime()
const now = Date.now()
if (now - paymentTime > 5 * 60 * 1000) {
console.error('[x402] Payment timestamp too old:', payment.timestamp)
return false
}
// 4. Validate cryptographic signature
const signatureValid = validatePaymentSignature(paymentHeader)
if (!signatureValid) {
console.error('[x402] Invalid payment signature')
return false
}
// 5. Verify on-chain (with retries)
if (payment.network === 'solana') {
const result = await verifySolanaPayment({
txSignature: payment.txSignature,
expectedRecipient: SOLANA_RECIPIENT,
expectedAmount: requirement.price,
usdcMint: SOLANA_USDC,
maxRetries: 3,
requireFinalized: false, // 'confirmed' is fast enough
})
if (!result.verified) {
console.error('[x402] Solana verification failed:', result.error)
return false
}
console.log(`[x402] Payment verified: ${result.amount} USDC from ${result.sender}`)
return true
}
console.error('[x402] Unsupported network:', payment.network)
return false
} catch (err) {
console.error('[x402] Verification error:', err)
return false
}
}
// Replay protection: track used transaction signatures
const usedSignatures = new Set<string>()
async function verifyWithReplayProtection(
paymentHeader: string,
requirement: PaymentRequirement
): Promise<boolean> {
const payment = JSON.parse(
Buffer.from(paymentHeader, 'base64').toString()
)
// Reject if this tx signature was already used
if (usedSignatures.has(payment.txSignature)) {
console.error('[x402] Replay attempt:', payment.txSignature)
return false
}
const verified = await productionVerify(paymentHeader, requirement)
if (verified) {
usedSignatures.add(payment.txSignature)
// Cleanup old signatures after 1 hour
setTimeout(() => {
usedSignatures.delete(payment.txSignature)
}, 60 * 60 * 1000)
}
return verified
}Track used tx signatures in a Set (or Redis for distributed). Reject duplicates.
Reject payment headers older than 5 minutes. Prevents stale payment reuse.
Always call validatePaymentSignature() before on-chain verification. Fast cryptographic check.
Log every payment event: verified, failed, replayed. Essential for debugging and accounting.
my-paid-api/
├── src/
│ ├── index.ts # Main Hono app (Node/Deno/Bun)
│ └── worker.ts # Cloudflare Workers entry point
├── package.json
├── tsconfig.json
├── wrangler.toml # Cloudflare Workers config
├── service-manifest.yaml # Marketplace submission
└── .env # Local env vars (not committed)
# .env contents:
PROXY_HOST=us.proxies.sx
PROXY_PORT=5057
PROXY_USER=your_username
PROXY_PASS=your_password
PORT=3000At $0.05/request with moderate agent traffic, here is what the numbers look like:
1,000/day
$50/day
$1,500/mo
10,000/day
$500/day
$15,000/mo
100,000/day
$5,000/day
$150,000/mo
Zero platform fees. All USDC goes directly to your wallet. Compare this to Stripe (2.9% + $0.30) or RapidAPI (20% cut). See our x402 vs Stripe comparison for the full breakdown.
You just built a production-grade paid API endpoint in 15 minutes. AI agents can discover it, pay for it with USDC, and use it -- no accounts, no API keys, no human checkout flows. Now ship it.
PROXIES.SX Team
Building AI-native proxy infrastructure