Skip to content

Repository files navigation

Grabit

Recover payments. Reconnect trust. Grow revenue.

Grabit is an AI-powered Revenue Recovery Agent.

It automatically detects failed payments and Autopay failures, diagnoses why they failed, and takes the smartest next action to recover the money — with personalized messages, perfect timing, and clear stopping rules.


The Problem

Every day, merchants lose revenue because of:

  • Soft declines (low balance, temporary issues)
  • Hard declines
  • UPI Autopay failures
  • Mandate cancellations

Most systems just send a generic “Payment failed” message and stop.
Customers get confused, merchants lose money, and recovery rates stay low.


What Grabit Does

Grabit closes the loop:

  1. Detects payment & Autopay failures in real time
  2. Diagnoses the failure type (Hard / Soft / Autopay Failed / Autopay Cancelled)
  3. Decides the right action using AI + business rules
  4. Acts with personalized one-click recovery messages
  5. Times the message intelligently (salary windows, quiet hours, retry gaps)
  6. Stops cleanly when it should (max attempts, human escalation, etc.)
  7. Measures everything in a Recovery Ledger + Dashboard

Key Features

  • Smart failure classification
  • Personalized GenZ/Hinglish explanations + one-click recovery
  • Smart Timing Intelligence (salary cycle aware)
  • Human-in-the-Loop (HITL) for high-value or unclear cases
  • Strict Stopping Rules
  • Full audit trail
  • Clear recovery metrics for merchants

High Level Architecture

The architecture is built around an event-driven, decoupled pipeline designed for high-throughput webhook ingestion, deterministic rule evaluation, AI-driven recovery messaging, and recovery ledger + audit logging.

Architecture Diagram


System Flow

The end-to-end recovery lifecycle follows an automated 6-step state transition:

[ Razorpay Failure Event ]
           |
           v
+----------------------+
| 1. Ingest & Verify   | ---> Validate Signature -> Paise-to-INR Conversion -> Idempotently create `failed_payments`; ignore duplicate webhooks
+----------+-----------+
           |
           v
+----------------------+
| 2. Stopping Rules &  | ---> Checks: Already paid? Max follow-ups? Hard decline? Stale (>24h)?
|    Timing Filter     |
+----------+-----------+
           |
     +-----+----------------------------------+
     | Passes Rules                           | Rule Triggered
     v                                        v
+----------------------+             +----------------------------------------------------------+
| 3. AI Agent Decision |             | - High Value (>=10k) / Low Confidence -> HITL Escalation |
|    & Copy Generation |             | - Quiet Hours (21:00-08:00 IST) / Salary Gap -> Delay    |
+----------+-----------+             | - Hard Decline / Max Follow-ups -> Mark Unrecovered      |
           |                         +----------------------------------------------------------+
           v
+----------------------+
| 4. WhatsApp Outreach | ---> Sends personalized one-click recovery message via WhatsApp API
+----------+-----------+
           |
           v
+----------------------+
| 5. Customer Action   | ---> Customer clicks one-click link or updates mandate via Razorpay
+----------+-----------+
           |
           v
+----------------------+
| 6. Reconciliation    | ---> Payment Webhook -> Mark `recovered` -> Record in `recovery_ledger`
+----------------------+

Database Schema

The database model is strictly relational with foreign key integrity, audit logging, and normalized Decimal money handling (stored in INR Rupees).

Db Schema

Documentation

Comprehensive engineering specifications, state machines, and data models are available in the /documentation directory:


Tech Stack

Layer Choice
Main API TypeScript + Hono
Background Jobs BullMQ + Redis
Database PostgreSQL + Prisma
AI Agent Python + Agno + FastAPI
Monorepo pnpm workspaces

Project Structure

grabit/
├── apps/
│   ├── api/            # Hono API
│   ├── worker/         # BullMQ workers
│   ├── web/            # Command View dashboard (Vite + React + TS)
│   └── ai-agent/       # Python + Agno service
├── packages/
│   ├── db/             # Prisma schema & client
│   ├── queue/          # BullMQ helpers
│   ├── core/           # Shared business logic
│   └── config/
├── scripts/            # demo:batch harness + db:seed
├── infra/
└── docs/               # Architecture diagrams & screenshots

Screenshots & Demo

  • Command View dashboard — live recovery KPIs + jobs table (apps/web, issue #32)
  • Recovery Ledger, sample recovery message, HITL queue — coming soon

Getting Started

Prerequisites

  • Node.js 22+ (repo scripts use node --env-file-if-exists, added in Node 22.9)
  • pnpm (npm i -g pnpm)
  • Docker (for Postgres + Redis)

1. Start the infrastructure

docker compose -f infra/docker-compose.yml up -d

Brings up:

Service Port
Postgres 5433
Redis 6380
AI Agent 8001

Ports differ from the usual 5432/6379 to avoid conflicts with other local projects.

2. Install dependencies & generate the Prisma client

pnpm install
pnpm --filter @grabit/db exec prisma generate

3. Push the schema to the database

DATABASE_URL="postgresql://grabit:grabit@localhost:5433/grabit" \
  pnpm --filter @grabit/db exec prisma db push

(Or copy .env.example to .env and skip the inline DATABASE_URL.)

3b. Seed demo data (optional, idempotent)

pnpm db:seed

Creates 4 representative recovery jobs (one-click recovered ₹1,499, a hard stopped case with no message, a high-value HITL pending case, and an active waiting follow-up) so an empty database shows meaningful dashboard numbers immediately. Uses deterministic IDs + upserts — re-running never duplicates rows. Refuses to run against a non-local DATABASE_URL.

4. Start the API

DATABASE_URL="postgresql://grabit:grabit@localhost:5433/grabit" pnpm dev:api

4b. Start the Command View dashboard (web)

pnpm --filter @grabit/web dev

Opens at http://localhost:5173. Reads the API at VITE_API_URL (default http://localhost:3100) and polls /dashboard/summary + /jobs every 3s while the tab is visible, so numbers move live after pnpm demo:batch or a payment.captured webhook — no refresh needed.

5. Test it

curl http://localhost:3100/health

Expected:

{"status":"ok","service":"grabit-api","database":"connected"}

Stopping

# API: Ctrl+C in its terminal

docker compose -f infra/docker-compose.yml down     # stop containers
docker compose -f infra/docker-compose.yml down -v  # also wipe Postgres data

Status

Currently in active development

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages