DEV Community

Cover image for x402 upto vs MPP Sessions: Two Philosophies of Usage-Based Payments
Ihor
Ihor

Posted on

x402 upto vs MPP Sessions: Two Philosophies of Usage-Based Payments

A deep comparison of x402 upto and MPP Sessions: how they handle variable-cost payments, micropayment streaming, escrow vs allowance models, and when to choose each architecture for machine-to-machine payments.

TL;DR

x402 upto and MPP Sessions (I use Tempo Session here as example) solve the same practical problem: how to charge a client exactly for what they actually consumed when the final cost is unknown in advance, while also reducing the number of transactions. But they solve it at different abstraction layers and with fundamentally different settlement architectures.

  • x402 upto is an “open check” with a maximum amount. The client signs a one-time authorization to charge up to X. The server delivers the service, calculates the actual cost, and performs one on-chain transaction for the real amount. This model lives entirely inside a single HTTP request-response cycle, uses Permit2, and requires no escrow.

  • MPP Tempo Sessions is a payment channel (state channel). The client deposits funds into an on-chain escrow contract, then exchanges off-chain EIP-712 “vouchers” with the server, each representing a cumulative amount. The channel stays alive for a long time, can contain unlimited micropayments, and requires exactly two on-chain transactions for all of them: opening and closing.

Simplified:

x402 upto = one HTTP request with an unknown final price.

MPP Sessions = a long-lived streaming connection where payments flow in sync with data.


Session Lifecycle

x402 upto

The upto scheme exists within a normal HTTP request-response cycle extended with HTTP 402 status.

Lifecycle:

  1. Challenge. The client makes a request, and the server responds with 402 Payment Required containing PaymentRequirements, specifying scheme: "upto", recipient address, token, network, maximum timeout, and most importantly amount — the upper limit the server wants authorization for.
  2. Signature. The client creates a Permit2 permitWitnessTransferFrom message where permitted.amount equals the maximum requested amount, witness.to is the recipient address, witness.facilitator is the facilitator address (published by the server via /supported), and sets deadline and validAfter. Then signs it with EIP-712.
  3. Paid request. The client repeats the HTTP request, attaching PAYMENT-SIGNATURE with the payload (signature + Permit2 authorization parameters).
  4. Verification. The facilitator verifies the signature, Permit2 allowance, client balance, signature validity window, and token/network consistency. No funds move at this stage.
  5. Service execution. The server processes the request (generates tokens, returns a file, runs computation) and calculates the actual final cost.
  6. Settlement. The server sends PaymentRequirements to the facilitator again, now with the actual amount (this is the key feature of the scheme: the same field means different things in different phases — maximum during verification, actual charge during settlement). The facilitator calls x402UptoPermit2Proxy.settle(...) using the real amount, which must be the signed maximum. If the actual amount is zero, no on-chain transaction happens at all — the authorization simply expires unused.

One signature = one settlement.

upto explicitly forbids multi-settlement and streaming: the same signature cannot be reused because of Permit2 nonce semantics. If another charge is needed, a new signature is required — meaning a new HTTP request.

MPP Tempo Sessions

A Tempo session is a full protocol with a dedicated on-chain TempoStreamChannel contract and multiple states.

