PerformanceBlog
Tempo MCP serverGive agents search and read tools for Tempo docs
Skip to content
LogoLogo

Accept pay-as-you-go payments

Build a payment-gated photo gallery API that charges $0.01 per photo using mppx sessions. The server returns random photos from Picsum behind a paywall.

How pay-as-you-go sessions work

  1. Open — Client deposits funds into an on-chain reserve contract, creating a payment channel
  2. Session — Client signs EIP-712 vouchers with increasing cumulative amounts as service is consumed
  3. Top up — If the channel runs low, the client deposits additional tokens without closing the channel
  4. Close — Either party closes the channel, settling the final balance on-chain and refunding unused deposit

Pay-as-you-go server setup

Install pay-as-you-go dependencies

Set up an Mppx session instance

Set up an Mppx instance with the tempo method.

  • recipient is the address where you receive payments.
  • currency is the token address for payments (in this case, pathUSD).
import { Mppx, tempo } from 'mppx/server'
 
const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

Add a pay-as-you-go route

Add payment verification using mppx.session as route middleware. The handler only runs after payment is verified.

import { Mppx, tempo } from 'mppx/nextjs'
 
const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})
 
export const GET =
  mppx.session({ amount: '0.01', unitType: 'photo' })
  (async () => {
    const res = await fetch('https://picsum.photos/200/200')
    return Response.json({ url: res.url })
  })

Test the pay-as-you-go endpoint

# Create account funded with testnet tokens
$ npx mppx account create
 
# Make a paid request
$ npx mppx http://localhost:3000/api/sessions/photo

Pay-as-you-go client setup

When using sessions from a client, set maxDeposit to enable automatic channel management. This is the maximum amount of tokens the client locks into the payment channel's reserve contract. Any unspent deposit is refunded when the channel closes.

import { Mppx, tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'
 
const mppx = Mppx.create({
  methods: [tempo({
    account: privateKeyToAccount('0x...'),
    maxDeposit: '1', // Lock up to 1 pathUSD per channel
  })],
})
 
// Each fetch automatically manages the session lifecycle:
// 1st request: opens channel on-chain, sends initial voucher
// 2nd+ requests: sends off-chain vouchers (no on-chain tx)
const res = await fetch('http://localhost:3000/api/sessions/photo')
  • maxDeposit: '1' — Locks up to 1 pathUSD into the payment channel. At $0.01/photo, this covers up to 100 requests before the channel runs out.
  • The client handles the full session lifecycle automatically: channel open, voucher signing, and retry after 402 responses.
  • If the server sets suggestedDeposit, the client uses min(suggestedDeposit, maxDeposit).

Next steps for pay-as-you-go payments