Skills nevermined-payments
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/aaitor/nevermined-payments" ~/.claude/skills/openclaw-skills-nevermined-payments && rm -rf "$T"
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/aaitor/nevermined-payments" ~/.openclaw/skills/openclaw-skills-nevermined-payments && rm -rf "$T"
skills/aaitor/nevermined-payments/SKILL.mdNevermined Payments Integration
Overview
Nevermined provides financial rails for AI agents — real-time monetization, access control, and payments. This skill gives you everything needed to:
- Protect API endpoints with the x402 payment protocol
- Charge per-request using credit-based billing
- Integrate with Express.js, FastAPI, Strands agents, MCP servers, or Google A2A agents
- Support subscriber-side flows (purchase plans, generate tokens, call protected APIs)
- Enable agent-to-agent payments via the Google A2A protocol
The x402 protocol uses HTTP 402 responses to advertise payment requirements. Clients acquire an access token and retry the request. The server verifies permissions, executes the workload, then settles (burns credits).
Quick Start Checklist
- Get an API key at nevermined.app → Settings → API Keys
- Install the SDK (
ornpm install @nevermined-io/payments
)pip install payments-py - Register your agent and plan (via the App UI or programmatically — see
)references/payment-plans.md - Add payment protection to your routes/tools (see framework-specific references below)
- Test — call without token (expect 402), then with token (expect 200)
Environment Setup
| Variable | Required | Description |
|---|---|---|
| Yes | Your Nevermined API key (get it at nevermined.app → Settings → API Keys) |
| Yes | for testing, for production |
| Yes | The plan ID from registration |
| Sometimes | Required for MCP servers and plans with multiple agents |
| For registration | Wallet address to receive payments |
.env
Template
.env# Required NVM_API_KEY=your-api-key-here NVM_ENVIRONMENT=sandbox NVM_PLAN_ID=your-plan-id-here # Required for MCP servers or multi-agent plans NVM_AGENT_ID=your-agent-id-here # Required for registration BUILDER_ADDRESS=0xYourWalletAddress
Prerequisites
- TypeScript/Express.js: Node.js 18+. Your
must includepackage.json
for the"type": "module"
subpath import to work.@nevermined-io/payments/express - Python/FastAPI: Python 3.9+. Install with
— thepip install payments-py[fastapi]
extra is required for the middleware.[fastapi]
TypeScript
npm install @nevermined-io/payments
import { Payments } from '@nevermined-io/payments' const payments = Payments.getInstance({ nvmApiKey: process.env.NVM_API_KEY!, environment: 'sandbox' })
Python
pip install payments-py
import os from payments_py import Payments, PaymentOptions payments = Payments.get_instance( PaymentOptions( nvm_api_key=os.environ["NVM_API_KEY"], environment="sandbox" ) )
Core Workflow (All Integrations)
Every Nevermined payment integration follows this 5-step pattern:
- Client sends request without a payment token
- Server returns 402 with
header (base64-encoded JSON with plan info)payment-required - Client acquires x402 token via
payments.x402.getX402AccessToken(planId, agentId) - Client retries with
header containing the tokenpayment-signature - Server verifies → executes → settles (burns credits), returns response with
headerpayment-response
Framework Decision Tree
Choose the integration that matches your stack:
| Framework | Language | Reference | Key Import |
|---|---|---|---|
| Express.js | TypeScript/JS | | from |
| FastAPI | Python | | from |
| Strands Agent | Python | | from |
| MCP Server | TypeScript | | / |
| Google A2A | TS / Python | | / |
| Any HTTP | Any | | Manual verify/settle via facilitator API |
| Client-side | TS / Python | | |
SDK Quick Reference
TypeScript (@nevermined-io/payments
)
@nevermined-io/payments// Initialize const payments = Payments.getInstance({ nvmApiKey, environment }) // Register agent + plan const { agentId, planId } = await payments.agents.registerAgentAndPlan( agentMetadata, agentApi, planMetadata, priceConfig, creditsConfig ) // Subscriber: order plan and get token await payments.plans.orderPlan(planId) const balance = await payments.plans.getPlanBalance(planId) const { accessToken } = await payments.x402.getX402AccessToken(planId, agentId) // Server: verify and settle const verification = await payments.facilitator.verifyPermissions({ paymentRequired, x402AccessToken: token, maxAmount: BigInt(credits) }) const settlement = await payments.facilitator.settlePermissions({ paymentRequired, x402AccessToken: token, maxAmount: BigInt(creditsUsed) }) // Helpers import { buildPaymentRequired } from '@nevermined-io/payments' import { paymentMiddleware, X402_HEADERS } from '@nevermined-io/payments/express' // MCP server payments.mcp.registerTool(name, config, handler, { credits: 5n }) const { info, stop } = await payments.mcp.start({ port, agentId, serverName }) // A2A server const agentCard = payments.a2a.buildPaymentAgentCard(baseCard, { paymentType, credits, planId, agentId }) const server = await payments.a2a.start({ port, basePath: '/a2a/', agentCard, executor }) // A2A client const client = payments.a2a.getClient({ agentBaseUrl, agentId, planId }) await client.sendMessage("Hello", accessToken)
Python (payments-py
)
payments-py# Initialize payments = Payments.get_instance(PaymentOptions(nvm_api_key=key, environment="sandbox")) # Register agent + plan result = payments.agents.register_agent_and_plan( agent_metadata, agent_api, plan_metadata, price_config, credits_config ) # Subscriber: order plan and get token payments.plans.order_plan(plan_id) balance = payments.plans.get_plan_balance(plan_id) token_res = payments.x402.get_x402_access_token(plan_id, agent_id) # Server: verify and settle verification = payments.facilitator.verify_permissions( payment_required=pr, x402_access_token=token, max_amount=str(credits) ) settlement = payments.facilitator.settle_permissions( payment_required=pr, x402_access_token=token, max_amount=str(credits_used) ) # Helpers from payments_py.x402.helpers import build_payment_required from payments_py.x402.fastapi import PaymentMiddleware from payments_py.x402.strands import requires_payment # A2A server from payments_py.a2a.agent_card import build_payment_agent_card from payments_py.a2a.server import PaymentsA2AServer agent_card = build_payment_agent_card(base_card, { ... }) server = PaymentsA2AServer.start(agent_card=agent_card, executor=executor, payments_service=payments, port=3005) # A2A client client = payments.a2a.get_client(agent_base_url=url, agent_id=agent_id, plan_id=plan_id)
x402 Payment Headers
All x402 v2 integrations use these three HTTP headers:
| Header | Direction | Description |
|---|---|---|
| Client → Server | x402 access token |
| Server → Client (402) | Base64-encoded JSON with plan requirements |
| Server → Client (200) | Base64-encoded JSON settlement receipt |
The
payment-required payload structure:
{ "x402Version": 2, "accepts": [{ "scheme": "nvm:erc4337", "network": "eip155:84532", "planId": "<plan-id>", "extra": { "agentId": "<agent-id>" } }] }
Payment Plan Types
Nevermined supports several plan types:
- Credits-based: prepaid balance, deducted per request (most common for APIs)
- Time-based: access for a fixed duration (e.g., 30 days unlimited)
- Pay-as-you-go (PAYG): settle in USDC per request, no credit balance
- Trial: free limited access, one-time claim per user
- Hybrid: combine credits with time expiry
See
references/payment-plans.md for plan registration code.
Common Patterns
Express.js — Fixed credits per route
import { paymentMiddleware } from '@nevermined-io/payments/express' app.use(paymentMiddleware(payments, { 'POST /ask': { planId: PLAN_ID, credits: 1 }, 'POST /generate': { planId: PLAN_ID, credits: 5 } }))
FastAPI — Fixed credits per route
from payments_py.x402.fastapi import PaymentMiddleware app.add_middleware( PaymentMiddleware, payments=payments, routes={ "POST /ask": {"plan_id": PLAN_ID, "credits": 1}, "POST /generate": {"plan_id": PLAN_ID, "credits": 5} } )
Express.js — Dynamic credits based on response
paymentMiddleware(payments, { 'POST /generate': { planId: PLAN_ID, credits: (req, res) => { const tokens = res.locals.tokenCount || 100 return Math.ceil(tokens / 100) } } })
FastAPI — Dynamic credits based on request
async def calculate_credits(request: Request) -> int: body = await request.json() max_tokens = body.get("max_tokens", 100) return max(1, max_tokens // 100) app.add_middleware( PaymentMiddleware, payments=payments, routes={"POST /generate": {"plan_id": PLAN_ID, "credits": calculate_credits}} )
MCP Server — Register tool with paywall
payments.mcp.registerTool( "weather.today", { title: "Today's Weather", inputSchema: z.object({ city: z.string() }) }, async (args, extra, context) => ({ content: [{ type: "text", text: `Weather in ${args.city}: Sunny, 25C` }] }), { credits: 5n } ) const { info, stop } = await payments.mcp.start({ port: 3000, agentId: process.env.NVM_AGENT_ID!, serverName: "my-server" })
Strands Agent — Decorator-based payment
from strands import Agent, tool from payments_py.x402.strands import requires_payment @tool(context=True) @requires_payment(payments=payments, plan_id=PLAN_ID, credits=1) def analyze_data(query: str, tool_context=None) -> dict: return {"status": "success", "content": [{"text": f"Analysis: {query}"}]} agent = Agent(tools=[analyze_data])
Google A2A — Agent server with payment extension
TypeScript
const agentCard = payments.a2a.buildPaymentAgentCard(baseAgentCard, { paymentType: "dynamic", credits: 1, planId: process.env.NVM_PLAN_ID!, agentId: process.env.NVM_AGENT_ID!, }) const server = await payments.a2a.start({ port: 3005, basePath: '/a2a/', agentCard, executor: new MyExecutor(), })
Python
from payments_py.a2a.agent_card import build_payment_agent_card from payments_py.a2a.server import PaymentsA2AServer agent_card = build_payment_agent_card(base_agent_card, { "paymentType": "dynamic", "credits": 1, "planId": os.environ["NVM_PLAN_ID"], "agentId": os.environ["NVM_AGENT_ID"], }) server = PaymentsA2AServer.start( agent_card=agent_card, executor=MyExecutor(), payments_service=payments, port=3005, base_path="/a2a/", )
Google A2A — Client sending a paid task
const client = payments.a2a.getClient({ agentBaseUrl: 'http://localhost:3005/a2a/', agentId: AGENT_ID, planId: PLAN_ID, }) const { accessToken } = await payments.x402.getX402AccessToken(PLAN_ID, AGENT_ID) const response = await client.sendMessage("Analyze this data", accessToken)
Gathering Developer Information Upfront
When a developer asks you to integrate Nevermined payments, gather ALL required information in a single question before generating code. This avoids multiple back-and-forth interactions.
Ask the developer once for:
- Framework: Express.js, FastAPI, MCP server, Strands agent, Google A2A, or generic HTTP?
- Routes to protect: Which endpoints need payment protection and how many credits each? (e.g.,
)POST /chat = 1 credit, POST /generate = 5 credits - Pricing model: Fixed credits per request, or dynamic pricing based on request/response parameters?
- Nevermined API Key: Do they already have an
? If not, direct them to nevermined.app → Settings → API KeysNVM_API_KEY - Plan ID: Do they already have a
? If not, do they need a registration script too?NVM_PLAN_ID - Environment:
(testing) orsandbox
(production)?live
If they need plan registration, also ask:
- Plan name and description: e.g., "Starter Plan — 100 API requests"
- Pricing: How much in USDC? (e.g., 10 USDC for 100 credits)
- Credits per plan: Total credits included (e.g., 100)
- Builder wallet address (
): The wallet that receives paymentsBUILDER_ADDRESS
Example combined prompt to offer the developer:
I need to set up Nevermined payments. Here's my info:
- Framework: Express.js
- Routes: POST /chat (1 credit), POST /summarize (3 credits)
- I need a registration script too
- Plan: "Starter Plan", 100 credits for 10 USDC
- Environment: sandbox
- My API key is in the NVM_API_KEY env var
- My wallet: 0x1234...
With this information, generate both the registration script and the payment-protected server in a single response.
Agent and Plan Registration
Using the SDK (Recommended)
Register your agent and plan programmatically — see
references/payment-plans.md for complete code.
// TypeScript const { agentId, planId } = await payments.agents.registerAgentAndPlan( { name: 'My Agent', description: 'AI service', tags: ['ai'], dateCreated: new Date() }, { endpoints: [{ POST: 'https://your-api.com/query' }] }, { name: 'Starter Plan', description: '100 requests for $10', dateCreated: new Date() }, payments.plans.getERC20PriceConfig(10_000_000n, USDC_ADDRESS, process.env.BUILDER_ADDRESS!), payments.plans.getFixedCreditsConfig(100n, 1n) )
# Python result = payments.agents.register_agent_and_plan( agent_metadata={'name': 'My Agent', 'description': 'AI service', 'tags': ['ai']}, agent_api={'endpoints': [{'POST': 'https://your-api.com/query'}]}, plan_metadata={'name': 'Starter Plan', 'description': '100 requests for $10'}, price_config=get_erc20_price_config(10_000_000, USDC_ADDRESS, os.environ['BUILDER_ADDRESS']), credits_config=get_fixed_credits_config(100, 1) )
Using the Nevermined App (No-Code)
- Go to nevermined.app and sign in
- Click "My agents" → register a new agent with metadata and endpoints
- Create a payment plan: set pricing, credits, and duration
- Link the plan to your agent and publish
- Copy the
andagentId
for yourplanId
file.env
Using the CLI
# 1. Install CLI npm install -g @nevermined-io/cli # 2. Configure (use sandbox for testing) nvm config init --api-key "$NVM_API_KEY" --environment sandbox # 3. Register agent and plan together nvm agents register-agent-and-plan \ --agent-metadata '{"name":"My Agent","description":"AI service"}' \ --agent-api '{"endpoints":[{"POST":"https://your-api.com/query"}]}' \ --plan-metadata '{"name":"Starter Plan","description":"100 requests"}' \ --price-config '{"tokenAddress":"0x036CbD53842c5426634e7929541eC2318f3dCF7e","price":10000000,"amountOfCredits":100}' \ --credits-config '{"minCreditsRequired":1,"minCreditsToCharge":1,"maxCreditsToCharge":10}' # 4. List your plans nvm plans get-plans # 5. As a subscriber: order a plan and get an x402 token nvm plans order-plan $PLAN_ID nvm x402token get-x402-access-token $PLAN_ID --agent-id $AGENT_ID # 6. Test against your running server curl -X POST http://localhost:3000/chat \ -H "Content-Type: application/json" \ -H "payment-signature: $TOKEN" \ -d '{"message": "Hello"}'
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| HTTP 402 returned | No header or invalid/expired token | Generate a fresh token via |
MCP error | Payment Required — no token, invalid token, or insufficient credits | Check subscriber has purchased plan and has credits remaining |
MCP error | Server misconfiguration | Verify , , and are set correctly |
is false | Token expired, wrong plan, or insufficient credits | Re-order the plan or generate a new token |
| Credits not deducting | Settlement not called after request | Ensure you call after processing (middleware does this automatically) |
header missing | Server not returning 402 properly | Use helper or framework middleware |
Additional Resources
- Documentation: nevermined.ai/docs
- Nevermined App: nevermined.app — register agents, create plans, manage subscriptions
- MCP Search Server:
— search Nevermined docs from any MCP clienthttps://docs.nevermined.app/mcp - Tutorials: github.com/nevermined-io/tutorials
- Discord: discord.com/invite/GZju2qScKq
- TypeScript SDK:
on npm@nevermined-io/payments - Python SDK:
on PyPIpayments-py