MPP
The Machine Payments Protocol (MPP) lets a server answer a request with a 402 challenge. The client pays, by Stripe Shared
Payment Token or by a stablecoin transfer, and retries with a credential. The server returns a receipt.
HalvorAI records MPP from the server that is being paid, by wrapping the mppx charge handler.
Wrap the charge
Section titled “Wrap the charge”import { Mppx } from 'mppx/server';import { HalvorClient } from '@halvorai/ingest';import { withHalvorCharge } from '@halvorai/ingest/mpp';
const halvor = new HalvorClient();const mppx = Mppx.create({ /* your methods and secret */ });
const charge = withHalvorCharge(mppx.charge({ amount: '0.50' }), halvor);
export async function handle(request: Request): Promise<Response> { const result = await charge(request); if (result.status === 402) return result.challenge; // the client will pay and retry return new Response('the paid resource');}withHalvorCharge returns a handler with the same signature as the one you pass in. It does not change the result, and it
never throws.
What it records
Section titled “What it records”| Moment | Event |
|---|---|
The server issues a 402 challenge | payment.requested |
| A charge succeeds and a receipt is returned | payment.settled, with the receipt attached as mpp.receipt evidence |
| MPP | APE |
|---|---|
The payment method (spt or tempo) | payment.rail_ref.method, with payment.rail set to mpp |
| The challenge id | payment.rail_ref.challenge_id |
| The Stripe PaymentIntent behind an SPT charge | payment.rail_ref.payment_intent |
| A Tempo transfer hash | payment.rail_ref.tx_hash, with the amount in atomic units |
Attribution
Section titled “Attribution”An MPP server usually does not know the agent that is paying. Supply what you know, either per request:
await withAgentContext({ agent: { id: payerId }, owner: { id: accountId, type: 'business' } }, () => handle(request));or leave it to default to unattributed, which still records the payment but lowers your attribution coverage.
Check it works
Section titled “Check it works”Run the MPP validator against your endpoint, then open Payments. You should see a payment.requested event followed by
a payment.settled event with the receipt in its evidence.