Inspiration
I kept thinking about how freelance payments actually go wrong. The client pays upfront and gets nothing back, or the freelancer does all the work and waits weeks to be paid. And when there's an argument, everyone is going off memory and screenshots.
So I asked myself what would happen if the money just sat on hold until the work was proven. PayPal already lets you reserve a payment without spending it. I wanted to add something that checks the work, and a record that neither side can quietly change afterwards.
What it does
Vouchsafe is a small app with two kinds of accounts, buyer and freelancer. A payment passes through four stops, and I built the interface around following the coin from one to the next.
Gate. Before any money moves, a few simple rules decide if the payment is allowed: a budget, a limit per payment, a list of approved payees, and a human sign-off for bigger amounts. The AI can add a warning here, but it never makes the decision. I didn't want a model deciding who gets paid.
Vault. The buyer writes down the job and what "done" means, then funds it. PayPal holds the money. It's reserved, but nobody has been charged yet.
Seal. The freelancer submits a public GitHub repo. Gemini reads the code and checks every requirement one by one, and says what passed and why.
- If everything passes, the full amount is paid.
- If at least half passes, the freelancer is paid for that share and the rest goes back to the buyer.
- If less than half passes, they get one chance to revise. If it fails again, the hold is released and nobody is charged.
Defense. If there's a dispute, the app pulls together a timeline from the receipts and drafts a reply for you.
Every step is written to a receipt log where each entry includes a fingerprint of the one before it. If someone edits an old record, the chain breaks and it shows. I also put the latest fingerprint in the note on the PayPal payment, so the payment points back to its own proof.
How we built it
The backend is FastAPI with SQLite, and the frontend is React with Vite. For PayPal I used the Orders API (authorize, then capture or void), Payouts, and webhook signature checks, all on the free sandbox. Gemini's free API does the checking, and the code can also switch to Groq or Anthropic if you give it a key.
Accounts have hashed passwords and sessions, and each person only sees their own jobs. The app has no demo mode and no fake data. Everything you see comes from real sandbox calls.
Challenges we ran into
- PayPal's approval page kept sending me in a loop. It turned out the order needed a return and a cancel URL.
- I tried to take the money before the buyer had approved it and got an
ORDER_NOT_APPROVEDerror. The app now waits and shows where things really stand. - I told myself that 1 passing requirement out of 5 would pay 20%. It doesn't, because the real rule is 50%. I fixed the rule text in the app so it can't mislead anyone.
- The dispute draft once quoted an older receipt instead of the latest one. I fixed that and added a test for it.
- After I renamed my project folder, my Python environment quietly broke. I rebuilt it.
Accomplishments that we're proud of
- I ran the whole flow on the PayPal sandbox: a held payment, buyer approval, an AI check of a real repo, and a partial payment of $66.67 for 2 of 3 requirements passing.
- The receipt fingerprint ends up on the PayPal payment itself, so the proof travels with the money.
- The AI never decides who gets paid. Rules decide, and the AI only checks and explains.
- It has real accounts, with a buyer and a freelancer using separate logins, and 65 automated tests.
What we learned
Holding money and judging work are two separate steps, and keeping them apart is what makes this safe. I also learned to let rules make the decisions and let the AI only advise. And a receipt log only matters if people can check it themselves.
What's next for Vouchsafe
Storage that survives restarts on the hosted version, a real-money mode with PayPal live credentials, and checks for more than GitHub repos.
Built With
- fastapi
- framer-motion
- gemini-api
- javascript
- paypal
- paypal-payouts
- paypal-rest-api
- python
- react
- render
- sqlite
- vercel
- vite