Machine Payments Protocol (MPP) for Algorand — HTTP-native micropayments using 402 Payment Required.
Try it live: https://mpp.goplausible.xyz (TestNet)
The Machine Payments Protocol (MPP) enables any HTTP API to charge for access using standard HTTP headers. When a client requests a paid resource, the server responds with 402 Payment Required and a payment challenge. The client pays on-chain, retries the request with proof of payment, and receives the resource.
MPP is designed for machine-to-machine payments — AI agents, automated systems, and applications that consume paid APIs without human intervention.
This SDK implements MPP for the Algorand blockchain, supporting:
- Native ALGO payments and ASA payments (USDC, etc.)
- Fee sponsorship — server pays transaction fees on behalf of clients
- Lease-based idempotency — protocol-level replay protection bound to each challenge
- Server-broadcast — server broadcasts transactions
Built on @algorandfoundation/algokit-utils v10 (no algosdk dependency) and the mppx protocol library.
| Document | Description |
|---|---|
| Documentation Index | Full documentation table of contents |
| What is MPP? | Protocol overview and comparison with traditional payments |
| Algorand Charge Spec | Algorand-specific charge method specification |
| Architecture | SDK modules, entry points, and design decisions |
| Payment Flows | Sequence diagrams for all payment modes |
| Demo Guide | Demo app features, scenarios, and walkthrough |
| Demo README | Demo quick start, configuration, and API reference |
| Full Specification | Complete IETF-style specification |
npm install @goplausible/algorand-mpp-sdk mppx
# or
pnpm add @goplausible/algorand-mpp-sdk mppximport express from 'express'
import { Mppx, algorand } from '@goplausible/algorand-mpp-sdk/server'
const mppx = Mppx.create({
secretKey: process.env.MPP_SECRET_KEY,
methods: [
algorand.charge({
recipient: 'YOUR_ALGO_ADDRESS',
network: 'algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=',
algodUrl: 'https://testnet-api.4160.nodely.dev',
}),
],
})
const app = express()
app.get('/api/data', async (req, res) => {
const webReq = toWebRequest(req) // convert Express req to Web Request
const result = await mppx.charge({
amount: '10000', // 0.01 ALGO
currency: 'ALGO',
description: 'API data access',
})(webReq)
if (result.status === 402) {
const challenge = result.challenge as Response
res.writeHead(challenge.status, Object.fromEntries(challenge.headers))
res.end(await challenge.text())
return
}
const response = result.withReceipt(Response.json({ data: '...' })) as Response
res.writeHead(response.status, Object.fromEntries(response.headers))
res.end(await response.text())
})import { Mppx, algorand } from '@goplausible/algorand-mpp-sdk/client'
// signTransactions from @txnlab/use-wallet
const method = algorand.charge({
signer: signTransactions,
senderAddress: activeAccount.address,
algodUrl: 'https://testnet-api.4160.nodely.dev',
})
const mppx = Mppx.create({ methods: [method] })
// Automatically handles 402 → pay → retry
const response = await mppx.fetch('https://api.example.com/api/data')
const data = await response.json()algorand.charge({
recipient: 'SELLER_ADDRESS',
network: 'algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=',
algodUrl: 'https://testnet-api.4160.nodely.dev',
// ASA payment (USDC)
asaId: 10458941n,
decimals: 6,
// Fee sponsorship
signer: feePayerSigner,
signerAddress: 'FEE_PAYER_ADDRESS',
})- Node.js >= 18
- pnpm >= 10
git clone https://github.com/GoPlausible/algorand-mpp-sdk.git
cd algorand-mpp-sdk
pnpm installpnpm build # Build the SDK (TypeScript → dist/)pnpm test # Run unit tests
pnpm test:watch # Watch mode
pnpm test:all # Unit + integration testspnpm lint # Check for lint errors
pnpm lint:fix # Auto-fix lint errors
pnpm format # Format code with Prettier
pnpm typecheck # Type-check without emittingThe demo includes a paid API server and a React frontend for interactive testing.
pnpm build # Build the SDK first
pnpm demo:install # Install demo dependencies
# Configure environment
cp demo/server/.env-local demo/server/.env # Edit with your values
cp demo/app/.env-local demo/app/.env # Edit with your valuespnpm demo:dev # Runs server (port 3000) + app (port 5173)pnpm demo:build # Build server + app
pnpm demo:start # Start production server| Method | Path | Cost | Description |
|---|---|---|---|
| GET | /api/v1/weather/:city |
0.01 ALGO | Weather data (native ALGO payment) |
| GET | /api/v1/marketplace/products |
Free | List marketplace products |
| GET | /api/v1/marketplace/buy/:id |
0.10-0.17 USDC | Marketplace purchase (USDC payment) |
| GET | /api/v1/health |
Free | Server status and configuration |
- ALGO — Lora TestNet Faucet
- USDC — Circle Faucet (select Algorand TestNet)
- Opt-in to USDC — Add ASA ID
10458941via your wallet
algorand-mpp-sdk/
├── sdk/src/ # SDK source code
│ ├── client/ # Client-side charge (browser/Node)
│ ├── server/ # Server-side charge (verify, sign, broadcast)
│ ├── utils/ # Transaction building and encoding
│ ├── Methods.ts # Shared charge method schema
│ └── constants.ts # Network IDs, algod URLs
├── demo/
│ ├── server/ # Express demo server
│ └── app/ # React + Vite demo frontend
├── docs/ # Documentation
├── specs/ # Algorand charge specification
├── dist/ # Built SDK output
└── package.json