Two ways to give an agent permission to pay
- ⬤ Built from your card / BNPL
- ⬤ Cancel via the card network
- ⬤ You approve it (SCA)
- ⬤ Revoke at your bank, anytime
My take For handing an AI agent authority to pay, Open Banking consent is the safer primitive: credential-blind, scoped, revocable, and holding no secret to leak. Cards still win on disputes (A2A has no chargeback), so use each for its job. The miss is making card rails the default while Europe’s purpose-built primitive sits unused.
One-line glossary
- Klarna APP
- Agentic Product Protocol: Klarna’s open standard for making products discoverable by AI agents. A protocol and product feed, not a mobile app.
- SCA
- a security check where you confirm the payment (bank app / face / code).
- Open Banking / PSD2
- EU law letting an approved app act on your account with your consent, via a standard bank API.
- RFC 9421
- HTTP Message Signatures — the agent signs its request with its own key so the bank knows which agent acted.
- BNPL
- Buy Now, Pay Later: pay in instalments (Klarna, Affirm).
Three identities — and why the app needs no separate human login
You — the user
Who is shopping?
No app account or password. You're identified by the mandate you grant at your bank — the agent carries it, so the page knows whose agent it is.
Login: none — via the mandateThe mandate — at your bank
What may be paid, from whose account?
Granted once via your bank's SCA — a scoped, revocable allowance. The app never sees your bank credentials.
Login: bank SCA · onceThe agent — the machine
Which agent is acting, for whom?
An issuer-attested credential bound to its key (RFC 7800); it signs each request (RFC 9421). No login page.
No login · cryptographicNo separate human login is needed: the page recognises the agent from its credential, and who it acts for from the mandate it carries. The only human step is the bank SCA that grants the mandate — that's where the user is established and authority to pay is given. One human moment (at the bank), no app password.
The gate verifies the agent — not just that it holds a key
An identity authority attests the trusted agent (RFC 7800 binds the credential to its signing key). Send each agent at the gate — only the issuer-attested one whose credential is bound to its key gets through. All decided by crypto, before any payment.
Pick an agent above to watch the gate verify it, step by step.
In production, the agent comes from outside
This shopping demo embeds an agent so it runs in one page. In reality an agent is a separate party: it holds its own key, and it never lives inside the merchant or the bank. The authority already treats it that way. It trusts an issuer-attested credential and the agent's own signature, not a key the server holds.
- 1Agent holds its own keyGenerated on the agent's machine. The server never sees the private key.
- 2Enrol for a credentialThe issuer attests the agent and binds the credential to that key (Know-Your-Agent).
- 3Authenticate from outsideThe agent signs each request (RFC 9421); the gate verifies the credential, then the signature.
python3 external_agent.py.
Have an external agent? Shop here.
The gate is public and credential-based, so any agent can transact against the live sandbox API at
agent-payment-authority.vercel.app. Where your agent runs does not matter; only what it
carries does. Here is what it brings and how it connects.
What your agent brings
- ① Its own Ed25519 keyGenerated on your machine. The private key never leaves it; only the public key is sent.
- ② An identity credentialEnrol the public key once; the issuer returns a credential bound to that key (RFC 7800 key-binding).
- ③ A signature on every requestEach call is signed with your key (RFC 9421) and carries the
credential in the
X-Agent-Identityheader. - ④ A scoped mandateYour human authorises a spending allowance once at the bank (one SCA). After that the agent pays with no re-SCA, within cap, use-count and expiry.
Prerequisites: Python 3 with the cryptography package and outbound HTTPS.
No account, no API key, no login page.
How it connects
- 1Enrol ·
POST /agent/enrollSend your base64url public key; receive a keyid and an issuer-attested credential. - 2Authenticate ·
POST /agent/verifySend an RFC 9421-signed request plus the credential. The gate verifies identity, then the signature → ALLOW. - 3Get a mandate ·
POST /agent/mandateReturns a bank authorisation URL; your human completes one SCA (test_authorised+ any 3 digits). - 4Pay ·
POST /agent/payThe agent draws real sandbox payments off the mandate, each signed, with no further approval.
Run the reference agent from your own machine:
python3 external_agent.py https://agent-payment-authority.vercel.app
It generates a fresh key, walks all four steps, waits for the one-time SCA, then draws a live sandbox payment. A rogue that presents a stolen credential but signs with a different key is denied at the signature check, before any bank call.
The same trust model the card networks use, on Open Banking rails
Verifiable Intent (Mastercard) and Google AP2 bind a human’s intent to an agent’s action with a layered SD-JWT chain (RFC 7800 key-binding plus selective disclosure): Layer 1 credential provider → user, Layer 2 user → agent (the mandate and its constraints), and Layer 3 the agent’s execution, split into a payment credential (L3a) and a checkout credential (L3b). The spec defines two modes: Immediate (the user confirms the final values) and Autonomous (the user sets constraints and the agent runs on a delegated key).
This demo issues spec-conformant Verifiable Intent credentials
(Apache 2.0): ES256, the spec’s vct and typ, KB-style layer binding,
delegate_payload, and the L3a/L3b cross-binding — verified to parse and verify with the
official reference decoder. Layer 2 (human intent) is met by a bank SCA and it
settles over Open Banking instead of cards.
Read the spec →
Build the chain to see L1 → L2 → L3a/L3b, signed and key-bound.
🏦 Network sees · L3a payment
🛍️ Merchant sees · L3b checkout
Selective disclosure: the network never sees the cart; the merchant never sees the payment account.
Open Banking consent authority
Scoped · SCA-backed · revocable · credential-blind
- TPP creates a scoped consent (cap + single payee + expiry)
- PSU completes SCA directly at the bank
- Agent pays within scope (bank enforces)
- Agent tries over cap → bank denies
- PSU revokes → token dies
authority token: not issued yet
Payment-network token
Stripe SPT / Mastercard Agentic Token · card + BNPL
- Token minted from a tokenised card / BNPL credential
- Authentication delegated to issuer/network
- Merchant + amount scoped (network-defined)
- Revocation via issuer/network, not the bank
- Carries a derived credential
token: not minted yet
Side by side
| Dimension | Open Banking consent | Network token | Why it matters |
|---|---|---|---|
| Credential exposure | None: token carries no PAN/secret/login | Derived from a tokenised card PAN / BNPL line | An agent holding no credential can't leak one. |
| Authentication | PSU does SCA directly at the bank | Delegated to issuer/network at provisioning | SCA keeps a human in the loop for the mandate. |
| Scope | Explicit: amount cap + single payee + expiry | Merchant + amount (network-defined) | Per-payment scope limits blast radius of a rogue agent. |
| Revocation | PSU, anytime, at the bank dashboard | Issuer/network: no direct PSU bank-side kill switch | The payer can pull authority instantly. |
| Dispute / chargeback | Weak: A2A has no chargeback; PSR refund is fraud-only | Strong: card scheme chargeback rights | THE honest counterpoint: cards win on buyer protection. |
| Rails | Account-to-account (SEPA / instant) | Card network + BNPL | Different settlement, different economics. |
One row keeps cards ahead: dispute / chargeback (A2A has none; the PSR refund is fraud-only). Everywhere authority itself is concerned (credentials, scope, revocation, who authenticates), the consent column is stronger. That’s the column Europe already ships, and the one agentic commerce is walking past.