Express backend for the Proxy Endpoints Demo, demonstrating how to protect API endpoints with AnySpend x402 payment requirements.
This server wraps third-party APIs (TAAPI.io for technical indicators, RapidAPI Twitter for social data) and protects them with x402 payment middleware. Clients must submit valid x402 payments to access these endpoints.
- x402 Payment Middleware: Automatic payment verification and settlement
- TAAPI.io Integration: Technical indicators (RSI, MACD, EMA, Bollinger Bands, etc.)
- Twitter Data Integration: Search and user profile data via RapidAPI
- Balance Fetching: Multi-chain token balance queries via Sim Dune API
- CORS Support: Configurable for frontend access
- Caching: HTTP response caching for improved performance
- Express for HTTP server
- @b3dotfun/anyspend-x402-express for payment middleware
- Viem for Ethereum interactions
- TypeScript with NodeNext module resolution
- Node.js 18+
- pnpm (or npm/yarn)
- TAAPI.io API key (get from https://taapi.io)
- RapidAPI key with Twitter API access (get from https://rapidapi.com)
- Optional: Sim Dune API key for balance queries
Create .env file in apps/server:
# Server Configuration
NODE_ENV=development
PORT=4021
# AnySpend x402 Configuration
ANYSPEND_FACILITATOR_URL=https://mainnet.anyspend.com/x402
# Supported networks: base, polygon, arbitrum, bsc
ANYSPEND_NETWORK=base
ANYSPEND_RECEIVER_ADDRESS=0x93f6fdB246Da7204d2845230967725256493A0E5
ANYSPEND_PRICE_USD=$0.01
# Optional: Override network per service
# TAAPI_NETWORK=bsc
# TWITTER_NETWORK=base
# Optional: BSC-specific token configuration (Binance-Peg USDC uses 18 decimals)
# TAAPI_PRICE_ASSET=0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d
# TAAPI_PRICE_DECIMALS=18
# TAAPI.io Configuration
TAAPI_BASE_URL=https://api.taapi.io
TAAPI_SECRET_KEY=your_taapi_secret_key_here
# RapidAPI Twitter Configuration
RAPIDAPI_KEY=your_rapidapi_key_here
TWITTER_RAPIDAPI_HOST=twitter-v24.p.rapidapi.com
TWITTER_RAPIDAPI_SEARCH_PATH=/search
TWITTER_RAPIDAPI_PROFILE_PATH=/user/profile
# Balance API (Optional)
SIM_DUNE_API_KEY=your_sim_dune_api_key_hereFrom the monorepo root:
# Install dependencies
pnpm install
# Run server only
pnpm dev:server
# Or run all apps
pnpm dev:allThe server will be available at http://localhost:4021
apps/server/
├── src/
│ ├── lib/
│ │ ├── cache.ts # HTTP caching utilities
│ │ └── http.ts # HTTP client with caching
│ ├── routes/
│ │ ├── index.ts # Main router + balance endpoint
│ │ ├── taapi.ts # TAAPI indicator endpoints
│ │ └── twitter.ts # Twitter data endpoints
│ ├── server/
│ │ └── index.ts # Express app setup + x402 middleware
│ ├── services/
│ │ ├── taapi.ts # TAAPI.io client
│ │ └── twitter.ts # RapidAPI Twitter client
│ └── types/ # TypeScript type definitions
├── dist/ # Compiled output (gitignored)
└── package.json
GET /api/balances/:address
Returns token balances across multiple networks for the given address.
Response:
{
"address": "0x...",
"balances": [
{
"network": "base",
"chainId": "8453",
"tokens": [
{
"symbol": "USDC",
"balance": "100.50",
"tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
}
]
}
]
}All TAAPI endpoints require x402 payment headers.
GET /api/taapi/rsi?symbol=BTC/USDT&exchange=binance&interval=1h
GET /api/taapi/macd?symbol=BTC/USDT&exchange=binance&interval=1h
GET /api/taapi/ema?symbol=BTC/USDT&exchange=binance&interval=1h&period=20
GET /api/taapi/bbands?symbol=BTC/USDT&exchange=binance&interval=1h
GET /api/taapi/adx?symbol=BTC/USDT&exchange=binance&interval=1h
Query Parameters:
symbol: Trading pair (e.g., BTC/USDT)exchange: Exchange name (e.g., binance)interval: Timeframe (e.g., 1h, 4h, 1d)period: Indicator period (for EMA, etc.)
GET /api/twitter/search?query=bitcoin&count=10
GET /api/twitter/profile?username=elonmusk
Search Parameters:
query: Search termcount: Number of results (default: 10)
Profile Parameters:
username: Twitter username (without @)
import { anyspendX402Factory } from '@b3dotfun/anyspend-x402-express';
const anyspendX402 = anyspendX402Factory({
facilitatorUrl: process.env.ANYSPEND_FACILITATOR_URL,
receiverAddress: process.env.ANYSPEND_RECEIVER_ADDRESS,
network: process.env.ANYSPEND_NETWORK,
price: process.env.ANYSPEND_PRICE_USD,
});
// Apply to protected routes
app.use('/api/taapi', anyspendX402, taapiRouter);
app.use('/api/twitter', anyspendX402, twitterRouter);- Client makes request with x402 payment headers
- Middleware verifies payment with facilitator
- If valid, request proceeds to handler
- Payment is settled to
ANYSPEND_RECEIVER_ADDRESS - Response returned to client
# Development mode with auto-reload
pnpm dev
# Build for production
pnpm build
# Run production build
pnpm start
# Type checking
pnpm typecheck
# Lint code
pnpm lint
# Format code
pnpm format- Create service in
src/services/to wrap the external API - Create route handler in
src/routes/ - Apply
anyspendX402middleware to the router - Register router in
src/server/index.ts
Example:
// src/services/myapi.ts
export async function fetchData(params: any) {
// External API call
}
// src/routes/myapi.ts
import { Router } from 'express';
import { fetchData } from '../services/myapi.js';
const router = Router();
router.get('/', async (req, res) => {
const data = await fetchData(req.query);
res.json(data);
});
export default router;
// src/server/index.ts
import myApiRouter from '../routes/myapi.js';
app.use('/api/myapi', anyspendX402, myApiRouter);The server implements HTTP caching to reduce external API calls:
- TAAPI responses: Cached based on symbol, interval, indicator
- Twitter responses: Cached based on query/username
- Cache entries automatically expire based on
Cache-Controlheaders
The server returns standard HTTP error codes:
400: Bad request (missing parameters)401: Payment required or invalid404: Resource not found500: Internal server error502: External API error
Issue: TAAPI endpoints returning 401
Solution: Check TAAPI_SECRET_KEY is valid and TAAPI account has credits
Issue: Twitter endpoints failing
Solution: Verify RAPIDAPI_KEY has access to Twitter API v2
Issue: x402 payment verification failing
Solution: Ensure ANYSPEND_FACILITATOR_URL is reachable and configured correctly
Issue: Balance endpoint returns empty
Solution: Provide SIM_DUNE_API_KEY in environment variables
- Never expose API keys in responses or logs
- Validate all input parameters before passing to external APIs
- Rate limit endpoints in production (not included in demo)
- Use HTTPS in production
- Rotate API keys regularly
- Client Application
- Root README - Architecture overview