Skip to content

Payments

7. Payments (x402)

7.1 Overview

M2M embeds the x402 protocol to add a settlement layer on top of the existing stack (compression → security → payments). x402 is HTTP-native: it uses the long-reserved 402 Payment Required status code and signed stablecoin authorizations (USDC on EVM chains), requiring no API keys, accounts, or subscriptions.

The implementation uses the x402-rs ecosystem and is gated behind the payments cargo feature.

Note: The payments feature requires a Rust toolchain >= 1.93 to compile (upstream MSRV). The core library remains MSRV 1.88.

7.2 Architecture

Client (payer) M2M Server (payee) Facilitator
| | |
|--- POST /compress ---------------->| |
|<-- 402 + PAYMENT-REQUIRED ---------| |
| (b64 PaymentRequired JSON) | |
| | |
| [sign EIP-712 / EIP-3009 locally] | |
| | |
|--- POST /compress --------------->|--- POST /verify ----------->|
| PAYMENT-SIGNATURE header |<-- isValid: true ------------|
| | |
|<-- 200 + PAYMENT-RESPONSE ---------|--- POST /settle ----------->|
| (b64 SettlementResponse) |<-- success: true -----------|
  • The client signs a transferWithAuthorization (EIP-3009) locally; no funds move without its signature and the facilitator cannot alter amount or recipient.
  • Verification/settlement is delegated to a facilitator over the standardized REST surface (/verify, /settle, /supported). Default: https://facilitator.x402.rs. No blockchain infrastructure runs locally.

7.3 Metered Routes

Route groupRoutesPayment
Free/health, /status, /session*, /scanNever metered
Metered/compress, /compress/auto, /decompress, /messageWhen configured

7.4 Pricing Models

Amounts are in atomic USDC units (6 decimals): 1000 = $0.001.

ModelSemantics
FlatFixed price per request.
PerTokenPrice derived from the X-Max-Tokens request header (per_1k_atomic per 1,000 tokens, rounded down), floored at minimum_atomic. Missing/zero header charges the minimum — metered endpoints can never be accessed for free by omitting the header.

Per-token pricing mirrors M2M’s design philosophy: routing metadata (MaxTokens, CostEst) is readable without payload decompression, so usage can be priced at the middleware layer with zero payload parsing.

7.5 Capability Advertisement

Agents advertise payment support during HELLO/ACCEPT negotiation via the capabilities extension map:

{
"extensions": {
"x402": "https://facilitator.x402.rs"
}
}

Peers detect support with capabilities.extensions.contains_key("x402").

7.6 Configuration

Server (payee):

Terminal window
cargo run --features payments -- server \
--pay-to 0x209693Bc6afc0C5328bA36FaF03C514EF312287C \
--payment-network eip155:84532 \
--price-per-1k-tokens 100 --price-minimum 50

Client (payer):

use m2m::payments::payer::paying_client;
let client = paying_client_from_env()?; // reads M2M_EVM_PRIVATE_KEY
let res = client.post("https://peer.example/compress")
.json(&payload)
.send()
.await?; // 402 handled automatically

7.7 Networks

NetworkCAIP-2Asset
Base Sepolia (dev default)eip155:84532USDC
Base mainneteip155:8453USDC

7.8 Security Considerations

  • Replay protection: each authorization carries a unique 32-byte nonce; EIP-3009 contracts reject reuse.
  • Time bounds: authorizations include validAfter/validBefore.
  • Trust minimization: the facilitator verifies signatures and simulates before settling; it cannot move funds beyond the signed intent.
  • Key custody: payer keys are read from M2M_EVM_PRIVATE_KEY; use a dedicated low-balance wallet for agents.
  • Settlement timing: default settles after handler success so failed requests do not charge payers; settle_before_execution trades this for stronger guarantee of payment before work begins.

7.9 Implementation Status

ComponentStatus
Server middleware (flat pricing)Stable
Server middleware (per-token pricing)Stable
Payer client (x402-reqwest)Experimental
Capability advertisementStable
Self-hosted facilitatorNot implemented (use hosted)