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

Accept pay-as-you-go payments

Use pay-as-you-go sessions when a customer should pay a small amount each time they use an API or service, without sending an on-chain transaction for every request.

This guide uses a simple photo API as the example: the client opens one mppx session, then pays $0.01 each time it asks for a photo. mppx is the library that manages the MPP session; Picsum only supplies sample images for the demo.

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

The channel-reserve gas snapshot for the credited reopen path is:

Channel reserve snapshotT7 gas
open_new_channel_with_storage_credit60,225

This is a call-level gas number and excludes separate approval gas. It matters most for session services where the same payer opens, closes or withdraws, and later opens channels again.

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