Streaming sessions
MPP sessions — open one channel, stream many metered deliveries authorized by cumulative off-chain vouchers, and settle once when the session idle-closes.
An MPP session opens one payment channel and meters many deliveries against it. Each delivery is authorized by an off-chain voucher carrying a running cumulative total; nothing touches the chain per delivery. When the session goes idle the operator settles the final amount on-chain and refunds the rest.
When to use it
Reach for a session when you're metering a stream rather than a single call:
- a token-by-token SSE response (the canonical case),
- a burst of many cheap calls a client makes in one sitting,
- anything where you want one channel reused across deliveries — and optionally split the proceeds across multiple recipients.
For a single call whose cost you only learn afterward, usage charges (upto) are simpler — one authorization, one settlement.
How it flows
The buyer opens the channel with a deposit (the cap). For each delivery they sign a cumulative voucher — if the first authorizes $0.0001 and the next $0.0002, the operator may claim up to $0.0002 total, not the sum. The gateway verifies each voucher and serves off-chain. After the configured idle delay (close_delay_ms), the operator settles the final voucher and distributes — refunding the unused deposit. A buyer can topUp to extend a channel, and can always force-close (after a grace period) to recover funds if the server goes away.
With the pay CLI
A session needs two things in the spec: a top-level session: block configuring the channel, and one or more endpoints whose metering accepts mpp-session. The channel cap and idle-close delay live on the block; the per-delivery price is the endpoint's metering dimension.
# Channel-wide config: deposit ceiling + idle-close delay.
session:
cap_usdc: 1.0
close_delay_ms: 2000 # settle + close after 2s of no deliveries
modes: [pull] # or [push]
pull_voucher_strategy: client_voucher
# Optional: split the settled total across recipients (percentage-only).
splits:
- recipient: platform
percent: 30
endpoints:
- method: GET
path: 'api/v1/stream'
description: 'Metered token stream over an MPP session channel.'
metering:
schemes: [mpp-session]
dimensions:
- direction: usage
unit: requests
scale: 1
tiers:
- price_usd: 0.0001 # per-delivery pricepay --sandbox server start provider.ymlOn-chain settle-at-close needs an operator signer + RPC. With the CLI the gateway owns the metering side channel and
the settlement transaction for you; on --sandbox the operator is provisioned, and in production you set
operator.signer + operator.fee_payer: true. Without a signer the close is a state-flip and no on-chain settlement
signature is produced.
On the wire
Sessions ride MPP's 402 handshake:
WWW-Authenticate: Payment(402) — the session challenge: per-unitamount,channelProgram,feePayer,minVoucherDelta,gracePeriodSeconds, and optionaldistributionSplits.Authorization: Payment(retry) — a discriminated credential withaction: "open" | "voucher" | "topUp" | "close". Avouchercarries the 48-byte on-chain structure[channelId | cumulativeAmount | expiresAt]plus the buyer's Ed25519 signature.Payment-Receipt—acceptedCumulative(highest voucher accepted),spent, and on closerefunded+ the settlementtxHash.
Full details: the MPP Solana session method spec.
Next
- Usage charges (x402
upto) — a single metered call instead of a stream. - upto vs sessions — when to pick which.
- YAML specification — the
recipientsand split fields a session settlement routes to.
Usage charges (upto)
x402 upto — authorize a ceiling for one metered call, then settle the actual amount and refund the rest. For costs you only know after the work runs.
upto vs sessions
Both are payment channels — pick upto for one metered call, sessions for a stream of many deliveries. The full comparison and when to use which.