The smallest possible paid HTTP agent: add a paywall to one route.
- Protect an Express endpoint with paymentMiddleware from @nevermined-io/payments/express
- Return 402 with the payment-required envelope, verify the payment-signature, settle on success
- Generate an x402 access token on the client with the SDK and retry the call
- Optionally track OpenAI cost per call with Nevermined observability
The client calls /ask with no token and gets 402 Payment Required, carrying the payment-required header. It mints an x402 token with the SDK, retries with the payment-signature header, and the agent verifies, runs, and settles (burns credits) before returning 200 with a payment-response receipt.
Create a delegation once, mint an x402 token, and call the paid route.
// one delegation backs the buyer (erc4337)
const { delegationId } = await payments.delegation.createDelegation({
provider: 'erc4337', spendingLimitCents: 10000, durationSecs: 604800, currency: 'usdc',
})
// mint an x402 access token for the plan, then call the route with it
const { accessToken } = await payments.x402.getX402AccessToken(
PLAN_ID, undefined, { delegationConfig: { delegationId } },
)
const res = await fetch(AGENT_URL + '/weather/credits', {
method: 'POST',
headers: { 'content-type': 'application/json', [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
body: JSON.stringify({ city: 'Lisbon' }),
})
// → 200 + weather, plus a 'payment-response' settlement receiptOne paymentMiddleware, three plans, both protocols — mpp: true makes every 402 advertise x402 AND MPP, so either buyer works against the same URL.
import { paymentMiddleware } from '@nevermined-io/payments/express'
app.use(paymentMiddleware(payments, {
'POST /weather/credits': { planId: PLAN_ID_CREDITS, credits: 1, mpp: true },
'POST /weather/subscription': { planId: PLAN_ID_TIME, credits: 1, mpp: true },
'POST /weather/payg': { planId: PLAN_ID_PAYG, credits: (req) => priceForRequest(req.body), mpp: true },
}))
app.post('/weather/credits', async (req, res) => {
const { city } = parseWeatherRequest(req.body) // 400 on bad input
res.json(await getTodayWeather(city)) // keyless Open-Meteo
})| src/agent.ts | Express agent — three dual-protocol (x402 + MPP) weather routes |
| src/services/weather.service.ts | keyless weather from Open-Meteo |
| scripts/smoke.ts | buyer: x402 + MPP round-trips against the agent |
| scripts/register-plans.ts | registers the credits / time / pay-as-you-go plans |
Sandbox agent — real payment round-trips (402 → authorize → settle) with a per-session credit balance, no external service and no real money. The buyer mints an x402 access token via the SDK and sends it as `payment-signature`; the sandbox runs that round-trip locally. See the README to point this at a hosted instance of the agent.