Zum Hauptinhalt springen

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.

MPP ist das Machine Payments Protocol: ein IETF-Draft (draft-httpauth-payment-00, co-authored Tempo Labs + Stripe, siehe paymentauth.org) der HTTP 402 Payment Required in eine echte, maschinenlesbare Challenge verwandelt. Ovra implementiert die card-Methode als Credential-Issuer. Wenn ein Merchant WWW-Authenticate: Payment ... returnt, kann dein Agent zahlen — ohne ein Formular zu rendern, einen Browser zu öffnen oder eine Kartennummer zu sehen.
Code-complete (Phase 7). Sandbox-only End-to-End. Das Credential-Envelope ist ein echtes JWE; Merchants liefern in ihrem MPP-Onboarding einen Private Key zum Entschlüsseln.

Wire-Flow

1

Merchant returnt 402

HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment challenge="<base64-json>"
Der Challenge-Body deklariert Amount, Currency, Payee, Expiry und Resource-URL.
2

Agent mintet Credential

Agent ruft POST /v1/mpp/credentials/mint mit der rohen Challenge plus genehmigtem Intent und einer Karte. Ovra mintet ein JWE-wrapped Network-Token gebunden an den Intent.
3

Agent präsentiert Credential

Agent wiederholt den Request mit Authorization: Payment <credential>.
4

Merchant entschlüsselt und settlet

Merchant verwendet eigenen Private Key (RSA-OAEP-256 + A256GCM) zum Unwrap von DPAN + Cryptogram, settlet via eigenen Acquirer.
5

Merchant returnt Payment-Receipt

Der Receipt-Header ist der kanonische Settlement-Record.
6

Agent verifiziert

Agent ruft POST /v1/mpp/credentials/:id/verify (oder /by-challenge/:challengeId/verify) — Ovra führt CAS-Consume aus, treibt Intent-FSM auf completed, schreibt transactions-Row mit rail = 'mpp', feuert mpp.transaction.completed.

High-Level-Convenience: POST /v1/mpp/pay

Für die meisten Agent-Code-Pfade willst du den Roundtrip nicht selbst orchestrieren. Der High-Level-Endpoint macht alles:
curl -X POST https://api.getovra.com/v1/mpp/pay \
  -H "Authorization: Bearer $OVRA_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "url": "https://shop.example.com/api/orders",
    "intentId": "int_...",
    "cardId": "ca_..."
  }'
Was er tut:
  1. GET die URL, erwartet 402 mit MPP-Challenge.
  2. Mintet eine Credential gebunden an intentId + cardId.
  3. Wiederholt den Request mit Authorization: Payment <cred>.
  4. Empfängt Payment-Receipt, ruft Verify, schreibt die Transaktion.
Response (200):
{
  "credential_id": "mppc_a1b2c3...",
  "merchant_status": 200,
  "receipt": "eyJ2ZXJzaW9uIjoiMSIs...",
  "merchant_body": { "order_id": "ord_42" }
}

Low-Level: Mint + Verify

curl -X POST https://api.getovra.com/v1/mpp/credentials/mint \
  -H "Authorization: Bearer $OVRA_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "challenge": "Payment challenge=\"eyJ2ZXJzaW9uIjoiMSIs...\"",
    "intentId": "int_...",
    "cardId": "ca_..."
  }'

Error-Matrix

StatusCodeBedeutung
400E_MPP_CRED_MALFORMED_CHALLENGEChallenge nicht parsbar
400E_MPP_CRED_AMOUNT_MISMATCHIntent-Amount ≠ Challenge-Amount
400E_MPP_CRED_MERCHANT_MISMATCHIntent-Merchant ≠ Challenge-payTo
400E_MPP_CRED_PAR_REQUIREDPAR ist mandatory aber fehlt
403E_MPP_CRED_INTENT_NOT_APPROVEDIntent nicht in approved-State
403E_MPP_CRED_INTENT_MISMATCHIntent-Owner ≠ Caller
404E_MPP_CRED_MERCHANT_NOT_FOUNDKein Merchant für die Challenge-Realm registriert
410E_MPP_CRED_INTENT_EXPIREDIntent jenseits expiresAt
410E_MPP_CRED_CARD_CONSUMEDSingle-use-Card bereits verbrannt
502E_UPSTREAM_ERRORCard-Issuer- oder PCI-Proxy-Upstream-Failure
Verify-Failures nutzen RFC-9457 Problem Details (application/problem+json) mit Type-URIs invalid-challenge oder verification-failed — niemals ein Oracle. Replays returnen 402 invalid-challenge egal welche Underlying-Cause.

Merchant-Onboarding

Wenn du einen Merchant betreibst der MPP akzeptieren möchte, registriere via POST /v1/merchants mit Invite-Code:
curl -X POST https://api.getovra.com/v1/merchants \
  -H "Authorization: Bearer $OVRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inviteCode": "INVITE-2026-...",
    "name": "Acme Shop",
    "encryptionJwk": { "kty": "RSA", "alg": "RSA-OAEP-256", "use": "enc", ... },
    "webhookUrl": "https://shop.acme.com/ovra/webhooks"
  }'
Response (One-Shot-Reveal, speichern):
{
  "id": "mer_...",
  "slug": "acme-shop",
  "merchant_secret_key": "mer_sk_a1b2c3...",
  "warning": "Save merchant_secret_key now — it will not be shown again."
}
mer_sk_* zum Aufruf von /verify verwenden. Der JWK validiert ausschließlich als RSA-OAEP-256 + A256GCM; Downgrades werden zur Write-Time abgelehnt.

Webhooks

EventWann
mpp.credential.mintedCredential via /mint ausgestellt
mpp.credential.consumedCredential erfolgreich verifiziert
mpp.credential.expiredReserviert (Sweep ist Future Work; Expiry surfaced heute via 410 von Mint und 402 von Verify)
mpp.transaction.completedVerifizierte MPP-Transaktion settled

Sacred Guarantees

  • Null Card-Data im Agent-Kontext. Das Credential-Envelope ist eine base64url-nopad JWE; nur der Private Key des Merchants kann sie entschlüsseln. Selbst wenn der Agent die volle Mint-Response loggt blutet kein PAN/DPAN/Cryptogram.
  • Single-use. CAS-Consume bei Verify — Replay returnt 402.
  • Gebunden an einen Intent. Wiederverwendete Intent-IDs über Challenges hinweg werden mit E_MPP_CRED_INTENT_MISMATCH abgelehnt.

Weiter

CUA

Der andere Pay-Modus — für Merchants ohne MPP.

Pay-Übersicht

Wie MPP und CUA ein Produktnarrativ teilen.

Intents

Die Approval-Primitive an die jede Credential bindet.

Webhooks

mpp.* Events für Echtzeit-Updates abonnieren.