<!--
Sitemap:
- [MPP — Machine Payments Protocol](/index): MPP (Machine Payments Protocol) is the open standard for machine-to-machine payments—co-developed by Tempo and Stripe. Charge for API requests, tool calls, and content via HTTP 402.
- [Page Not Found](/404)
- [Brand assets and guidelines](/brand): Download official MPP logos, wordmarks, and brand assets. Guidelines for using the Machine Payments Protocol brand in your project or integration.
- [Extensions](/extensions): Community-built tools and integrations for MPP
- [Frequently asked questions](/faq): Answers to common questions about MPP—payment methods, settlement, pricing, security, and how the protocol compares to API keys and subscriptions.
- [Machine Payments Protocol](/overview): MPP standardizes HTTP 402 for machine-to-machine payments. Learn how agents, apps, and services exchange payments in the same HTTP request.
- [Payment methods](/payment-methods/): Available methods and how to choose one
- [Protocol overview](/protocol/): The Machine Payments Protocol standardizes HTTP 402 with an extensible challenge–credential–receipt flow that works with any payment network.
- [Quickstart](/quickstart/): Get started with MPP in minutes. Protect your API with payments, connect your agent, or integrate your app with MPP-enabled services.
- [SDKs and client libraries](/sdk/): Official MPP SDKs in TypeScript, Python, and Rust, plus community SDKs in other languages.
- [Discovery](/advanced/discovery): Advertise your API's payment terms with an OpenAPI discovery document so clients and agents know what endpoints cost before making requests.
- [Identity](/advanced/identity): Use MPP Credentials for access control, rate limiting, and multi-step workflows—without requiring payment.
- [Refunds](/advanced/refunds): Return funds to clients after a charge, or let sessions refund unused deposits automatically.
- [Build with an LLM](/guides/building-with-an-llm): Use llms-full.txt to give your agent complete MPP context.
- [Accept multiple payment methods](/guides/multiple-payment-methods): Accept Tempo stablecoins, Stripe cards, and Lightning Bitcoin on a single API endpoint. Serve a multi-method 402 Challenge and let clients choose.
- [Accept one-time payments](/guides/one-time-payments): Charge per request with a payment-gated API
- [Accept pay-as-you-go payments](/guides/pay-as-you-go): Build a payment-gated API with session-based billing using mppx payment channels. Charge per request with near-zero latency overhead.
- [Proxy an existing service](/guides/proxy-existing-service): Put a payment gate in front of any API without changing its code. Use the mppx Proxy SDK to charge for upstream access.
- [Accept split payments](/guides/split-payments): Distribute a charge across multiple recipients
- [Accept streamed payments](/guides/streamed-payments): Accept streamed payments over Server-Sent Events with mppx. Bill per token in real time using Tempo payment channels for LLM inference APIs.
- [Charge intent for one-time payments](/intents/charge): Immediate one-time payments
- [Card payment method](/payment-methods/card/): Card payments via encrypted network tokens
- [Custom payment methods](/payment-methods/custom): Build your own payment method
- [Lightning](/payment-methods/lightning/): Bitcoin payments over the Lightning Network
- [Solana](/payment-methods/solana/): Native SOL and SPL token payments
- [Stellar SEP-41 token payments](/payment-methods/stellar/): SEP-41 token payments on the Stellar network
- [Stripe payment method](/payment-methods/stripe/): Cards, wallets, and other Stripe supported payment methods
- [Tempo stablecoin payments](/payment-methods/tempo/): Stablecoin payments on the Tempo blockchain
- [Challenges](/protocol/challenges): Server-issued payment requirements
- [Credentials](/protocol/credentials): Client-submitted payment proofs
- [HTTP 402 payment required](/protocol/http-402): HTTP 402 Payment Required signals that a resource requires payment. Learn when and how MPP servers return 402 with a WWW-Authenticate Challenge.
- [Payment receipts and verification](/protocol/receipts): Receipts confirm successful payment in MPP. Return them in the Payment-Receipt header so clients can verify that the server accepted their Credential.
- [Transports](/protocol/transports/): MPP defines transport bindings for HTTP and MCP. Learn how Challenges, Credentials, and Receipts map to headers and JSON-RPC messages.
- [Use with agents](/quickstart/agent): Connect your coding agent to MPP-enabled services. Set up Tempo Wallet or the mppx SDK to handle 402 payment flows automatically.
- [Use with your app](/quickstart/client): Handle payment-gated resources in your app. Use the mppx client SDK to intercept 402 responses, pay, and retry—all automatically.
- [Add payments to your API](/quickstart/server): Add payment-gated access to your API with mppx. Accept stablecoins, cards, and Bitcoin in a few lines of code using the MPP server SDK.
- [SDK features](/sdk/features): Feature parity across TypeScript, Python, and Rust MPP SDKs.
- [Python SDK](/sdk/python/): The pympp Python library
- [Rust SDK for MPP](/sdk/rust/): The mpp Rust library
- [Getting started](/sdk/typescript/): The mppx TypeScript library
- [Card charge](/payment-methods/card/charge): One-time payments using encrypted network tokens
- [Lightning charge](/payment-methods/lightning/charge): One-time payments using BOLT11 invoices
- [Lightning session](/payment-methods/lightning/session): Pay-as-you-go payments over Lightning
- [Solana charge](/payment-methods/solana/charge): One-time payments on Solana
- [Stellar charge](/payment-methods/stellar/charge): One-time SEP-41 token transfers
- [Channel](/payment-methods/stellar/session): High-frequency off-chain payments
- [Stripe charge](/payment-methods/stripe/charge): One-time payments using Shared Payment Tokens
- [Tempo charge](/payment-methods/tempo/charge): One-time TIP-20 token transfers
- [Session](/payment-methods/tempo/session): Low-cost high-throughput payments
- [HTTP transport](/protocol/transports/http): The HTTP transport maps MPP payment flows to standard HTTP headers—WWW-Authenticate for Challenges, Authorization for Credentials, and Payment-Receipt.
- [MCP and JSON-RPC transport](/protocol/transports/mcp): Payment flows for AI tool calls
- [Python MPP client](/sdk/python/client): Handle 402 responses automatically
- [Core Types](/sdk/python/core): Challenge, Credential, and Receipt primitives
- [Server](/sdk/python/server): Protect endpoints with payment requirements
- [Client](/sdk/rust/client): Handle 402 responses automatically
- [Core types](/sdk/rust/core): Challenge, Credential, and Receipt primitives
- [Server](/sdk/rust/server): Protect endpoints with payment requirements
- [CLI Reference](/sdk/typescript/cli): Built-in command-line tool for paid HTTP requests
- [Method.from](/sdk/typescript/Method.from): Create a payment method from a definition
- [Paid API proxy server](/sdk/typescript/proxy): Paid API proxy
- [McpClient.wrap](/sdk/typescript/client/McpClient.wrap): Payment-aware MCP client
- [stripe client method](/sdk/typescript/client/Method.stripe): Register all Stripe intents
- [Method.stripe.charge](/sdk/typescript/client/Method.stripe.charge): One-time payments via Shared Payment Tokens
- [tempo client method](/sdk/typescript/client/Method.tempo): Register all Tempo intents
- [Method.tempo.charge](/sdk/typescript/client/Method.tempo.charge): One-time payments
- [Method.tempo.session](/sdk/typescript/client/Method.tempo.session): Low-cost high-throughput payments
- [tempo.session](/sdk/typescript/client/Method.tempo.session-manager): Standalone session manager
- [Mppx.create](/sdk/typescript/client/Mppx.create): Create a payment-aware fetch client
- [Mppx.restore](/sdk/typescript/client/Mppx.restore): Restore the original global fetch
- [Transport.from](/sdk/typescript/client/Transport.from): Create a custom transport
- [Transport.http](/sdk/typescript/client/Transport.http): HTTP transport for payments
- [Transport.mcp](/sdk/typescript/client/Transport.mcp): MCP transport for payments
- [BodyDigest.compute](/sdk/typescript/core/BodyDigest.compute): Compute a body digest hash
- [BodyDigest.verify](/sdk/typescript/core/BodyDigest.verify): Verify a body digest hash
- [Challenge.deserialize](/sdk/typescript/core/Challenge.deserialize): Deserialize a Challenge from a header
- [Challenge.from](/sdk/typescript/core/Challenge.from): Create a new Challenge
- [Challenge.fromHeaders](/sdk/typescript/core/Challenge.fromHeaders): Extract a Challenge from Headers
- [Challenge.fromMethod](/sdk/typescript/core/Challenge.fromMethod): Create a Challenge from a method
- [Challenge.fromResponse](/sdk/typescript/core/Challenge.fromResponse): Extract a Challenge from a Response
- [Challenge.meta](/sdk/typescript/core/Challenge.meta): Extract correlation data from a Challenge
- [Challenge.serialize](/sdk/typescript/core/Challenge.serialize): Serialize a Challenge to a header
- [Challenge.verify](/sdk/typescript/core/Challenge.verify): Verify a Challenge HMAC
- [Credential.deserialize](/sdk/typescript/core/Credential.deserialize): Deserialize a Credential from a header
- [Credential.from](/sdk/typescript/core/Credential.from): Create a new Credential
- [Credential.fromRequest](/sdk/typescript/core/Credential.fromRequest): Extract a Credential from a Request
- [Credential.serialize](/sdk/typescript/core/Credential.serialize): Serialize a Credential to a header
- [Expires utility functions](/sdk/typescript/core/Expires): Generate relative expiration timestamps
- [Method.from](/sdk/typescript/core/Method.from): Create a payment method definition
- [Method.toClient](/sdk/typescript/core/Method.toClient): Extend a method with client logic
- [Method.toServer](/sdk/typescript/core/Method.toServer): Extend a method with server verification
- [PaymentRequest.deserialize](/sdk/typescript/core/PaymentRequest.deserialize): Deserialize a payment request
- [PaymentRequest.from](/sdk/typescript/core/PaymentRequest.from): Create a payment request
- [PaymentRequest.serialize](/sdk/typescript/core/PaymentRequest.serialize): Serialize a payment request to a string
- [Receipt.deserialize](/sdk/typescript/core/Receipt.deserialize): Deserialize a Receipt from a header
- [Receipt.from](/sdk/typescript/core/Receipt.from): Create a new Receipt
- [Receipt.fromResponse](/sdk/typescript/core/Receipt.fromResponse): Extract a Receipt from a Response
- [Receipt.serialize](/sdk/typescript/core/Receipt.serialize): Serialize a Receipt to a string
- [Elysia payment middleware](/sdk/typescript/middlewares/elysia): Payment middleware for Elysia
- [Express payment middleware](/sdk/typescript/middlewares/express): Payment middleware for Express
- [Hono payment middleware](/sdk/typescript/middlewares/hono): Payment middleware for Hono
- [Next.js payment middleware](/sdk/typescript/middlewares/nextjs): Payment middleware for Next.js
- [stripe](/sdk/typescript/server/Method.stripe): Register all Stripe intents
- [Method.stripe.charge](/sdk/typescript/server/Method.stripe.charge): One-time payments via Shared Payment Tokens
- [tempo server method](/sdk/typescript/server/Method.tempo): Register all Tempo intents
- [Method.tempo.charge](/sdk/typescript/server/Method.tempo.charge): One-time stablecoin payments
- [Method.tempo.session](/sdk/typescript/server/Method.tempo.session): Low-cost high-throughput payments
- [Mppx.compose](/sdk/typescript/server/Mppx.compose): Present multiple payment options
- [Mppx.create](/sdk/typescript/server/Mppx.create): Create a server-side payment handler
- [Mppx.toNodeListener](/sdk/typescript/server/Mppx.toNodeListener): Adapt payments for Node.js HTTP
- [Request.toNodeListener](/sdk/typescript/server/Request.toNodeListener): Convert Fetch handlers to Node.js
- [Response.requirePayment](/sdk/typescript/server/Response.requirePayment): Create a 402 response
- [Transport.from](/sdk/typescript/server/Transport.from): Create a custom transport
- [Transport.http](/sdk/typescript/server/Transport.http): HTTP server-side transport
- [Transport.mcp](/sdk/typescript/server/Transport.mcp): Raw JSON-RPC MCP transport
- [Transport.mcpSdk](/sdk/typescript/server/Transport.mcpSdk): MCP SDK server-side transport
-->

