Inspiration

PayPal's hackathon asks for "what's next with PayPal and AI" — and the most useful thing an AI layer can do with money is not to be trusted with it. Most generative demos I had seen let the model roam freely over a payment API. PayPilot starts from the opposite constraint: the model never touches money.

What it does

PayPilot turns one sentence into a real PayPal operation:

  • charge $25 for the API design review → POST /v2/checkout/orders, and it hands back a live approval link
  • the buyer approves in the real PayPal checkout, PayPal redirects to /return, and PayPilot captures the order
  • send $20 to [email protected] → Payouts API
  • refund capture 4N720427W8450252W → Refunds API

The UI shows what the model thought — action, amount, currency, receiver, confidence, and whether it came from the LLM or the rule fallback — right next to the raw PayPal response. Nothing hides behind a spinner.

How I built it

Two layers, one contract:

  1. Intent layer. An LLM (any OpenAI-compatible endpoint) returns a strict JSON intent. The output is normalised before it is used: synonyms (send → payout, complete → capture_order), field aliases (recipient/to → receiver, order_id → reference), numbers to strings, and fenced or chatty replies are salvaged.
  2. Money layer. A deterministic router validates the intent (a charge needs an amount, a payout needs a receiver, a refund needs a capture id) and calls PayPal. Every write carries a PayPal-Request-Id, so a retry cannot double-charge.

If the LLM is unreachable a rule-based parser takes over, so the app keeps working with no API keys — which is also how the test suite runs offline (11 tests, no network).

The order payload carries application_context.return_url / cancel_url, so the buyer journey closes properly: approve → redirect back → server-side capture.

Challenges

  • The sandbox checkout turned out to be the hard part, which was a genuine surprise. PayPal's checkout is a single-page app: it only renders once its tab is actually in front, and it silently ignores a click on the pay button while the layout is still settling. The fix was to poll until the button's bounding box stops moving, re-measure immediately before clicking, and verify by URL afterwards instead of trusting the click.
  • Never let the model be the last word on money. The routing layer had to be boring and testable: intent in, validated API call out. Refusing an ambiguous request ("charge" with no amount) is a feature, not a gap.

Accomplishments

Everything in the demo video is real sandbox traffic: order 5EA941833H521112A → APPROVED (payer = the sandbox buyer) → capture 4A121993N1219260E → COMPLETED → refund 35C846144T923481T → COMPLETED, and a payout batch 3G7RX8YFYTAHG ending SUCCESS for $20.00 with a $0.40 fee. The demo runs end to end in under two minutes and the code is MIT licensed.

What I learned

The hard part of "AI + payments" is not the prompt, it is the boundary. A model can be creative about what should happen, and must be completely predictable about how it happens. Put the flexibility in the parser, keep the executor deterministic and idempotent — and make the failure path as visible as the happy path.

What's next

  • a dry-run mode that answers "what would this sentence do?" before any API call
  • webhook-driven capture instead of relying on the browser redirect
  • an approval step that shows the parsed intent and the amount side by side before money moves

Built With

Share this project:

Updates

Submission history