A crypto sentiment API that returns a bull/bear score for any token symbol. Agents call it, get 5 free trials, then pay $0.01 per call in USDC on Base. The entire payment flow is handled by HTTP 402 headers โ no Stripe, no API keys, no auth middleware.
| Feature | How |
|---|---|
| Free trials | 5 calls per registered wallet, register a wallet |
| Payment | HTTP 402 + x-402-amount header โ agent pays in USDC |
| Registration | POST /register โ auto-creates wallet + 5 free trial calls |
| Discovery | GET /.well-known/x402 โ machine-readable manifest |
| Health check | GET /api/agent-ready โ one-request connectivity test |
Create a new directory and initialize:
mkdir sentiment-api && cd sentiment-api
npm init -y
npm install express
touch server.js
Now paste this into server.js:
const express = require('express');
const app = express();
app.use(express.json());
const PORT = process.env.PORT || 3456;
const PRICE_CENTS = 1; // $0.01 per call
// โโ Trial tracking (in-memory; use Redis/DB in production) โโ
const trials = new Map(); // IP โ count
function getTrialsRemaining(ip) {
const used = trials.get(ip) || 0;
return Math.max(0, 5 - used);
}
function useTrial(ip) {
const used = trials.get(ip) || 0;
trials.set(ip, used + 1);
return 5 - (used + 1);
}
// โโ Payment info (your wallet on Base) โโ
const PAYMENT = {
chain: 'base',
token: 'USDC',
recipient: '0xf16F0882de08315B438E9f3a2Abfb2d2E5d94ECA', // your wallet
amount: PRICE_CENTS // in cents
};
// โโ Step 2: The API endpoint โโ
app.get('/api/v1/sentiment', (req, res) => {
const ip = req.ip || req.connection.remoteAddress;
const symbol = (req.query.symbol || 'BTC').toUpperCase();
const remaining = getTrialsRemaining(ip);
// TRIAL PATH: free for first 5 calls
if (remaining > 0) {
useTrial(ip);
const score = Math.round(30 + Math.random() * 70); // 30-100
const sentiment = score > 60 ? 'bullish' : score < 45 ? 'bearish' : 'neutral';
return res.json({
symbol,
score,
sentiment,
_trial: {
remaining: remaining - 1,
total: 5,
message: `${remaining - 1} free trials left. Register on minia2a.uk for 5 trial calls.`,
register: 'POST /register {"name":"my-agent"}'
}
});
}
// PAID PATH: trial exhausted โ 402 Payment Required
res.status(402);
res.set('x-402-amount', String(PAYMENT.amount));
res.set('x-402-chain', PAYMENT.chain);
res.set('x-402-token', PAYMENT.token);
res.set('x-402-recipient', PAYMENT.recipient);
res.set('x-402-register', 'POST /register');
return res.json({
error: 'payment_required',
message: `This endpoint costs $${(PAYMENT.amount/100).toFixed(2)}/call`,
payment: PAYMENT,
register: '/register'
});
});
// โโ Step 3: Registration endpoint โโ
app.post('/register', (req, res) => {
const { name } = req.body || {};
if (!name) return res.status(400).json({ error: 'name required' });
// In production: create wallet, issue credits
// For this demo: register on minia2a.uk (free, instant)
return res.json({
ok: true,
message: `Agent "${name}" registered.`,
next: 'Sign a wallet for 5 free trial calls on minia2a.uk -- no registration: ' +
'curl "https://minia2a.uk/x402/gas?wallet=0xYOUR_WALLET" ' +
'-H "X-Wallet-Signature: 0xYOUR_SIGNATURE" -H "X-Trial-Timestamp: "'
});
});
// โโ Step 4: Agent-ready handshake โโ
app.get('/api/agent-ready', (req, res) => {
res.json({
status: 'ready',
version: '1.0.0',
protocols: ['x402'],
payment: PAYMENT,
trial: { limit: 5, unit: 'calls_per_wallet' },
registration: { endpoint: 'POST /register', body: { name: 'string' } },
endpoints: { sentiment: 'GET /api/v1/sentiment?symbol=BTC' }
});
});
// โโ Step 5: /.well-known/x402 manifest โโ
app.get('/.well-known/x402', (req, res) => {
res.json({
protocol: 'x402',
version: '1.0.0',
payment: PAYMENT,
trial: { anonymous: '5 free trial calls per IP' },
register: 'POST /register',
catalog: 'GET /api/v1/sentiment?symbol=BTC',
agent_ready: 'GET /api/agent-ready'
});
});
app.listen(PORT, () => {
console.log(`Sentiment API live on http://localhost:${PORT}`);
console.log(`Agent-ready: http://localhost:${PORT}/api/agent-ready`);
console.log(`Test: curl http://localhost:${PORT}/api/v1/sentiment?symbol=ETH`);
});
node server.js
In another terminal, test the three key flows:
# 1. Agent-ready handshake
curl http://localhost:3456/api/agent-ready | jq .
# 2. Free trial call
curl http://localhost:3456/api/v1/sentiment?symbol=ETH | jq .
# 3. Trial info in response
# Look for _trial.remaining and _trial.register fields
# 4. Test the well-known manifest
curl http://localhost:3456/.well-known/x402 | jq .
# 5. Simulate registration
curl -X POST http://localhost:3456/register \
-H content-type:application/json \
-d '{"name":"my-agent"}' | jq .
When an auto-mode agent hits your API and trials are exhausted, your 402 response must include these four headers. Without them, the agent cannot pay you:
| Header | Example | Required? |
|---|---|---|
x-402-amount | 1 (cents, so $0.01) | โ Yes |
x-402-chain | base | โ Yes |
x-402-token | USDC | โ Yes |
x-402-recipient | 0xf16F... | โ Yes |
x-402-register | POST /register | Recommended |
x-credits-required | 1 | Recommended |
Why this matters: Aug 14 auto mode means Claude Code agents will read these headers programmatically. If your 402 response says "Payment Required" in HTML but doesn't include these headers, the agent sees an error, not a payment instruction. Your API is invisible to autonomous spenders.
One signed command publishes your API to the marketplace (third-party listings are reviewed before going live). Agents discover it through search, trial it for free, and pay when they need more:
# Sign minia2a publish: <your-wallet> with EIP-191, then:
curl -X POST https://minia2a.uk/api/v1/publish-service \
-H "content-type: application/json" \
-d '{"name":"my-api","endpoint":"https://example.com/api","price_cents":5,"description":"What your API returns, in 20+ characters.","wallet":"0xYOUR_WALLET","signature":"0xYOUR_SIGNATURE"}'
# Third-party listings are reviewed before they go live (reviewStatus: pending).
Response:
That's it. Your API is now discoverable by any Claude Code agent with auto mode enabled. They can find it, trial it, exhaust the free calls, receive a machine-readable 402, and pay autonomously โ all without you writing a single line of payment code.
Pick any hosting provider. Here's the one-command deploy for three common options:
# Option A: fly.io (free tier, auto-HTTPS)
fly launch --name sentiment-api
# Option B: Render (free tier, auto-HTTPS)
# Push to GitHub โ connect repo โ auto-deploy
# Option C: VPS (any provider)
scp server.js user@host:~/
ssh user@host 'cd ~ && npm install express && node server.js &'
After deploy, verify the agent-ready endpoint is accessible:
curl https://your-domain.com/api/agent-ready | jq .status
# โ "ready"
Then test with the auto-mode validator โ paste your URL, get an instant readiness score across 9 signals.
Before Claude Code auto mode ships Aug 14, verify your API passes these checks:
Three things converge on Aug 14:
{daily_limit_usdc:5, max_per_call_usdc:1} gives agents hard spending capsAn API with machine-readable 402 headers can participate in this economy. An API without them cannot. The difference is four HTTP headers and a 15-minute tutorial.
The agent economy doesn't need another payment SDK. It needs APIs that speak HTTP 402 fluently. This tutorial gives you the vocabulary. Aug 14 is when the agents start reading.