# `tempo.session` \[Standalone session manager]

Creates a standalone session manager that handles the full payment channel lifecycle—open, fetch, stream, and close—without `Mppx.create` or `Fetch.from`.

Use this when you need direct control over session state instead of automatic 402 handling.

## Usage

```ts twoslash
import { tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')

const session = tempo.session({
  account,
  maxDeposit: '1',
})

// Make a paid request — opens a channel on first call
const response = await session.fetch('https://api.example.com/resource')
console.log(response.status)
// @log: 200

// Access payment metadata
console.log(response.receipt)
console.log(response.cumulative)

// Close the channel and settle on-chain
const receipt = await session.close()
```

:::warning
Channels remain open until you call `session.close()`. Always close sessions when done to settle on-chain and reclaim unspent deposit.
:::

### Session resumption

All channel state is held in memory. If the client process restarts, the session is lost and a new on-chain channel opens on the next request—the previous channel's deposit is orphaned until manually closed.

When the server includes a `channelId` in the `402` Challenge, the client attempts to recover the channel by reading its on-chain state. If the channel has a positive deposit and is not finalized, it resumes from the on-chain settled amount.

### With SSE streaming

Stream server-sent events with automatic voucher handling. The session signs incremental vouchers as the server requests them during the stream.

```ts twoslash
import { tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'

const session = tempo.session({
  account: privateKeyToAccount('0x...'),
  maxDeposit: '5',
})

const stream = await session.sse('https://api.example.com/stream', {
  onReceipt(receipt) {
    console.log('Receipt:', receipt)
  },
  signal: AbortSignal.timeout(30_000),
})

for await (const message of stream) {
  console.log(message)
}

await session.close()
```

