Inspiration

It started with a text message about money that never arrived.

My brother got an SMS that looked like it came from his bank, saying ₹50,000 had been credited to his account. Five minutes later, someone called him. The money, the caller said, had been sent by mistake, and could he please send it back?

At first glance, the message looked completely genuine. That is the trap. If a stranger says your account received money that was never meant for you, returning it feels like the honest thing to do. The scam only works if you act before you doubt it.

I looked closer and stopped my brother before he sent anything. I checked the account balance to confirm, and the credit wasn't real. I caught it in time, but that was luck. I kept thinking about everyone who has no one to double-check for them.

The same trick, many disguises

Once I started paying attention, I saw the same pattern everywhere:

  • A message warning that your electricity will be cut tonight at 9:30 PM unless you call a number.
  • A "cashback" that asks for your UPI PIN so you can "receive" money.
  • A video call from a "police officer" announcing that you are under digital arrest.

Each one pulls the same levers: urgency, fear or greed, and a request that moves your money or your credentials.

What Was Missing?

When I looked for a tool that could have helped my brother, I noticed two gaps:

  1. Scam checkers and fact-checkers are separate tools. A phishing message can quote a completely true news event to sound convincing, and a false viral claim can contain no malicious link at all. One "safe / unsafe" label hides that.
  2. Most AI answers are confident but unsourced. A model that says "this looks fine" does not tell you what was actually checked.

I wanted something my brother could paste that message into and get a calm answer to three questions:

  • Is this trying to defraud me?
  • Is this claim true?
  • And how sure are you?

In English, Hindi, or Hinglish, because that is how people here actually write.

What Does It Do?

SatyamAI is a decision-support tool for suspicious messages, links, and screenshots. Its central idea is to keep two verdicts separate instead of merging them into one score:

$$V = (s, c)$$

Scam/security risk:

$$s \in {\texttt{likely_scam},\ \texttt{suspicious},\ \texttt{unverified},\ \texttt{no_obvious_risk_found}}$$

Factual accuracy:

$$c \in {\texttt{supported},\ \texttt{contradicted},\ \texttt{mixed},\ \texttt{unverified}}$$

Each result also includes:

  • Plain-language reasons.
  • Evidence with a real title, publisher, and URL.
  • A list of which checks ran and which couldn't.
  • Recommended next steps, including the National Cyber Crime Helpline (1930) and cybercrime.gov.in.

Where PayPal and AI Come Together

The hackathon asks for meaningful use of both, so each one does real work in SatyamAI.

  • AI does the understanding. Amazon Bedrock reads the message in context, extracts the factual claims, reads screenshots through a vision model, and writes the explanation in English, Hindi, or Hinglish. Deterministic rules and retrieved evidence keep it grounded.
  • PayPal funds the protection. Every guest gets 3 free checks. When they run out, they can buy more through a PayPal Orders v2 checkout in USD or INR. The server creates the order, verifies the captured status, amount, currency, and package before crediting anything, checks webhook signatures, and reverses credits on refunds. This runs in PayPal Sandbox, so no real money moves.
  • Money and safety are kept apart. A user is only charged for an analysis that succeeds, and when credits hit zero, a safety card (helpline 1930, never share an OTP or UPI PIN, no such thing as a digital arrest) still shows. Running out of credits never leaves someone defenseless.

How I Built It

SatyamAI is a modular monolith, on purpose: one developer, a fixed deadline, and no appetite for microservice overhead. It is a Next.js 15 App Router app in TypeScript, with Tailwind CSS v4, Zod validation on every request and response, and Vitest for tests.

Every analysis follows the same path

  1. Guard. Rate limiting, session resolution (guest or signed-in), and a credit reservation with a 120-second expiry.
  2. Deterministic rules (under 2 ms). A catalogue of India-specific patterns: UPI PIN and QR reversal traps, electricity disconnection threats, digital-arrest extortion, KYC and bank-block scare tactics, plus Hindi and Hinglish cues.
  3. Claim extraction and evidence. Factual claims are pulled out, then checked against Wikipedia search and, when configured, the Google Fact Check Tools API. Irrelevant results are filtered so citations stay honest.
  4. URL reputation. A Cloudflare DNS reputation lookup, plus Google Safe Browsing when configured. The server never visits the target page, which removes a whole class of SSRF risk.
  5. Amazon Bedrock. Server-side only, returning structured JSON for the explanation and recommended actions. User text and retrieved pages are treated as untrusted data, never as instructions.
  6. Orchestrator. It fuses the signals into two separate verdicts. A missing provider result becomes unverified, never "safe".
  7. Commit. The credit is debited only on success and returned if anything fails.

Around that core

  • Adapters everywhere. The AI model, evidence, URL reputation, and OCR each sit behind a thin typed interface, so any of them can be swapped without touching domain logic.
  • Three ways in. A web dashboard for text, links, and screenshots (with an OCR review step so users can fix extraction mistakes), and a Telegram bot that calls the same analysis pipeline.
  • Accounts and history. Salted scrypt passwords, 30-day sessions, and guest-to-account migration that carries credits and scans over. Data lives in Node's native SQLite locally and Turso/libSQL on Vercel.
  • PayPal credits. Server-authoritative orders, idempotent capture, signature-checked webhooks, and an append-only transaction ledger.
  • Tested. 229 Vitest tests across 20 suites pass, along with type checking and the production build.

What I Learned

  • Uncertainty is a feature. "No evidence found" is not "evidence of safety." Building the schema and UI to say so changed how I thought about every result.
  • AI should interpret evidence, not replace it. Rules and retrieved sources carry the weight; the model explains. A model's explanation is never shown as a citation.
  • Never trust the client with money. Orders are created on the server, and a capture is only credited after its status, amount, currency, and package all match.
  • Payments arrive twice. Webhooks retry and users double-click, so database-backed unique indexes make crediting idempotent.
  • A credit system is a small state machine. Reserve, then commit or release. Getting the failure paths right mattered more than the happy path.
  • Outages are a design case. Partial results, timeouts, and unavailable providers each needed their own tested path and UI state.
  • Audit your own work. When I audited the project against my own spec, I found gaps I had missed while building. Honest reporting is a discipline, not a README line.

Challenges

  • Two verdicts, one screen. Scam risk and factual accuracy had to sit side by side and still be easy to scan on a phone.
  • Hindi and Hinglish. Devanagari, Roman-script Hindi, and English can mix inside one message, which rigid patterns handle badly. I treated the rules as indicators, not proof.
  • Credits that survive failures. Aborted requests, retries, and concurrent checks must never charge for a failed analysis or lose a balance. A per-user lock and expiring reservations solved most of it.
  • Refunds and bounds. A refunded payment has to reduce credits without ever pushing a balance below zero.
  • One app, two databases. Local SQLite and Vercel's serverless filesystem behave very differently, which led to Turso, migration scripts, and a rule that production fails loudly instead of quietly using ephemeral storage.
  • A privacy gap I found myself. My spec says not to store raw submissions by default, but the app automatically saves a preview and the full result of each analysis. Users can search and delete their history, but there is no opt-in or retention period yet. I am calling that a known gap, not claiming privacy by default.
  • Not overclaiming. I avoided words like "safe" and "100% accurate". A small test set cannot support accuracy claims, so the limitations are documented.

What's Next?

  • Make saving history opt-in, with a clear notice and a retention period.
  • Grow the labeled evaluation set (legitimate, fraudulent, ambiguous, Hindi, and Hinglish examples) before making any accuracy claim.
  • Add regional languages once evaluation shows a clear need.
  • Move payments from PayPal Sandbox to live checkout.

Built With

Share this project:

Updates

Submission history