How to Build a Paid API Agent with MoltPe (2026)
What you will build
A production-ready HTTP endpoint that charges 0.01 USDC per request, runs an OpenAI call behind it, and returns the result. Callers only get billed when the AI call succeeds. The wallet receiving the USDC is an isolated MoltPe agent wallet with a spending policy, so even if your server is compromised the attacker cannot drain it beyond your configured sweep rules.
The architecture is boring in the best way. One Express app, one middleware, one LLM call, one deployment. No queues, no webhooks, no Stripe account, no KYC flow. The x402 protocol does all the payment coordination over vanilla HTTP headers.
When you are done you will have a URL like https://your-api.run.app/v1/summarize that any MoltPe-equipped agent can call and pay automatically. Callers include Claude Desktop, Cursor agents, LangChain pipelines, or other paid API agents chaining together.
Prerequisites
- Node 20+ and npm installed locally.
- A MoltPe account with an API key (
mp_test_for dev,mp_live_for prod). - An OpenAI or Anthropic API key for the AI call inside the endpoint.
- A Cloud Run or Vercel account for deployment (both have free tiers).
- Basic comfort with
curland environment variables.
Step 1 — Create a receiving agent wallet
Spin up a MoltPe wallet that will collect USDC from callers. This is a receive agent — it does not spend, it only accumulates. Keep the agent ID handy; you will paste the wallet address into the x402 middleware config.
# Create an isolated receiving wallet on Polygon mainnet.
curl -X POST https://api.moltpe.com/v1/agents/create \
-H "Authorization: Bearer $MOLTPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "summarizer-api-receiver", "network": "polygon" }'
{
"agent_id": "ag_01JMT3K9P4R7X2VB8N5CQZDHEW",
"wallet_address": "0xC3e9F1d3B5a7C9e1F3b5A7c9E1f3B5a7C9e1F3b5",
"network": "polygon",
"status": "active"
}
Step 2 — Scaffold the Express server
Create a fresh Node project and install the three packages you need: Express for the HTTP surface, the MoltPe x402 middleware for payment gating, and the OpenAI SDK for the AI call behind the paywall.
mkdir paid-summarizer && cd paid-summarizer
npm init -y
npm install express @moltpe/x402-express openai
Create server.js with one public health route and a stubbed paid route you will fill in next.
// server.js — entry point for the paid summarization API.
import express from "express";
import OpenAI from "openai";
const app = express();
app.use(express.json());
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
app.get("/health", (req, res) => res.json({ ok: true }));
// Paid route: wired up in Step 3.
app.post("/v1/summarize", (req, res) => res.status(501).json({ todo: true }));
const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`paid-summarizer on :${port}`));
Step 3 — Add the x402 middleware and AI handler
This is the whole trick. Drop moltpeX402() in front of the handler. Callers without payment get a 402 with payment instructions; callers with a valid proof fall through to your AI code. The middleware verifies every payment against MoltPe before calling next().
// Paid /v1/summarize route. Price: 0.01 USDC per request.
import { moltpeX402 } from "@moltpe/x402-express";
const requirePayment = moltpeX402({
price: "0.01",
token: "USDC",
network: "polygon",
recipient: "0xC3e9F1d3B5a7C9e1F3b5A7c9E1f3B5a7C9e1F3b5",
apiKey: process.env.MOLTPE_API_KEY,
idempotencyWindowSeconds: 60,
});
app.post("/v1/summarize", requirePayment, async (req, res) => {
const { text } = req.body;
if (!text) return res.status(400).json({ error: "text required" });
try {
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "Summarize in 2 sentences." },
{ role: "user", content: text },
],
});
res.json({ summary: completion.choices[0].message.content });
} catch (err) {
// Auto-refund if the AI call fails — caller shouldn't pay for errors.
await fetch("https://api.moltpe.com/v1/payments/refund", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MOLTPE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ payment_id: req.moltpePaymentId, reason: "llm_failure" }),
});
res.status(502).json({ error: "ai_failed_refund_issued" });
}
});
Read the error handler carefully. If the LLM call throws, the middleware has already confirmed the caller paid — so we immediately refund. This turns the endpoint into a pay-on-success service, which dramatically improves caller trust.
Step 4 — Set receive-side policy and sweep
A receiving wallet should not hoard funds. Configure MoltPe to sweep accumulated USDC to your treasury wallet once per day. This limits blast radius if the API key ever leaks — an attacker can only touch what accumulated since the last sweep.
curl -X POST https://api.moltpe.com/v1/agents/ag_01JMT3K9P4R7X2VB8N5CQZDHEW/sweep-policy \
-H "Authorization: Bearer $MOLTPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"treasury_address": "0xF1d3B5a7C9e1F3b5A7c9E1f3B5a7C9e1F3b5A7c9",
"frequency": "daily",
"min_balance_to_sweep": "10.00"
}'
From now on, any time the balance crosses 10 USDC, MoltPe moves it to your treasury wallet automatically. You never log in to a dashboard to move funds.
Step 5 — Deploy to Cloud Run or Vercel
Both platforms work. Here is the Cloud Run path because it gives you a stable URL and full Node runtime. Create a Dockerfile, build, and deploy.
# Dockerfile — minimal Node 20 container for the paid API.
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]
gcloud run deploy paid-summarizer \
--source . \
--region us-central1 \
--allow-unauthenticated \
--update-env-vars MOLTPE_API_KEY=$MOLTPE_API_KEY,OPENAI_API_KEY=$OPENAI_API_KEY
Cloud Run returns a URL like https://paid-summarizer-xyz.run.app. That is your paid API. Vercel works the same way with vercel --prod after setting the same env vars in the project settings.
Testing the agent
Use the MoltPe x402 client from a second terminal or a separate agent wallet. The client automatically handles the 402 handshake.
// Client agent — calls the paid endpoint, pays transparently.
import { createX402Client } from "@moltpe/x402-client";
const client = createX402Client({
apiKey: process.env.MOLTPE_API_KEY,
agentId: "ag_01JMT5R7W2X9B4V6N3CQZDPKEM", // a spending agent
maxPaymentUsd: "0.05",
});
const res = await client.fetch("https://paid-summarizer-xyz.run.app/v1/summarize", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: "Long article to summarize..." }),
});
console.log(await res.json());
// { summary: "Two-sentence summary of the input text." }
In the MoltPe dashboard, the receiving wallet balance ticks up by 0.01 USDC per successful call. Refunded failures never show. This is your live usage graph — no Stripe webhook, no analytics pipeline needed.
Production checklist
- Rotate keys: generate a fresh
mp_live_key for the Cloud Run service and never reuse the dev key. - Rate limit: add
express-rate-limitin front of the x402 middleware to reject abusive callers before they even see the 402. - Log errors: forward 5xx responses and refund events to your log aggregator — refund volume is the best leading indicator of LLM trouble.
- Monitor the sweep: set an alert if daily sweep transactions stop arriving at the treasury — it usually means something upstream is broken.
- Document the endpoint: publish the price, method, and expected payload on a public docs page so other agents know how to call you.
Frequently Asked Questions
How much should I charge per request?
Match your marginal cost plus a margin. If an LLM call costs you $0.004 in tokens, charging $0.01 to $0.02 per request covers cost plus infra and leaves headroom. USDC supports micropayments down to six decimals, so you can price fractions of a cent without floating-point pain.
Do callers need a crypto wallet?
Not in the traditional sense. They need a MoltPe agent wallet, which is just an API-managed account. The x402 client library handles the 402 handshake, payment construction, and retry without any manual signing. From the caller's perspective it looks like a normal HTTP request with an API key header.
What if a caller times out between the 402 and the retry?
The x402 middleware uses payment proofs with short expiry windows. If the caller submits payment but loses the response, MoltPe records the transaction and the caller can re-present the same proof to get the cached response for the idempotency window, usually 60 seconds. No double-charging, no lost work.
Can I run this on a free tier?
Yes. Cloud Run has a generous free tier and Vercel Hobby works for light traffic. MoltPe itself charges transaction-based fees, not per-endpoint fees, so you pay only when money moves. That means your fixed cost stays near zero until you have real paying callers.
How do I handle refunds if the AI call fails?
Call POST /v1/payments/refund with the payment_id and optional reason. MoltPe returns the USDC to the caller's wallet within seconds. Wire this into your error handler so a failed LLM response auto-refunds without manual intervention.
Ship your paid API today
Grab an API key, paste the snippets, and deploy. Your first paying caller could be an hour away.
Create my receiving wallet →About MoltPe
MoltPe is AI-native payment infrastructure that gives AI agents isolated wallets with programmable spending policies for autonomous USDC transactions. Live on Polygon PoS, Base, and Tempo. Supports REST, MCP, and x402.