### With explicit open

Open the channel before the first request. This separates the on-chain deposit transaction from the first API call.

```ts twoslash
import { tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')

const session = tempo.session({
  account,
  maxDeposit: '10',
})

// Trigger a 402 to receive the challenge
await session.fetch('https://api.example.com/resource')

// Open the channel explicitly
await session.open()

// Subsequent requests use the open channel
const response = await session.fetch('https://api.example.com/resource')
```

## Return type

`tempo.session()` returns a `SessionManager` object:

```ts
type SessionManager = {
  readonly channelId: Hex | undefined
  readonly cumulative: bigint
  readonly opened: boolean
  open(options?: { deposit?: bigint }): Promise<void>
  fetch(input: RequestInfo | URL, init?: RequestInit): Promise<PaymentResponse>
  sse(
    input: RequestInfo | URL,
    init?: RequestInit & {
      onReceipt?: (receipt: SessionReceipt) => void
      signal?: AbortSignal
    },
  ): Promise<AsyncIterable<string>>
  close(): Promise<SessionReceipt | undefined>
}
```

### `PaymentResponse`

`session.fetch()` returns a standard `Response` extended with payment metadata:

```ts
type PaymentResponse = Response & {
  receipt: SessionReceipt | null
  challenge: Challenge | null
  channelId: Hex | null
  cumulative: bigint
}
```