Lifecycle:

  1. Challenge. The server returns 402 with WWW-Authenticate: Payment method="tempo" intent="session". It includes price per unit of consumption (amount + unitType, e.g. 25 base units per llm_token), recommended deposit (suggestedDeposit), escrow contract address, and optionally channelId if the server proposes reusing an existing channel.
  2. Open. The client sends an on-chain transaction open(payee, token, deposit, salt, authorizedSigner). The contract creates a channel with deterministic channelId = keccak256(payer, payee, token, salt, authorizedSigner, contract, chainId) and locks the deposit. The client sends the signed transaction to the server together with action="open" and an initial voucher with cumulativeAmount = 0.
  3. Streaming + vouchers. The server begins streaming content (typically SSE or chunked). As consumption grows, the client signs EIP-712 vouchers with monotonically increasing cumulative amounts: 100 → 250 → 400 → .... Vouchers are sent over the same HTTP URI (often via HEAD requests), with no separate control plane. Each voucher is only a few hundred bytes and verifies in microseconds.
  4. Top-up (optional). If the session lasts longer than expected and deposit runs low, the client can call on-chain topUp() and continue without closing the channel. Tempo even defines an SSE event payment-need-voucher to notify the client that balance is exhausted.
  5. Settle (optional, many times). The server may call settle(channelId, cumulativeAmount, signature) at any time to withdraw already earned funds without closing the channel. This is a major difference from upto: partial on-chain settlements during a live session are allowed.
  6. Cooperative close. The client sends action="close" with the final voucher. The server calls close(), and the contract transfers the delta (cumulativeAmount - already_settled) to the payee, refunds the remainder to the payer, and finalizes the channel.
  7. Forced close (client protection). If the server becomes silent and does not close the channel, the client calls requestClose(), waits through a grace period (15 minutes in the reference implementation), then calls withdraw() to reclaim remaining funds. The server has a window to submit the final voucher.

Key detail: vouchers are cumulative. This means the client does not need to track history — it simply signs “total owed so far is X.” Once the server receives a newer voucher, all previous ones can be discarded. During settlement, the contract computes delta as cumulativeAmount - channel.settled, naturally preventing replay and double-spending.


Table of Key Differences

Parameter x402 upto MPP Tempo Sessions
Settlement model Allowance (Permit2) — funds stay with client until settlement Escrow — funds locked in contract
Protocol unit Single HTTP request Long-lived channel across many requests
On-chain tx per session 0 or 1 (final transfer only) Minimum 2 (open + close), plus optional settle()
Payment granularity One final amount per request Unlimited vouchers (per-token, per-byte, per-ms)
Payment confirmation speed ~On-chain confirmation Microseconds (voucher signature verification)
Client signature type EIP-712 Permit2 Witness Transfer EIP-712 Voucher (channelId + cumulativeAmount)
Time limits Strict: validAfter + deadline No expiry — channel lives until explicitly closed
Authorization reuse Forbidden (single-use nonce) Built-in: each new voucher replaces previous
Partial settlements during session Not supported Yes, via settle()
Client protection if server silent Signature expires after deadline requestClose + grace period + withdraw
Server protection Signature + allowance/balance check; client may empty wallet before settlement Funds already in escrow
Server state requirements Minimal, nearly stateless Requires persistent accounting
Ideal use case REST endpoint with variable pricing Streaming, agents, high-frequency APIs

Architectural Differences That Actually Matter

Escrow vs Allowance Is Not Style — It Is Risk Allocation

In x402 upto, funds physically remain in the client wallet until settlement. The server relies on:

  • valid signature,
  • sufficient balance at settlement time,
  • Permit2 allowance not revoked.

Between verification and settlement there is a window where the client can technically withdraw funds. In practice this window is short (seconds), but for high-stakes scenarios it is still a risk.

In MPP Sessions, funds are already in escrow. Once the server has a signed voucher, it is guaranteed to settle it — nobody else can withdraw those funds. This is a fundamentally different guarantee model, paid for with deposits and at least two on-chain transactions.

Why Sessions Can Handle a Million Payments per Second and upto Cannot

Verifying one voucher in Sessions is just ECDSA signature verification plus comparing cumulativeAmount > highestVoucherAmount. That takes microseconds. A server can process thousands of vouchers per second on one channel without touching blockchain. Heavy chain interaction happens only on open/close.

In upto, every payment requires a new Permit2 nonce and new signature. upto is designed for cases where neither client nor server knows in advance how much will ultimately be charged. It enables a complex process to run and then settle afterward. MPP Sessions, by contrast, allows continuous process control.

You could implement more complex channel-like logic in x402 too — but why, if MPP Sessions already provides it?

Cumulative Semantics — Small but Elegant

In MPP Sessions, a voucher specifies total amount paid so far, not incremental payment. This gives three properties:

  • Idempotency. Re-submitting the same voucher changes nothing.
  • Replay protection without nonce. Any older voucher is rejected because it was already accepted or superseded.
  • Resilience to network flakiness. Lost vouchers do not matter — the next one covers everything.

