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 APIrefund 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:
- 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. - 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
Log in or sign up for Devpost to join the conversation.