go middleware for the machine payments protocol (MPP).
agents pay per-request via HTTP 402 challenge-credential-receipt exchanges. no accounts, no API keys — just pay and go.
implements draft-ryan-httpauth-payment-01 (IETF).
go get github.com/inference-sh/mpp
pay := mpp.Middleware(mpp.Config{
SecretKey: secretKey,
Realm: "api.example.com",
Methods: []mpp.Method{
&mpp.StripeMethod{
Client: stripe.NewClient("sk_live_..."),
NetworkID: "profile_xxx",
PaymentMethodTypes: []string{"card", "link"},
},
},
Price: func(r *http.Request) (string, string, error) {
return "50", "usd", nil // 50 cents
},
AllowFallthrough: true, // let Bearer API key requests pass through
})
r := chi.NewRouter()
r.Route("/v1", func(r chi.Router) {
r.Use(pay)
r.Post("/generate", generateHandler)
})full runnable example: examples/chi
works with chi, gorilla/mux, stdlib ServeMux, or any net/http compatible router.
agent your server
| |
| POST /v1/generate |
|---------------------------------------→|
| |
| 402 Payment Required |
| WWW-Authenticate: Payment id="...", |
| method="stripe", amount="50", ... |
|←---------------------------------------|
| |
| [agent pays via Stripe SPT] |
| |
| POST /v1/generate |
| Authorization: Payment <credential> |
|---------------------------------------→|
| |
| 200 OK |
| Payment-Receipt: <receipt> |
|←---------------------------------------|
- HMAC-signed challenges — tamper-proof price binding, constant-time verification
- multiple payment methods — stripe SPT (fiat) built-in, implement
Methodinterface for tempo, x402, lightning, or custom settlement - crypto-ready — string amounts throughout (no int64 precision loss for wei/lamports),
Methodinterface is settlement-agnostic AllowFallthrough— mount on the same route as API key auth. bearer tokens pass through, unauthenticated requests get a 402 challenge. this is the key feature for adding MPP to an existing API without separate routesOnPaymentcallback — hook into your billing system after payment verificationPriceFn— dynamic per-request pricing. look up the resource, evaluate your pricing formula, return the cost- context helpers —
ReceiptFromContext(ctx)andCredentialFromContext(ctx)in your handler - defense-in-depth — HMAC binding + SPT prefix validation + request field verification + idempotency replay detection
- RFC 9457 problem details — structured error responses per spec
# terminal 1: run the demo server
cd examples/chi
STRIPE_SECRET_KEY=sk_test_... STRIPE_PROFILE_ID=profile_test_... go run .
# terminal 2: hit a paid endpoint (gets 402 challenge)
curl -i http://localhost:8080/v1/generate
# hit with an API key (AllowFallthrough passes through)
curl -i -H "Authorization: Bearer my-api-key" http://localhost:8080/v1/generate
# hit a free endpoint
curl -i http://localhost:8080/healthaccepts fiat payments via shared payment tokens (SPTs). requires a Stripe profile for the networkId.
&mpp.StripeMethod{
Client: stripe.NewClient(os.Getenv("STRIPE_SECRET_KEY")),
NetworkID: "profile_xxx",
PaymentMethodTypes: []string{"card", "link"},
Decimals: 2, // default for USD; set to 6 for USDC
}implement the Method interface to add any payment rail:
type Method interface {
Name() string
ChallengeRequest(amount, currency string) map[string]any
Verify(ctx context.Context, cred *Credential, amount, currency string) (reference string, err error)
}amounts are strings to support both fiat cents and crypto wei/lamports without precision loss.
MIT — inference.sh