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 script 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. No 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 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: process.env.NVM_API_KEY!,
  environment: 'sandbox',
})

const PLAN_ID = process.env.NVM_PLAN_ID!
const AGENT_ID = process.env.NVM_AGENT_ID!

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

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

if (!x402Token) {
  // Return 402 with payment-required header so clients know how to pay
  const paymentRequiredBase64 = Buffer.from(
    JSON.stringify(paymentRequired)
  ).toString('base64')

  return res
    .status(402)
    .setHeader('payment-required', paymentRequiredBase64)
    .json({ error: 'Payment Required' })
}

// 1. Verify permissions (does NOT burn credits)
const verification = await payments.facilitator.verifyPermissions({
  paymentRequired,
  x402AccessToken: x402Token,
  maxAmount: 1n,
})

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

// 2. Execute your logic here — payment is verified
const result = await handleRequest(req)

// 3. Settle (burn credits) after successful processing
await payments.facilitator.settlePermissions({
  paymentRequired,
  x402AccessToken: x402Token,
  maxAmount: 1n,
})

return res.json({ result })

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: ${accessToken}" \
  -d '{"prompt": "Hello"}'
Response:
{
  "result": "Hello! How can I help you today?",
  "creditsRemaining": 99
}

What’s Next?