Canopy

MPP — Auto-pay sub-cent calls on Tempo

MPP (Multi-Provider Payments) is an HTTP authentication standard for agent-initiated payments. When a server requires payment for a resource, it returns a 401 Unauthorized with a WWW-Authenticate: Payment challenge that names a method (e.g. tempo), an intent (charge), and the price. The client signs a credential, retries with Authorization: Payment …, and the server verifies and serves the response.

Canopy supports MPP on Tempo today. Tempo's sub-cent fees and fast finality make it the natural rail for high-frequency agent calls — research feeds, embeddings, ranking, anything where x402's per-tx cost on Base is too coarse.

canopy.fetch() handles both x402 and MPP transparently. The same call works against either rail; the SDK picks the funded chain based on your treasury balance.

Calling an MPP-paywalled API

Same surface as x402 — your code never sees the 401:

import { Canopy } from "@canopy-ai/sdk";
 
const canopy = new Canopy({
  apiKey: process.env.CANOPY_API_KEY!,
  agentId: process.env.CANOPY_AGENT_ID!,
});
 
const res = await canopy.fetch("https://feed.example.tempo/depth/btc-usd");
const data = await res.json();
res = canopy.fetch("https://feed.example.tempo/depth/btc-usd")
data = res.json()

The agent's policy gates MPP charges the same way it gates x402 — caps, allowlists, approvals all apply. Outcomes (allowed / pending_approval / denied) are uniform across rails.

When MPP, when x402

QuestionAnswer
Single call costs more than ~$0.10x402 on Base is fine — the per-tx fee is a small fraction of the call
Calls cost cents or sub-cent, made many timesMPP on Tempo — Tempo's fees keep the spread workable
You don't know in advanceUse canopy.discover() and check paymentMethods — it lists the rails each service supports
The provider only supports oneWhatever they support

Treasury funding across rails

The treasury is one wallet, two chains. Canopy routes balance to the chain that needs to settle:

  • Treasury starts with USDC on Base.
  • When an MPP charge needs Tempo USDC.e and the Tempo balance is empty, Canopy bridges via Stargate / LayerZero and retries.
  • Bridge events are recorded as treasury_movements (separate from agent-attributed transactions).

In the dashboard, the Treasury page surfaces both balances. In the SDK, canopy.discover() returns each service's preferredBaseUrl already biased toward the chain currently funded — so the agent doesn't have to think about it.

Discovering MPP services

const services = await canopy.discover({ category: "data" });
const mpp = services.filter((s) =>
  s.paymentMethods.some((pm) => pm.protocol === "mpp")
);
services = canopy.discover(category="data")
mpp = [s for s in services if any(pm["protocol"] == "mpp" for pm in s["payment_methods"])]

Where to go next

  • x402 — the EVM-native counterpart
  • Payment outcomes — the same allowed / pending_approval / denied shape applies to MPP charges
  • Treasury — how the org wallet funds both rails