MPP is the Machine Payments Protocol: an IETF draft (Documentation Index
Fetch the complete documentation index at: https://docs.getovra.com/llms.txt
Use this file to discover all available pages before exploring further.
draft-httpauth-payment-00, co-authored Tempo Labs + Stripe, see paymentauth.org) that turns HTTP 402 Payment Required into a real, machine-readable challenge. Ovra implements the card method as a credential issuer.
If a merchant returns WWW-Authenticate: Payment ..., your agent can pay it without ever rendering a form, opening a browser, or seeing a card number.
Code-complete (Phase 7). Sandbox-only end-to-end. The credential envelope is a real JWE; merchants ship a private key in their MPP onboarding to decrypt it.
Wire flow
Agent mints a credential
Agent calls
POST /v1/mpp/credentials/mint with the raw challenge plus an approved intent and a card.
Ovra mints a JWE-wrapped network token bound to the intent.Merchant decrypts and settles
Merchant uses its own private key (RSA-OAEP-256 + A256GCM) to unwrap the DPAN + cryptogram, then settles via its own acquirer.
High-level convenience: POST /v1/mpp/pay
For most agent code paths, you don’t want to orchestrate the round-trip yourself. The high-level endpoint does it all:
GETthe URL, expects402with an MPP challenge.- Mints a credential bound to your
intentId+cardId. - Retries the request with
Authorization: Payment <cred>. - Receives
Payment-Receipt, calls verify, writes the transaction.
Low-level: mint + verify
Error matrix
| Status | Code | Meaning |
|---|---|---|
| 400 | E_MPP_CRED_MALFORMED_CHALLENGE | Challenge unparseable |
| 400 | E_MPP_CRED_AMOUNT_MISMATCH | Intent amount ≠ challenge amount |
| 400 | E_MPP_CRED_MERCHANT_MISMATCH | Intent merchant ≠ challenge payTo |
| 400 | E_MPP_CRED_PAR_REQUIRED | PAR is mandatory but missing |
| 403 | E_MPP_CRED_INTENT_NOT_APPROVED | Intent not in approved state |
| 403 | E_MPP_CRED_INTENT_MISMATCH | Intent owner ≠ caller |
| 404 | E_MPP_CRED_MERCHANT_NOT_FOUND | No merchant registered for the challenge realm |
| 410 | E_MPP_CRED_INTENT_EXPIRED | Intent past expiresAt |
| 410 | E_MPP_CRED_CARD_CONSUMED | Single-use card already burned |
| 502 | E_UPSTREAM_ERROR | Card-issuer or PCI-proxy upstream failure |
application/problem+json) with type URIs invalid-challenge or verification-failed — never an oracle. Replays return 402 invalid-challenge regardless of the underlying cause.
Merchant onboarding
If you operate a merchant that wants to accept MPP, register viaPOST /v1/merchants with an invite code:
mer_sk_* to call /verify. The JWK validates as RSA-OAEP-256 + A256GCM only; downgrades are rejected at write time.
Webhooks
| Event | When |
|---|---|
mpp.credential.minted | Credential issued via /mint |
mpp.credential.consumed | Credential successfully verified |
mpp.credential.expired | Reserved (sweep is future work; expiry surfaces today via 410 from mint and 402 from verify) |
mpp.transaction.completed | Verified MPP transaction settled |
Sacred guarantees
- Zero card data in agent context. The credential envelope is a base64url-nopad JWE; only the merchant’s private key can decrypt it. Even if the agent logs the full mint response, no PAN/DPAN/cryptogram bleeds.
- Single-use. CAS consume on verify — replay returns 402.
- Bound to one intent. Reused intent IDs across challenges are rejected with
E_MPP_CRED_INTENT_MISMATCH.
Next
CUA
The other Pay mode — for merchants without MPP.
Pay overview
How MPP and CUA share one product narrative.
Intents
The approval primitive every credential binds to.
Webhooks
Subscribe to
mpp.* events for real-time updates.