Inspiration

In 2025, people 60 and over reported losing $7.7 billion to online fraud, in 201,266 complaints to the FBI (FBI IC3 2025 Internet Crime Report). Many of these scams work by borrowing someone's trust: a grandchild in trouble, a bank, PayPal itself. They add urgency and secrecy so the victim doesn't check with anyone.

Most of today's protections guess. Bank fraud models score the payment, scam checkers score the message, and when a bank calls to confirm, it calls the sender, who is the one being fooled. Detection alone is an arms race: every new script has to be recognised. We wanted to break the trick itself. A scammer can copy a grandson's voice and story, but can't answer from the real grandson's phone. So we ask him.

What it does

Trust Circle is a protected way to send money with PayPal. It's a working reference for a setting PayPal could offer on every account, built only on PayPal's public APIs and running in the sandbox.

  • Check a message. Paste a text, or add a screenshot or a voice note. A voice note is turned into words with Groq Whisper; the audio is never kept. Groq judges it and explains, in plain words, what gave the scam away. Meta's Prompt Guard screens the text for instructions aimed at the AI first. If a message claims to be someone in the circle but comes from a number that isn't theirs, it says so first: "It came from +1 (415) 555-0199, not Daniel's number."
  • Guarded send. Each payment is assessed by rules in code and then by the AI. The AI can raise the risk level, never lower it, and if it's unavailable the payment is held. A high-risk payment can still go ahead, but it is only authorised in PayPal and held. The sender feels they've "done it", so the pressure is off, yet the money hasn't left.
  • Ask the real person. When the sender says "my grandson Daniel asked", the AI identifies who is being impersonated. If Daniel is in the circle, he gets "Did you just ask Margaret for $800?" One tap on It wasn't me voids the authorisation. For a claimed bank or PayPal support, the app shows official routes and keeps the hold. In the remote-access "refund" scam, where a caller claiming to be a company controls the sender's computer and shows a fake balance, the payment is always held, the first step is to end the connection, and with a circle, the decision is made on someone else's phone, which the scammer can't touch.
  • Safe word and memory challenge. If the real person doesn't answer in 10 minutes, the sender is coached to ask the caller for the safe word or a memory question. The challenge is one-way: a wrong answer or an excuse stops the payment, and a right one never releases a high-risk payment by itself.
  • The circle decides. A trusted contact (Sarah, the daughter) can stop or approve. Approve captures the authorisation and pays the payee out with PayPal Payouts. If nobody decides, the sender can release it after a cooling-off period (24 hours by default), and the hold is voided after 72 hours.
  • A shared scam list that learns. A payee confirmed as a scam (stopped by a contact, denied by the real person, or reported by two people) is high risk for everyone. The AI writes an anonymised description of each reported script, embedded locally and matched in pgvector, so reworded versions are caught too. Trends are charted with AG Charts.
  • Aftercare. An agent built on PayPal's Agent Toolkit reviews the sender's recent payments for anything the earlier checks missed. For a completed payment to a now-confirmed scammer, it drafts a dispute the family copies and sends. Its PayPal tools are read-only (list_transactions and get_order, scoped in code to that sender), so the money moves only through the hold, void and capture the circle decides.
  • Family, Business and Solo presets, push alerts, an installable app, and a dashboard in AG Grid and AG Studio showing money protected, scams stopped and, for each payment, whether PayPal's own record matches ours ("PayPal says").

How we built it

  • Next.js 16 (App Router, TypeScript), installable as a PWA with web push.
  • PayPal: Orders v2 with AUTHORIZE intent, approval in the JavaScript SDK v6, then authorize, capture or void, Payouts, refunds when a payout fails, and webhooks verified online with verify-webhook-signature and stored once per event id. Every money-moving PayPal call carries a PayPal-Request-Id, so retries can't move money twice. The aftercare agent uses @paypal/agent-toolkit, cut down to a read-only allow-list.
  • AI: Groq for the text and vision judgements, the aftercare tool loop and the pattern descriptions; meta-llama/llama-prompt-guard-2-86m on Groq as an injection screen; all-MiniLM-L6-v2 running inside the server for embeddings, stored in pgvector.
  • Money safety: a payment state machine (created → approved → authorised → held → released → captured → paid_out, with blocked, expired, voided, payout_failed and refunded). Each decision is claimed in the database before PayPal is called, and a scheduled sweep finishes anything interrupted.
  • Hosting: Render free web service, Neon free Postgres with pgvector, and GitHub Actions schedules for hold expiry and a daily demo reset.
  • Testing: Vitest unit and integration tests, Playwright end-to-end stories against the real sandbox, a production smoke test, and a live evaluation on 79 labelled cases, with a rules-only comparison.