In upto, this problem is solved differently: single-use signatures and Permit2 nonce semantics. But the scenario itself is much simpler — one signature lives for one request only.

Server State

upto is nearly stateless — the server may store nothing between verification and settlement except the signature itself.

Sessions require persistent crash-safe accounting (draft-tempo-session explicitly requires writing spent into durable storage before delivering service, otherwise a crash may cause unpaid content delivery). This is serious operational complexity if your architecture was previously stateless.

Client Protection: deadline vs Grace Period

In upto, the client is protected by signature expiry: after deadline, the facilitator can no longer charge anything. But while it remains valid, the client cannot revoke it except by spending funds or calling Permit2.invalidateNonces.

In MPP Sessions, even without server cooperation, the client can always reclaim funds: requestClose → wait 15 min → withdraw. This costs 2–3 on-chain calls and some waiting, but guarantees exit.


Pros and Cons

x402 upto

Pros:

  • Simplest integration on top of any REST API.
  • Zero operational overhead: stateless server, no background settlement tasks.
  • No deposit — client funds are not locked.
  • Fits naturally into existing HTTP semantics and HTTP 402.
  • Uses canonical Permit2 trusted across the EVM ecosystem.
  • Minimal setup: client only needs to approve Permit2 once.

Cons:

  • Not suitable for streaming: impossible to pay per-token in real time.
  • Strictly single-use authorization — multi-settlements are out of scope.
  • Server pays gas for every settlement separately.
  • Client must trust server’s cost calculation within the signed maximum.
  • Between signing and settlement, client may theoretically empty wallet.
  • Requires client funds to remain in wallet rather than escrow.

MPP Tempo Sessions

Pros:

  • True streaming: payment synchronized with data flow.
  • Gas amortization: thousands of micropayments fit into two on-chain tx.
  • Strong guarantees for server (funds already escrowed).
  • Built-in forced close protects clients.
  • Supports delegated authorizedSigner: hot wallet can sign while cold wallet deposits.
  • Clean top-up model without closing channel.
  • Uses IETF-compatible Payment Auth scheme — not just a Web3 hack.

Cons:

  • Two mandatory on-chain steps: open and close. Expensive for short sessions.
  • Deposit locks client capital.
  • Requires separate contract and infrastructure (indexing, workers, crash-safe accounting).
  • Server must maintain persistent per-channel state.
  • Harder to debug: more states, more failure scenarios.
  • Bound to a specific network (Tempo chain in this case); cross-chain is harder.

When to Choose Which

Choose upto if:

  • You have a classic REST/RPC API where one request = one response.
  • Request price is variable but resolved in one atomic operation.
  • You do not want escrow/state-channel infrastructure.
  • Your clients do not want locked deposits.
  • Payment frequency is low.
  • You want to monetize an existing API quickly with minimal changes.

Choose Sessions if:

  • You stream content (SSE, WebSocket, chunked) and want payment synchronized with bytes.
  • Agents/bots interact hundreds of times per minute.
  • Gas cost for on-chain settlement becomes comparable to service price.
  • You need strong guarantees that client payment is secured.
  • You are building AI inference marketplaces with millisecond billing latency.
  • Your architecture can support stateful servers.

Hybrid is also valid. Nothing prevents one service from supporting both upto for one-shot API requests and Sessions for streaming endpoints. At the 402 challenge level, you simply offer multiple schemes and let the client choose.


Conclusion

upto and Sessions are not competitors — they are complementary tools at different points on the “frequency vs complexity” spectrum.

  • upto is the evolution of the HTTP request. You add the ability to charge an amount only known after processing, while everything else stays familiar.
  • Sessions are the evolution of payment infrastructure. You establish a dedicated payment channel where money movement becomes nearly free, but inherit the complexity of state channels.

For most AI APIs today — where “one prompt = one response” — upto wins because of simplicity. But once you seriously enter machine-to-machine economies, where agents live inside APIs for hours and consume streams continuously, MPP Sessions becomes the only viable option.

A simple mnemonic:

upto = “Charge me whatever it costs, within the check limit.”

MPP Sessions = “I put money in the vault — take vouchers as needed until I say stop.”

Top comments (0)