Skip to main content
This guide gets you from zero to a working payment integration in 5 minutes. By the end, you’ll have a monetizable service set up with Nevermined — typically an agent API, but the same flow applies to MCP tools/servers and protected assets.
In the code below we use “agent” terminology because it maps to the underlying object model, but you can think of it as the service/resource you’re charging for.

Prerequisites

1

Get Your API Key

  1. Go to nevermined.app and sign in
  2. Navigate to Settings > API Keys
  3. Generate a new key and copy it
export NVM_API_KEY="nvm:your-api-key-here"
2

Install the SDK

npm install @nevermined-io/payments

Register Your Agent

Create a scrupt to register your agent and a payment plan.
You can register your agent and any payment plan using the following code OR using the Nevermined App. So not need to code this, just follow the steps in the app to create your agents and plans.
If you’re monetizing an agent, MCP tool/server or a protected resource, you’ll still register the monetizable unit and attach a plan — only the delivery step changes.
import { Payments } from '@nevermined-io/payments'

// In this example we require a payment a payment of 10 USDC for 100 requests
// For that USDC payment we use USDC on Base Sepolia, so we need its contract address:
const USDC_ADDRESS = '0x036CbD53842c5426634e7929541eC2318f3dCF7e'

async function main() {
  // 1. Initialize the SDK
  const payments = Payments.getInstance({
    nvmApiKey: process.env.NVM_API_KEY!,
    environment: 'sandbox'
  })

  // 2. Register service + payment plan ("agent" in the SDK)
  const { agentId, planId } = await payments.agents.registerAgentAndPlan(
    // Service metadata
    {
      name: 'My AI Assistant',
      description: 'A paid service (agent API / MCP tool / protected resource)',
      tags: ['ai', 'payments'],
      dateCreated: new Date()
    },
    // Service interface - replace with your endpoint
    {
      endpoints: [{ POST: 'https://your-api.com/query' }]
    },
    // Plan metadata
    {
      name: 'Starter Plan',
      description: '100 requests for $10',
      dateCreated: new Date()
    },
    // Price: 10 USDC
    payments.plans.getERC20PriceConfig(
      10_000_000n, // 10 USDC (6 decimals)
      USDC_ADDRESS,
      process.env.BUILDER_ADDRESS! // Your wallet address
    ),
    // Credits: 100 requests, 1 credit each
    payments.plans.getFixedCreditsConfig(100n, 1n)
  )

  console.log('Registered!')
  console.log(`Service (agent) ID: ${agentId}`)
  console.log(`Plan ID: ${planId}`)
  console.log('\nSave these IDs for your integration.')
}

main().catch(console.error)
Run it:
npx ts-node register-agent.ts

Add Payment Validation in the Agent

Add this middleware to your agent to validate if a request is valid (have a payment attached) before delivering your response/resource. The example shows an HTTP API route; the same check can be used before calling an MCP tool handler or before serving a protected asset:
import { Payments, buildPaymentRequired } from '@nevermined-io/payments'

const payments = Payments.getInstance({
  nvmApiKey: 'nvm:agent-key',
  environment: 'sandbox',
})

// Get token from payment-signature header
const x402Token = req.headers['payment-signature']

if (!x402Token) {
  // Return 402 with payment requirements
  return res.status(402).json({ error: 'Payment Required' })
}

// Build payment required specification
const paymentRequired = buildPaymentRequired(planId, {
  endpoint: req.url,
  agentId: agentId,
  httpVerb: req.method,
})

// Verify permissions - facilitator extracts planId and subscriberAddress from token
const verification = await payments.facilitator.verifyPermissions({
  paymentRequired,
  x402AccessToken: x402Token,
  maxAmount: 1n,
})

if (!verification.isValid) {
  return res.status(402).json({ error: 'Payment verification failed' })
}

//////////
// Here you can execute your logic knowing payment is valid
//////////

Integrate the validation code in your agent/server

Integrate the above validation code into your agent/server code at the very beginning of your request handling logic. The payment validation should occur before any processing of the request and can be complemented by any other authorization logic you may have.

Test It

1) Try without payment (should fail)
curl -X POST http://localhost:3000/query \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Hello"}'
Response:
{
  "error": "Payment Required",
  "message": "Purchase a plan to access this API",
  "plans": [{"planId": "did:nv:...", "agentId": "did:nv:..."}]
}
2) Purchase a plan and get an access token
// As a subscriber
const payments = Payments.getInstance({ nvmApiKey: subscriberKey, environment: 'sandbox' })

// Order the plan
await payments.plans.orderPlan(PLAN_ID)

// Get your balance about the plan you just ordered
const balance = await payments.plans.getPlanBalance(PLAN_ID)

// Generate the x402 access token
const { accessToken } = await payments.x402.getX402AccessToken(PLAN_ID, AGENT_ID)

// Use this token in the next request
// HTTP header: 'PAYMENT-SIGNATURE'
// value: `${accessToken}`
3) Query with payment
curl -X POST http://localhost:3000/query \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: ${agentAccessParams.accessToken}" \
  -d '{"prompt": "Hello"}'
Response:
{
  "result": "Hello! How can I help you today?",
  "creditsRemaining": 99
}

What’s Next?