### `SessionReceipt`

The receipt returned by `session.close()` and available on `PaymentResponse.receipt`:

```ts
type SessionReceipt = {
  method: 'tempo'
  intent: 'session'
  status: 'success'
  timestamp: string
  /** Payment channel ID (not a transaction hash). */
  reference: string
  challengeId: string
  channelId: Hex
  /** Highest cumulative voucher amount accepted by the server. */
  acceptedCumulative: string
  /** Total amount spent in this session. */
  spent: string
  /** Number of units consumed (if the server tracks units). */
  units?: number
  /** On-chain settlement transaction hash. Present after close. */
  txHash?: Hex
}
```

:::info
The `reference` field contains the channel ID, not a transaction hash. To get the settlement transaction hash, read `txHash` from the receipt returned by `session.close()`.
:::

## Parameters

### account (optional)

* **Type:** `Account`

Account to sign vouchers with.

### authorizedSigner (optional)

* **Type:** `Address`

Address authorized to sign vouchers. Defaults to the account address. Use when a separate access key signs vouchers while the root account funds the channel.

### client (optional)

* **Type:** `Client`

Viem client instance. Shorthand for `getClient: () => client`.

### decimals (optional)

* **Type:** `number`
* **Default:** `6`

Token decimals for parsing human-readable amounts like `maxDeposit`.

