Machine Payments Protocol (MPP): Per-Call Debits and Spend State
How Stripe and Tempo’s Machine Payments Protocol charges per HTTP call, how sessions and vouchers work, and what spend state a fleet of paying agents needs.
How Stripe and Tempo’s Machine Payments Protocol charges per HTTP call, how sessions and vouchers work, and what spend state a fleet of paying agents needs.
TL;DR: The Machine Payments Protocol (MPP), co-authored by Stripe and Tempo and launched in March 2026, puts a payment inside an HTTP request: the server issues a 402 challenge, the client pays and retries with a credential, the server returns a receipt. It works across stablecoins, cards and other rails, and its session intent lets an agent pay per call with signed vouchers instead of one settlement per request. MPP moves the money. Whether an agent should spend it is a decision your system makes on authorization-time context: remaining budget net of open sessions, per-agent caps and recent spend, read at the moment the agent pays.
An agent that needs one search result, one rendered page or one model call should not need an account, a pricing page and a billing form. Until recently it did. Most paid APIs assumed a human would sign up once, hand over a card and receive an API key.
The Machine Payments Protocol is one answer to that. The server names a price in the HTTP response, the agent pays, and the resource comes back on the retry. Per-call pricing becomes practical, down to fractions of a cent.
That shifts a problem onto whoever runs the agents. When each tool call is a debit, spend stops being a monthly invoice and becomes thousands of small decisions made by software, often by many agents at once, against shared budgets. This page covers how the Machine Payments Protocol works, what it says about spend, and what your spend state has to look like.
The Machine Payments Protocol (MPP) is an open protocol for paying for a resource inside an HTTP request. The server answers with 402 Payment Required and a challenge that describes the price; the client pays using one of the offered methods and retries with a credential; the server verifies payment and returns the resource with a receipt.
Stripe announced MPP on March 18, 2026, describing it as “an open standard, internet-native way for agents to pay—co-authored by Tempo and Stripe.” The same post says Stripe businesses can accept MPP payments through the PaymentIntents API, “in stablecoins as well as fiat with cards and buy now, pay later payment methods via Shared Payment Tokens (SPTs),” and that these payments appear in the Stripe Dashboard like any other transaction.
The core of the protocol is an Internet-Draft, The “Payment” HTTP Authentication Scheme, with authors from Tempo Labs and Stripe. The MPP governance page splits the protocol in two: the core specification, submitted to the IETF standards track, and payment methods, each “defined and maintained by the rail behind it.” Payment methods can add their own rules, and the page names “disputes, refunds, or KYC requirements” as examples.
The flow reuses HTTP authentication. Per the MPP overview, there are three headers:
Challenge. The server returns 402 Payment Required with a WWW-Authenticate: Payment header. It carries a challenge id, the method (such as tempo or stripe), the intent (such as charge or session), and a base64url-encoded request object with the amount, currency and recipient. A server can offer several challenges, one per payment method.
Credential. The client fulfills the payment (signs a transaction, completes a card payment, pays an invoice) and retries with Authorization: Payment carrying proof.
Receipt. The server verifies, delivers the resource and returns a Payment-Receipt header.
Abridged from the challenge documentation, the decoded request object looks like this:
{
"amount": "1000",
"currency": "0x20c0000000000000000000006a37DA5C996874BE",
"recipient": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
}
The server must bind the challenge id to the challenge parameters, with an HMAC or by storing them, so a client cannot reuse an id with different terms. The draft also says servers “MUST NOT perform side effects” for requests that have not been paid.
MPP defines payment intents, and two of them matter for agents.
Charge is one request, one payment, one receipt. The charge intent “requests an immediate one-time payment,” and the server settles before returning the response. It suits a fixed price per call.
Session is for metered use. The session intent “establishes reusable payment state so clients can pay for many requests, streamed chunks, or metered units without settling a separate payment for each one.” On Tempo, the pay-as-you-go guide describes the mechanics: the client deposits funds into an onchain reserve contract, opening a payment channel; it then “signs vouchers with increasing cumulative amounts as service is consumed”; it can top up without closing; and closing the channel settles the final balance and refunds the unused deposit.
That is a per-call debit with deferred settlement. Each voucher is a promise of money, signed before the money moves. The MPP FAQ says sessions support payments “as small as 0.0001 USD,” because only net settlement reaches the chain.
Three protocols with “payment” in the name do different jobs.
Sources: MPP FAQ, x402 whitepaper, Linux Foundation release, AP2.
MPP and x402 overlap the most. The MPP FAQ says x402’s exact flows “map directly onto MPP’s charge intent,” and MPP’s session intent covers metered use. For x402’s mechanics, see x402: payments by HTTP request; for how the agent commerce protocols divide the work, see UCP vs ACP.
| MPP | x402 | AP2 | |
|---|---|---|---|
| From | Stripe and Tempo | Started by Coinbase; now the x402 Foundation at the Linux Foundation | Google; donated to the FIDO Alliance |
| Job | Pay for a resource inside an HTTP request | Pay for a resource inside an HTTP request | Prove what a user authorized |
| Moves money | Yes: stablecoins on Tempo, cards, Lightning and other methods | Yes: signed payments verified and settled onchain, usually through a facilitator | No; it travels with a payment made another way |
On the server side, Stripe’s MPP integration guide uses the mppx SDK. The endpoint returns a 402 challenge when a request arrives without payment, verifies the payment on the retry and returns the resource with a receipt. Abridged from the guide:
const response = await mppx.charge({ amount: '0.50' })(request);
if (response.status === 402) return response.challenge;
return response.withReceipt(Response.json({ data: '...' }));
The guide sets two minimums that shape pricing: 0.50 USD for card payments through Shared Payment Tokens, and 0.01 USDC for stablecoin payments, which agents send to a deposit address on a chain such as Tempo and Stripe settles into the Stripe balance. Prices below a cent are what sessions are for. The guide’s npx mppx@latest validate command tests discovery, challenge formats, error handling and the full payment flow against a running server.
Cloudflare’s MPP documentation covers charging for a Worker route or an MCP tool and paying from an agent built with its Agents SDK, and lists MPP SDKs for TypeScript, Python, Rust, Go and Ruby.
The protocol is explicit about where spend judgment sits. Section 11.6 of the draft, “Amount Verification,” says clients MUST verify before authorizing payment that the “Requested amount is reasonable for the resource,” that the recipient is expected, that the currency is as expected and that the validity window is appropriate. It warns that a malicious server could put a misleading description on a challenge that requests a different amount.
Section 11.5 covers the server side: “Servers MUST ensure that concurrent requests with the same Payment credential result in at most one successful payment settlement and one resource delivery.” That stops one credential being spent twice. It says nothing about two agents each paying with their own valid credential from the same budget.
For limits, MPP points to the rail. The Managing agent spend guide says “Spend management is independent of any one payment rail.” On Tempo, it uses access keys: delegated signing keys that can carry token spending limits per period, contract and function scopes, recipient restrictions and an expiry. Its example key “can spend up to 10 OUSD per day and only transfer OUSD to one recipient.” Each key can have “its own expiry, budget, scopes, recipients, and revocation path.”
Use rail-level limits. They are also scoped to one key on one rail. A team budget spanning Tempo sessions and Stripe card payments, a per-task cap, a fleet-wide per-seller cap, or a loop breaker all live with whoever runs the agents.
Call it authorization-time context: everything the decision to pay has to read, at the moment it pays. With MPP sessions, that context has more parts than a balance.
Settled spend. What has already moved on the rail.
Open session exposure. Money locked in channel deposits, and the cumulative amount of the latest signed voucher on each channel. A voucher is spend you have promised that the server may not have settled yet.
Per-agent and per-task limits. One stuck agent should not drain the shared budget.
Recent spend by endpoint and seller. A tool that has billed two hundred times in a minute is either very useful or caught in a retry loop.
Policy version. If someone lowered a cap or blocked a seller a minute ago, every agent paying from now on needs to see it.
Most of this is derived: sums and windows over payment and voucher events. It changes on every call, and every agent about to pay reads it concurrently. That combination of state velocity and concurrency is what makes a periodic counter unsafe.
The numbers below are illustrative, built to show the mechanism.
A team runs ten research agents. Each opens an MPP session with a web-data service and a model provider, and they share a $200 daily cap. A job recomputes spend every 60 seconds from settled payments plus channel deposits.
At 15:00:00 the counter shows $186 committed, $14 of headroom. Between 15:00:00 and 15:01:00 a long document set arrives and all ten agents start streaming model output, signing vouchers as tokens arrive. Each agent’s channel runs low. Each agent checks the counter before topping up, sees $14 of headroom, and tops up by $5.
At 15:01:00 the job runs and shows $236 committed: $50 of top-ups against $14 of headroom. Every agent checked the cap. Every check read a number that did not include the other nine agents’ last minute.
Nothing in MPP failed. Each challenge was valid, each voucher was correctly signed, and each server settled at most once per credential, as section 11.5 requires. The agents paid on context that was a minute old and did not count each other’s promises. That is a race condition on unmergeable state: two agents’ spends against one cap do not merge, they add up.
The fix is to make the decision to pay read and write the same state, under concurrency, with no recompute job in between.
Reserve before you pay or top up. The budget check and the reservation are one transaction.
-- One transaction per charge, top-up or voucher batch (Postgres-style SQL)
BEGIN;
-- 1. Conditional reserve against the shared budget and the agent's own cap.
UPDATE budgets
SET reserved = reserved + :amount
WHERE budget_id = :budget_id
AND spent + reserved + :amount <= cap
RETURNING budget_id; -- zero rows: ROLLBACK, do not pay
UPDATE agent_limits
SET reserved = reserved + :amount
WHERE agent_id = :agent_id
AND spent + reserved + :amount <= daily_cap
RETURNING agent_id; -- zero rows: ROLLBACK, do not pay
-- 2. Velocity check, now that this agent's row is locked.
SELECT count(*) AS calls_last_minute
FROM payment_events
WHERE agent_id = :agent_id
AND endpoint = :endpoint
AND created_at > now() - interval '1 minute';
-- above the loop threshold: ROLLBACK, do not pay
-- 3. Record the decision.
INSERT INTO payment_events (event_id, agent_id, budget_id, endpoint, intent, channel_id, amount, status)
VALUES (:event_id, :agent_id, :budget_id, :endpoint, :intent, :channel_id, :amount, 'reserved');
COMMIT;
-- On Payment-Receipt: move :amount from reserved to spent.
-- On channel close: release whatever deposit the final voucher did not use.
Under PostgreSQL’s READ COMMITTED, a second UPDATE on the same row waits for the first transaction to commit, then re-evaluates its WHERE clause against the updated row, so two reservations cannot both pass the cap. Each later statement in the transaction takes a fresh snapshot, and any earlier transaction for the same agent had to commit before this one could lock the agent’s row, so the velocity count includes it.
Track vouchers, not just settlements. Store the latest cumulative voucher amount per channel. Open exposure is the deposit you cannot get back until close, and the voucher total is the part you have promised.
Expire with the challenge. The draft says a challenge SHOULD carry an expires timestamp, and clients must not pay against an expired challenge. A reservation for a payment that was never sent should be released when the challenge expires.
If your budget is one row and one cap, this is all ordinary Postgres, and you should use it. Notice what the shared budget row does, though: every payment from every agent queues on it, and every check you add runs while that lock is held. It gets harder when the decision also needs fleet-wide derived context: spend with this seller across every agent, voucher totals across every open channel, per-task spend that spans rails. Each is an aggregate over a table every agent is writing to at once. Run those scans under the hot row and the fleet waits on them; move them to a counter refreshed by a job and you are back in the failure above.
The Tacnode Context Lake™ holds the agent side of the loop: the decision context each agent reads before it pays, and the decision it writes after.
Budgets, reservations, per-agent limits and payment events are state your system owns. Held in Tacnode, they are covered by full ACID transactions, so two agents reserving against the same budget cannot both pass the cap. Fleet-wide aggregates, such as spend per seller in the last minute or open voucher exposure across every channel, are computed on demand against the latest committed data in the same system, so the check and the aggregate read the same moment. Receipts and channel closes flow back in as writes and become context for the next payment. Settlement records from Stripe or the chain can arrive by change data capture and join the same state, as current as that feed. The payment itself settles on its rail, as it does today; Tacnode enforces nothing inside Tempo, a card network, an issuer or Stripe’s ledger.
That is the context gap closed for one decision: each agent pays with an accurate picture of what the fleet has already promised. For how per-agent caps are modeled, see agent spend limits; for keeping a record of each payment decision, see decision ledger.

Former Cockroach Labs. Tells stories about infrastructure that actually make sense.
Fresh Context Newsletter
The argument behind the posts — what breaks when AI acts on stale data, from the team building the Context Lake. About twice a month.
Book a demo and discover how Tacnode can power your AI-native applications.
Book a Demo