-
-
ProofPay: escrow for freelance software work, verified by AI and held by PayPal.
-
AI turns the client's brief into acceptance criteria, each checked against the code or the CI run.
-
The AI verdict: every criterion passed, each with a reason, the evidence and a confidence.
-
A human admin approves the release. The AI drafts; it never moves money.
-
Released: PayPal captured the hold and paid the freelancer. Every step is on the audit timeline.
-
The payout arrives in the freelancer's PayPal sandbox account.
Inspiration
Freelancers do the work and don't get paid. Clients pay and get work that doesn't do what was asked. Escrow solves half of this: it keeps the money safe. But someone still has to decide whether the work is actually done, and that decision is slow, subjective and easy to argue about. For software, though, "done" can often be checked: does the code do what the brief said, and do the tests pass? That is a job AI can do quickly and explain clearly.
What it does
ProofPay is escrow for freelance software work, built on PayPal.
- Agree. The client describes the job in plain language. AI turns the brief into acceptance criteria that can each be checked against the code diff or the CI run. The criteria freeze once the job is funded.
- Fund. The client pays with PayPal. The payment is authorized, not captured: PayPal holds the money and nothing is charged yet.
- Verify. The freelancer submits a GitHub pull request. AI checks it against every criterion and gives a reason, the evidence and a confidence for each.
- Release. A human admin approves. PayPal captures the hold, in full or in part, and pays out to the freelancer's PayPal account.
- Defend. A dispute copilot drafts rulings for appeals inside the platform and evidence for PayPal disputes, using the job's audit trail. An admin edits and submits.
The rule throughout: AI drafts, people approve, PayPal moves the money. No model output can move money by itself.
How I built it
- PayPal: the Orders API with
intent=AUTHORIZEfor the hold, the Payments API withfinal_capturefor full or partial release, void for refunds, Payouts to pay the freelancer, the Disputes API for evidence and accept-claim, and signature-verified webhooks. Every money call carries a stablePayPal-Request-Id, so retries are safe. - PayPal MCP server: the dispute copilot is an agent that investigates through PayPal's official MCP server. It gets five read-only tools (orders, disputes, transactions, shipment tracking) and nothingthat can move money.
- AI: Google Gemini through the Vercel AI SDK, with structured output. The provider is pluggable, so Claude works with one environment variable.
- Guard rails in code: CI results are judged in code, the overall verdict is computed in code, andanything uncertain goes to a human.
- App: Next.js 16, React 19, TypeScript, PostgreSQL with Drizzle. A job state machine makes illegalmoney moves fail loudly. Hosted on Render.
Challenges I ran into
- Choosing the escrow model. Capturing first and paying out later means "held" is only a database flag. Authorize-then-capture makes the hold real and visible in PayPal, and a partial capture mapsdirectly onto a partial release. The cost is the authorization lifetime, so long jobs renew the hold.
- Giving an agent PayPal tools safely. PayPal's agent toolkit pinned an older AI SDK version thanthe app uses. Running the official MCP server as a separate process with a tool allowlist solved the version problem and kept the agent read-only.
- AI you can't fully rely on. The model provider was sometimes busy, and an early version left jobs stuck when a call failed. Every AI call now has a timeout, failures are recorded, either party canretry, and an admin can take a job over manually.
- Sandbox behaviour. Disputes take a while to appear in the API, payouts are accepted first andsettled later, and a balance total can lag behind the activity list. I added a manual sync for disputes and learned to verify money by the transaction, not the total.
Accomplishments that I'm proud of
- A real PayPal hold, capture and payout driven end to end by an AI verdict and a human approval,working on a live deployment.
- Verdicts that explain themselves: each criterion shows a reason, the evidence and a confidence, so arejection is something you can argue with.
- A dispute copilot that can investigate but cannot act, with the boundary enforced by which tools it is given, not by a prompt.
What I learned
- Authorization holds are an underused building block: they give escrow-like behaviour without the platform taking custody of the money first.
- The safest way to use an AI agent around payments is to separate reading from writing completely. The model reads and drafts; code and people write.
- Deterministic checks should come first. Letting code decide what code can decide (CI passed or failed) makes the AI's judgement smaller and more trustworthy.
What's next for ProofPay
- Private repositories and other kinds of deliverable beyond pull requests.
- Automatic fallback to a second model when the first is unavailable.
- Tracking payouts to completion and showing a denied payout on the job.
- A multiparty PayPal setup, or a licensed escrow partner, for production use.
Built With
- drizzle-orm
- gemini
- github-api
- model-context-protocal
- next.js
- paypal
- paypal-disputes
- paypal-mcp
- paypal-order-api
- paypal-payouts
- paypal-webhooks
- postgresql
- react
- render
- typescript
- vercel-ai-sdk
- zod