### escrowContract (optional)

* **Type:** `Address`

Escrow contract address override. Derived from the server Challenge if not provided.

### fetch (optional)

* **Type:** `typeof globalThis.fetch`
* **Default:** `globalThis.fetch`

Custom fetch function to use for requests.

### getClient (optional)

* **Type:** `(parameters: { chainId: number }) => MaybePromise<Client>`

Function that returns a viem client for the given chain ID.

### maxDeposit (optional)

* **Type:** `string`

Maximum deposit in human-readable units (for example `"10"` for 10 tokens). Caps the server's suggested deposit and enables automatic channel management.

## Methods

### `session.close()`

Closes the payment channel and settles on-chain. Returns the final `SessionReceipt` if available, or `undefined` if no channel was open.

```ts
const receipt = await session.close()
```

### `session.fetch(input, init?)`

Makes a payment-aware request. Handles the 402 Challenge → Credential flow automatically, opening a channel on first use if needed.

Returns a [`PaymentResponse`](#paymentresponse) with payment metadata attached.

```ts
const response = await session.fetch('https://api.example.com/resource')
console.log(response.receipt)
console.log(response.cumulative)
```

### `session.open(options?)`

Opens the payment channel explicitly. You must make at least one `fetch()` or `sse()` call first to receive a 402 Challenge from the server.

* **options.deposit** (`bigint`, optional) — Raw deposit amount in token units.

```ts
await session.fetch('https://api.example.com/resource')
await session.open()
```

### `session.sse(input, init?)`

Opens a server-sent events stream with automatic voucher signing. The server requests incremental vouchers via `payment-need-voucher` events, and the session signs them transparently.

Returns an `AsyncIterable<string>` of message payloads.

* **init.onReceipt** (`(receipt: SessionReceipt) => void`, optional) — Called when the server sends a payment Receipt during the stream.
* **init.signal** (`AbortSignal`, optional) — Aborts the stream.

```ts
const stream = await session.sse('https://api.example.com/stream', {
  onReceipt: (receipt) => console.log('paid:', receipt),
  signal: AbortSignal.timeout(60_000),
})

for await (const message of stream) {
  console.log(message)
}
```

## Properties

### `session.channelId`

* **Type:** `Hex | undefined`

The on-chain channel ID after the channel opens. `undefined` before the first successful payment.

### `session.cumulative`

* **Type:** `bigint`

The cumulative amount paid across all vouchers in this session. Starts at `0n`.

### `session.opened`

* **Type:** `boolean`

Whether the payment channel is currently open.
