Skip to main content
MPP is the Machine Payments Protocol: an IETF draft (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

1

Merchant returns 402

The challenge body declares amount, currency, payee, expiry, and resource URL.
2

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.
3

Agent presents the credential

Agent retries the request with Authorization: Payment <credential>.
4

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.
5

Merchant returns Payment-Receipt

The receipt header is the canonical record of settlement.
6

Agent verifies

Agent calls POST /v1/mpp/credentials/:id/verify (or /by-challenge/:challengeId/verify) — Ovra runs the CAS consume, drives the intent FSM to completed, writes the transactions row with rail = 'mpp', fires mpp.transaction.completed.

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:
What it does:
  1. GET the URL, expects 402 with an MPP challenge.
  2. Mints a credential bound to your intentId + cardId.
  3. Retries the request with Authorization: Payment <cred>.
  4. Receives Payment-Receipt, calls verify, writes the transaction.
Response (200):

Low-level: mint + verify

Error matrix

Verify failures use RFC 9457 Problem Details (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 via POST /v1/merchants with an invite code:
Response (one-shot reveal, save it):
Use mer_sk_* to call /verify. The JWK validates as RSA-OAEP-256 + A256GCM only; downgrades are rejected at write time.

Webhooks

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.