📰 free-crypto-news Integration Guide
Add premium tiers to the free crypto news API using x402
Overview
Repository: https://github.com/nirholas/free-crypto-news (20⭐)
free-crypto-news provides RSS/Atom feeds and a JSON API. This guide adds premium features while keeping the core service free.
Premium Features
| Feature | Price | Description |
|---|---|---|
| Real-time Firehose | $0.10/day | WebSocket feed, <1s latency |
| AI Summaries | $0.001/summary | GPT-powered article summaries |
| Breaking Alerts | $0.05/day | Push notifications |
| Deep Archive | $0.01/query | Full historical search |
| Custom Feeds | $0.50/month | Personalized keyword feeds |
Installation
Step 1: Define Premium Tiers
Create src/tiers.ts:
import { createPremiumTier } from "@nirholas/x402-ecosystem/premium";
export const NEWS_TIERS = createPremiumTier({
free: {
features: ["rss", "json-api", "30-day-archive"],
rateLimit: 100,
ratePeriod: "day",
},
basic: {
price: "4.99",
period: "monthly",
features: ["rss", "json-api", "90-day-archive", "ai-summaries"],
rateLimit: 1000,
ratePeriod: "day",
},
premium: {
price: "19.99",
period: "monthly",
features: ["all", "firehose", "alerts", "custom-feeds", "api-priority"],
rateLimit: 10000,
ratePeriod: "day",
},
payAsYouGo: {
price: "0.001",
period: "per-request",
features: ["ai-summaries", "deep-archive"],
},
});
export const FEATURE_PRICES = {
"ai-summary": "0.001",
"deep-archive-query": "0.01",
"firehose-day": "0.10",
"breaking-alerts-day": "0.05",
"custom-feed-month": "0.50",
};
Step 2: Add x402 Middleware
Create src/middleware/x402.ts:
import express from "express";
import {
x402Paywall,
x402DynamicPaywall,
dynamicPrice,
} from "@nirholas/universal-crypto-mcp";
import { FEATURE_PRICES } from "../tiers";
const RECIPIENT = process.env.PAYMENT_ADDRESS as `0x${string}`;
/**
* Paywall for AI summaries - $0.001 per summary
*/
export const summaryPaywall = x402Paywall({
price: FEATURE_PRICES["ai-summary"],
recipient: RECIPIENT,
description: "AI-powered article summary",
});
/**
* Paywall for archive queries - $0.01 per query
*/
export const archivePaywall = x402Paywall({
price: FEATURE_PRICES["deep-archive-query"],
recipient: RECIPIENT,
description: "Deep archive search query",
});
/**
* Dynamic paywall based on data size
*/
export const firehosePaywall = x402DynamicPaywall({
pricing: dynamicPrice({
basePrice: FEATURE_PRICES["firehose-day"],
// Discount for longer subscriptions
modifiers: [
{ condition: (ctx) => ctx.duration >= 7, multiplier: 0.9 },
{ condition: (ctx) => ctx.duration >= 30, multiplier: 0.8 },
],
}),
recipient: RECIPIENT,
description: "Real-time news firehose",
});
/**
* Revenue sharing for content
*/
export const contentPaywall = (sourceAddress: `0x${string}`) =>
x402Paywall({
price: "0.001",
recipient: RECIPIENT,
revenueSplit: [
{ address: sourceAddress, percent: 70 }, // Content source
{ address: RECIPIENT, percent: 30 }, // Platform
],
description: "Premium content access",
});
Step 3: Update API Routes
Modify src/routes/api.ts:
import express from "express";
import {
summaryPaywall,
archivePaywall,
firehosePaywall,
} from "../middleware/x402";
const router = express.Router();
// ============================================================
// FREE ENDPOINTS (unchanged)
// ============================================================
router.get("/news/latest", async (req, res) => {
const news = await getLatestNews(50);
res.json({ news, tier: "free" });
});
router.get("/rss", async (req, res) => {
const rss = await generateRSS();
res.type("application/rss+xml").send(rss);
});
// ============================================================
// PREMIUM ENDPOINTS (with x402)
// ============================================================
/**
* AI Summary - $0.001 per article
*/
router.get(
"/news/:id/summary",
summaryPaywall, // Requires payment
async (req, res) => {
const article = await getArticle(req.params.id);
const summary = await generateAISummary(article);
res.json({
articleId: req.params.id,
summary,
keyPoints: summary.keyPoints,
sentiment: summary.sentiment,
tier: "premium",
});
}
);
/**
* Deep Archive Search - $0.01 per query
*/
router.get(
"/archive/search",
archivePaywall,
async (req, res) => {
const { query, from, to, sources } = req.query;
const results = await searchArchive({
query: query as string,
dateRange: { from, to },
sources: sources?.split(","),
});
res.json({
query,
results,
count: results.length,
tier: "premium",
});
}
);
/**
* Real-time Firehose - $0.10/day
*/
router.get(
"/firehose/subscribe",
firehosePaywall,
async (req, res) => {
// Return WebSocket endpoint after payment
const wsToken = generateWSToken(req.paymentProof);
res.json({
websocket: `wss://news.api.com/firehose?token=${wsToken}`,
expiresAt: Date.now() + 24 * 60 * 60 * 1000,
tier: "premium",
});
}
);
export default router;
Step 4: Add MCP Tools
Create src/mcp/server.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { registerX402 } from "@nirholas/universal-crypto-mcp";
import { z } from "zod";
const server = new McpServer({
name: "free-crypto-news",
version: "2.0.0",
});
// Register x402 payment tools
registerX402(server);
// ============================================================
// FREE TOOLS
// ============================================================
server.tool(
"news_latest",
"Get latest crypto news (free)",
{ limit: z.number().optional() },
async ({ limit }) => {
const news = await fetch(`https://api.news.com/news/latest?limit=${limit ?? 10}`);
return { content: [{ type: "text", text: await news.text() }] };
}
);
// ============================================================
// PREMIUM TOOLS (instruct to use x402_pay_request)
// ============================================================
server.tool(
"news_summarize",
"Get AI summary of an article ($0.001). Use x402_pay_request to access this premium endpoint.",
{
articleId: z.string().describe("Article ID to summarize"),
},
async ({ articleId }) => {
return {
content: [{
type: "text",
text: JSON.stringify({
instruction: "Use x402_pay_request to call this premium endpoint",
url: `https://api.news.com/news/${articleId}/summary`,
cost: "$0.001",
method: "GET",
}),
}],
};
}
);
server.tool(
"news_archive_search",
"Search historical news archive ($0.01/query). Use x402_pay_request for premium access.",
{
query: z.string(),
from: z.string().optional(),
to: z.string().optional(),
},
async ({ query, from, to }) => {
const params = new URLSearchParams({ query });
if (from) params.set("from", from);
if (to) params.set("to", to);
return {
content: [{
type: "text",
text: JSON.stringify({
instruction: "Use x402_pay_request to access premium archive",
url: `https://api.news.com/archive/search?${params}`,
cost: "$0.01",
method: "GET",
}),
}],
};
}
);
export { server };
Step 5: Revenue Tracking
Create src/analytics/revenue.ts:
import { X402Analytics, createFileAnalytics } from "@nirholas/universal-crypto-mcp";
const analytics = createFileAnalytics("./data/revenue.json");
export async function trackRevenue(payment: {
amount: string;
feature: string;
source?: string;
}) {
await analytics.record({
type: "payment_received",
amount: payment.amount,
metadata: {
feature: payment.feature,
contentSource: payment.source,
},
});
}
export async function getRevenueReport(period: "day" | "week" | "month") {
const stats = await analytics.getStats(period);
return {
period,
totalRevenue: stats.total,
byFeature: stats.byMetadata("feature"),
topSources: stats.byMetadata("contentSource").slice(0, 10),
transactions: stats.count,
};
}
// Weekly payout to content sources
export async function distributeRevenue() {
const week = await analytics.getStats("week");
const bySource = week.byMetadata("contentSource");
// 70% goes to content sources
for (const [source, amount] of Object.entries(bySource)) {
const payout = parseFloat(amount) * 0.7;
// Queue payout via x402 batch payment
}
}
Testing
# Start server with x402
export PAYMENT_ADDRESS=0x...
export X402_CHAIN=arbitrum-sepolia
npm run dev
# Test free endpoint
curl http://localhost:3000/api/news/latest
# Test premium endpoint (will return 402)
curl http://localhost:3000/api/news/123/summary
# Response: HTTP 402 Payment Required
Pricing Summary
| Endpoint | Price | Revenue Split |
|---|---|---|
/news/latest |
Free | - |
/rss |
Free | - |
/news/:id/summary |
$0.001 | 100% platform |
/archive/search |
$0.01 | 100% platform |
/firehose/subscribe |
$0.10/day | 100% platform |
| Premium content | $0.001 | 70% source / 30% platform |
Next Steps
- ✅ Install dependencies
- ✅ Define premium tiers
- ✅ Add x402 middleware
- ✅ Update API routes
- ✅ Add MCP tools
- 🔲 Set up revenue tracking
- 🔲 Deploy to production
Marketing: "The news stays free. Premium features pay for themselves."