Examples
A paid API, a paid MCP tool, and an agent paying for both.
A paid JSON API (Node)
import express from "express";
import { createX402Xrpl, sqliteStore } from "@openwallet/x402-xrpl";
const x402 = createX402Xrpl({
network: "xrpl:1", // Testnet while you build
payTo: "rYourTestnetAddress…",
rpc: "https://s.altnet.rippletest.net:51234",
store: sqliteStore("./x402.db"),
});
const app = express();
app.get("/v1/quote",
x402.http({ price: { asset: "XRP", drops: "10000" }, description: "One quote" }),
(req, res) => res.json({ quote: "Plain words beat clever ones." }));
app.listen(8080);
The same on Cloudflare Workers
import { createX402Xrpl } from "@openwallet/x402-xrpl";
export default {
async fetch(request, env) {
const x402 = createX402Xrpl({
network: "xrpl:1",
payTo: env.PAY_TO,
rpc: "https://s.altnet.rippletest.net:51234",
store: env.STORE, // a store with an atomic claim
});
const r = await x402.handle(request, {
price: { asset: "RLUSD", value: "0.01" },
description: "One quote",
});
if (!r.paid) return r.response; // the 402 challenge, or a failure
return r.finish(Response.json({ quote: "Plain words beat clever ones." }));
},
};
A paid MCP tool
import { McpServer } from "@modelcontextprotocol/server";
import { createX402Xrpl, memoryStore } from "@openwallet/x402-xrpl";
const server = new McpServer({ name: "summaries", version: "1.0.0" });
const x402 = createX402Xrpl({
network: "xrpl:1",
payTo: "rYourTestnetAddress…",
rpc: "https://s.altnet.rippletest.net:51234",
store: memoryStore(), // one process only; use sqlite or redis in production
});
x402.mcpPaidTool(server, "summarise", {
price: { asset: "XRP", drops: "20000" },
description: "Summarise a text in three sentences",
inputSchema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] },
}, async ({ text }) => ({ content: [{ type: "text", text: summarise(text) }] }));
An agent paying for both
With an AI app connected to OpenWallet, the model makes these calls. It never gives a destination or signs anything itself. On the remote server, the user approves each payment in the extension; with the desktop agent, small payments to approved merchants go through without a prompt.
// The HTTP API
// tools/call openwallet_pay_x402
{ "url": "https://api.example.com/v1/quote",
"reason": "The user asked for a quote",
"task": "Get me a quote from api.example.com" }
// The remote paid MCP tool
// tools/call openwallet_call_paid_mcp_tool
{ "server_url": "https://mcp.example.com/mcp",
"tool": "summarise",
"arguments": { "text": "…" },
"max_amount": { "asset": "XRP", "amount": "20000" },
"reason": "The user asked for a summary" }
Each result has status, the resource or tool result in untrusted_ fields, and a receipt with the transaction hash and an explorer link.