Inspiration

AI agents are starting to buy things for people. That raises a question nobody can answer today: when an agent buys the wrong thing, who decides it was wrong? The buyer says they never asked for it, the store says they did, and PayPal has to guess. Honest people lose either way. We wanted the buyer's intent to be a record that travels with the payment.

What it does

  • The buyer signs their limits. They say what they want ("white trainers, size 10, under $110, within two weeks"), by typing or by voice. AI turns it into structured limits, and the buyer signs them as a mandate with their own key.
  • Every cart is checked before PayPal is touched. A shopping agent picks real products inside those limits (the store sells 25 products from five seller brands), or the buyer browses. A cart guard checks every cart against the mandate: hard limits are plain code, and AI only settles the unsure matches.
  • Pay with PayPal or a card (PayPal Card Fields, with 3-D Secure when needed). A receipt hash ties the mandate, cart and payment together.
  • Problems are handled in two steps. The buyer can report a problem and the store can reply or refund directly. If it becomes a PayPal dispute, an AI analyst reads the signed mandate, the cart and the payment (including whether the buyer's own PayPal account paid) and recommends a response with the evidence it relied on.
  • An MCP server lets any outside AI agent shop for a buyer inside the mandates they signed. It can list products, test baskets against the guard and create the PayPal order, but it can never sign a mandate or pay. The buyer approves in PayPal.
  • A person always decides. Code rules override anything unsafe (an action PayPal does not allow, a second refund, a different payer, prompt injection in the buyer's text). A person approves everything before it goes to PayPal: a message with the evidence PDF, an offer, a refund, or accepting the claim.

How we built it

Next.js 16 and TypeScript, Postgres on Neon, deployed on Vercel.

PayPal: Orders v2, Card Fields and Smart Buttons, Payments refunds, the Customer Disputes API (list, show, send message, provide evidence, make offer, accept claim), verified webhooks, and Log in with PayPal for payer matching.

AI: Gemini (with Claude and Grok behind the same interface) for mandate drafting, the shopping agent, fuzzy cart checks and the dispute analyst.

Mandates are Ed25519 JWS with a per-buyer encrypted key. Every API has a Zod contract, 339 automated tests pass, and the analyst is scored on a labelled set of 28 disputes.

Challenges we ran into

  • PayPal only lets a seller take certain actions at each dispute stage, so the analyst's recommendation is reconciled with the actions PayPal currently offers (for example, at the inquiry stage the evidence goes as a message, not an upload).
  • A payment can be refunded outside the app, so we re-read refunds from PayPal and never refund twice.
  • Keeping the model honest: it only proposes, code decides what is allowed, and the buyer's own words are treated as untrusted data.
  • Raising the analyst from 36% (our first 25-case set) to 79% (the current 28-case set) by changing the policy and the prompt, and measuring each change instead of guessing.

Accomplishments that we're proud of

A full loop with no canned data: real sandbox orders, real sandbox disputes, real refunds. An analyst that is measured, with guardrails that do not depend on the model. A buyer experience with voice input, and a store experience built around what needs a person. An MCP server that proves the idea works with agents we did not build.

What we learned

In agentic commerce the hard part is not letting the agent buy, it is being able to explain afterwards why it was allowed to. A signed, checkable record makes that cheap.

What's next

Email and push notifications for dispute deadlines, a second analyst pass for the unclear cases, OAuth for remote MCP connectors, and the move from sandbox to PayPal live.

Try it

Live: https://mandate-pay.vercel.app (PayPal sandbox, no real money moves). Testing steps and sample accounts are in the testing instructions field.

Built With

Share this project:

Updates

Submission history