> ## Documentation Index
> Fetch the complete documentation index at: https://selat.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MPP on Tempo

> The MPP payment protocol and how SELAT settles it on Tempo.

**MPP** is one of the two paid-rail protocols SELAT can use to satisfy an [HTTP 402](/docs/primers/http-402) challenge (the other is [x402](/docs/primers/x402)). When SELAT routes a request over MPP, the payment settles on **Tempo**.

In the [SELAT Router SDK](/docs/selat-sdk/router-client), MPP is the default rail — `preferProtocol` defaults to `mpp`, with `x402` available when explicitly requested.

<Note>
  MPP stands for **Machine Payments Protocol**, an open machine-to-machine payment standard co-authored by Tempo and Stripe. The wire format SELAT detects (a `www-authenticate: Payment ...` challenge over HTTP 402) is public; how the SELAT Router signs and settles the Tempo leg internally is proprietary and is not described here.
</Note>

## What MPP is

MPP reuses HTTP 402 as a challenge–response handshake built on a `Payment` HTTP authentication scheme. A server that wants payment returns `402 Payment Required` with a `WWW-Authenticate: Payment` header carrying a challenge; the client fulfils it and retries with an `Authorization: Payment` credential, and the server returns the resource (with a `Payment-Receipt` header). The protocol is payment-method-agnostic — the same endpoint can accept stablecoins, cards, or other methods. SELAT uses the **Tempo stablecoin method** for the MPP rail.

<Tip>
  This is the same 402 shape as [x402](/docs/primers/x402) — the difference is the challenge scheme. x402 advertises an `X402` challenge (or a `payment-required:` body header); MPP advertises a `Payment` challenge in `www-authenticate`. Many services expose both in one response.
</Tip>

## What Tempo is

Tempo is a payments-first, EVM-compatible Layer 1 blockchain incubated by Stripe and Paradigm, with Paradigm's Matt Huang as CEO. It is purpose-built for stablecoin payments and pairs naturally with MPP, the agent-payments protocol it shipped alongside. SELAT's chain-normalization layer maps the network to **`tempo:4217`** (chain ID 4217) — see `normalizeNetwork()` in the discovery skill's `chains.mjs`.

<Note>
  Tempo's marketed performance characteristics (high throughput, sub-second finality, stablecoin-denominated gas, sub-cent transfer costs) come from Tempo's own materials and third-party coverage. Treat them as vendor claims rather than SELAT-verified facts. The specific stablecoin and per-transaction fee SELAT incurs on the Tempo leg are not exposed in selat-pay or the SELAT docs.
</Note>

## How SELAT detects MPP

[selat-pay](/docs/selat-cli) probes the upstream once with no `Authorization` header and parses **both** protocols from the same response. A `www-authenticate` header can carry several comma-separated challenges (for example `X402 requirements="...", Payment id="..."`); selat-pay splits them and reads each.

An MPP challenge has the form:

```
www-authenticate: Payment id="...", realm="...", method="tempo", intent="charge", request="<base64-json>", ...
```

`decodeMppChallenge()` extracts the quoted params and base64-decodes the `request` JSON, surfacing the amount, currency, recipient, and `methodDetails.chainId`. The summarizer composes a network string as `method:chainId` (e.g. `tempo:4217`).

<Note>
  The challenge `method` value: the code comment shows `method="tempo"`, and the summarizer builds `tempo:4217` from `method` + the request's `chainId`. Whether the live router emits the bare `tempo` token or another form is not pinned down in these sources.
</Note>

### Dual-protocol services

Some services gate the MPP path behind an auth header (observed with Nansen). When the first probe surfaces no MPP challenge and there is reason to look for it, selat-pay conditionally fires a **second probe** with `Authorization: Payment probe` to unlock the hidden challenge. It does not send that header blindly — some services reject unknown auth — so the second probe runs only when MPP was asked for (`--prefer-mpp`) but not found, or as a last resort when the first probe surfaced no payable protocol at all.

## How SELAT chooses the rail

After probing, selat-pay picks a route mode:

Every paid call is routed through the SELAT Router; the probe decides the router's **outbound protocol**:

<Steps>
  <Step title="Same-rail passthrough wins for Gateway-capable upstreams">
    If the upstream offers a [Circle Gateway-batched](/docs/primers/nanopayments-gateway) accept on the agent's chain, the call routes as `routed-x402` — a same-rail passthrough with no cross-protocol translation, currently quoted at par by the router.
  </Step>

  <Step title="MPP wins otherwise">
    With no Gateway-batched accept, MPP is preferred over cross-protocol x402 by default (`routed-mpp`).
  </Step>

  <Step title="Flags override">
    `--prefer-x402` opts out of MPP; `--prefer-mpp` forces MPP even for a Gateway-capable upstream. The two flags are mutually exclusive. In the SDK this surfaces as `preferProtocol: "mpp" | "x402"`.
  </Step>
</Steps>

When the chosen mode is `routed-mpp`, selat-pay targets the SELAT Router proxy (`routerUrl/proxy?target=...`) and sends the hint header `x-selat-prefer-protocol: mpp`; the router translates the inbound Gateway-batched payment to the tempo-native leg on the way out.

<Note>
  **Verified vs. proprietary.** Verified from code/public sources: the `www-authenticate: Payment` detection, the dual-probe behavior, the rail-selection order, the `x-selat-prefer-protocol` hint, the `tempo:4217` identity, MPP's HTTP-402 handshake, and the router's default markup on routed rails (\~5%; see the discovery skill's README). Left as open items (not asserted): the router's internal MPP signing/settlement, whether SELAT uses MPP's streaming "sessions" primitive (selat-pay treats each call as a discrete challenge), and the settlement asset and fee on Tempo.
</Note>

## Next

* [x402](/docs/primers/x402)
* [Nanopayments powered by Circle Gateway](/docs/primers/nanopayments-gateway)
* [SELAT Router SDK](/docs/selat-sdk/router-client)