Challenges we ran into

  • Never pay twice. Between capture, payout and refund there are many ways for a retry to move money twice. We made decisions claim their state first, gave every PayPal call a request id, refused to refund after an uncertain payout, and built a sweep that finishes interrupted payments.
  • Telling the truth on screen. Early screens said things like "Sarah has been told" before any alert existed. We made a rule that every line must be backed by something that really happened, and added the alerts to make those lines true.
  • AI you can't talk down. Scam messages can contain instructions aimed at the AI. Rules set a floor the AI can't lower, Prompt Guard flags injected instructions, and the aftercare agent can only call two read-only tools on one person's data.
  • Pattern matching without a paid service. We first planned Elastic, but a trial would expire before judging, so we moved to pgvector with a local MiniLM model. It catches reworded scams, but it also raised false alarms, which we report.
  • Free-tier hosting. Render's free service has no cron, so expiry runs from a GitHub Actions schedule that also pings the service. GitHub runs these schedules far less often than asked (hours apart, not every few minutes), so the first load after a quiet spell can take about a minute.

Accomplishments that we're proud of

  • The whole lead story works end to end on real sandbox money movement: check, send, hold, Daniel says "It wasn't me", the authorisation is voided and the scammer goes on the shared list.
  • On 79 hand-written cases, all 43 scams were flagged and held, and 1 of 36 genuine cases was held (a business payment the scam-pattern matcher flagged). The AI earns its place: on the same payments, rules alone hold at best 17 of 23 scams while holding 7 of 20 genuine ones, and miss every scam that uses an everyday amount or a payee already paid. We publish the cost too: 11 of 36 genuine cases got a warning, mostly large first payments to new payees.
  • Calm, blame-free screens with large type and big tap targets, checked with an automated accessibility pass.

What we learned

  • Asking the impersonated person is a stronger check than any classifier, and it gets stronger as scams get better.
  • Holding an authorisation, rather than refusing a payment, removes the urgency without pushing the victim to another way of paying.
  • The AI decides which payments must wait, and PayPal then holds, voids or captures them for real (in the sandbox). Its power is one-way: it can raise risk but never lower it, and it never releases money by itself.

What's next

Trust Circle is meant to become a setting, not another app. A scammer can always tell a victim to pay somewhere else, so protection has to live where people already pay. Everything here runs on PayPal's public APIs (authorise and hold, void, capture, Payouts and webhooks), so PayPal could offer it as a "Trusted Contact" option on any account: name someone you trust, and risky payments wait for them before the money leaves.

The idea has precedent. In US brokerage, firms must make reasonable efforts to collect a trusted contact for each customer (FINRA Rule 4512), and may place a temporary hold on a disbursement when they reasonably believe an adult 65 or older is being financially exploited, telling that trusted contact within two business days (FINRA Rule 2165). Trust Circle brings the same protection to everyday payments, with AI deciding which payments need a second look.

A small-business version is next. The same engine already runs a Business preset, where a freelancer's accountant reviews risky payments, and it catches the invoice and CEO-fraud cases in our tests. Building it out means AI prompts written for a business rather than for an older person, a step that checks new bank details with the supplier on a number already on file, and a demo story of its own.

  • A real sign-up flow with an emailed one-time code, in place of demo mode.
  • Reconciling more "already done" PayPal answers, and a clear path for payments that need a person's attention.
  • Link inspection in a sandboxed browser.
  • Tuning the scam patterns to cut false alarms on everyday payments.
  • Working with PayPal on the native setting, so holds and reviews run under PayPal's own licence and dispute processes.

Built With

  • ag-charts
  • ag-grid
  • ag-studio
  • apimatic
  • drizzle-orm
  • groq
  • llama-prompt-guard
  • neon
  • next.js
  • paypal-agent-toolkit
  • paypal-javascript-sdk
  • paypal-orders-api
  • paypal-payouts
  • paypal-server-sdk
  • paypal-webhooks
  • pgvector
  • playwright
  • postgresql
  • qwen
  • react
  • render
  • tailwind-css
  • transformers.js
  • typescript
  • whisper
Share this project:

Updates