Inspiration

I'm a tutor. After a session, there are times I know the student really got it, and times I'm not sure anything stuck, but I'm paid exactly the same either way. Parents pay by the hour and simply hope it's working. Nobody measures the one thing everyone is paying for: did the student actually learn?

As a tutor, I wanted a way to prove my teaching works, and to be rewarded when it does. As a parent's or student's money, it should only go to learning that actually happened.

PayPal's authorize-and-capture flow made that possible. Hold the money at booking, and release it once there's proof of learning. That became Gained: tutoring where you pay for what's learned, not for the hour.

How we built it

A family books a tutor, and PayPal places a hold for the full price; nothing is charged yet. AI writes a short warm-up quiz before the session and a fresh quiz right after it, based on what the tutor taught. Two days later, a check-in quiz shows what stuck.

The tutor gets a guaranteed 80% base, plus up to a 20% bonus based on how much the student improved. Anything unearned goes back to whoever paid, automatically. We measure improvement with normalized gain, the share of the room left to improve that the student actually covered:

$$ g = \frac{\text{post} - \text{pre}}{100 - \text{pre}}, \qquad \text{Tutor pay} = \text{price} \times \left(0.80 + 0.125\, g_{\text{quiz}} + 0.075\, g_{\text{retention}}\right) $$

For a \(\$50\) session where a student goes from 40% to 80%, then holds 70% two days later, the tutor earns \(\$46.04\) and \(\$3.96\) goes back to the family.

Stack

  • PayPal Orders v2 (intent: AUTHORIZE): a partial capture for the base, a final capture for the bonus (which releases the rest), voids for cancellations, and PayPal Payouts to tutors.
  • Claude through Elastic's managed AI: it writes the quizzes, works out what was covered, grades written answers and powers the tutor dashboard assistant. Every response is checked against a strict schema.
  • Next.js 16, Postgres and Prisma, hosted on Render, with Brevo for email and Bryntum calendars for booking.
  • All money in integer cents, so the base, bonus and refund always add up to the exact price.

Challenges we ran into

  • Holding money correctly. A PayPal hold only stays fresh for 3 days, but our flow runs longer: a session, a 48-hour check-in, then a 72-hour appeal window. We reauthorize exactly once, right before capturing, and void the hold on cancellation, so money never gets stuck.
  • Making AI fair enough to decide pay. A second AI pass checks every quiz. Multiple-choice and number answers are graded in code, not by AI, and anyone can appeal a grade to a human.
  • Moving all AI onto Elastic. It only accepts text, so we dropped audio recordings and photo uploads and wrote quizzes from the tutor's summary instead. That also meant collecting less data about kids.
  • Sandbox confusion. We had to learn which sandbox account is the merchant, which one pays, and which one receives the tutor's payout.
  • Free hosting that sleeps. Our host spins down after 15 idle minutes. A scheduler now pings the site every 10 minutes, which keeps it awake and runs the payment jobs on time.

What we learned

  • PayPal's authorize-and-capture flow is more than a payment. It lets money wait for an outcome.
  • AI should only move money when it's checked: schemas, a second review, code-based grading where possible, and a human appeal path.
  • Trust comes from clarity. Showing families where their money is at every step mattered as much as the AI did.

Built With

Share this project:

Updates

Submission history