Inspiration
In India a large share of online orders are cash on delivery (COD), and about one in four of them comes back undelivered. The merchant pays shipping both ways and loses the sale. Blunt fixes, such as blocking PIN codes or forcing prepayment, turn away good customers as well. We wanted a merchant tool that asks a better question: what will being wrong about this order cost in rupees, and what is the cheapest way to protect it? PayPal then does what a risk score cannot: it actually moves the money.
What it does
ChakraShield sits between "Place order" and the merchant's order system. In one call (budget 25 ms, median 1.9 ms) it
scores the order, says how sure it is, and picks the cheapest action: allow COD, take a refundable ₹49 shipping deposit,
or require prepayment. PayPal does the payment: the decision becomes a real PayPal order (the ₹49 deposit is charged
as $0.58 in the sandbox), the buyer approves it in PayPal, the gateway captures it, and when the courier reports
delivery the deposit is refunded automatically. If the parcel comes back, the deposit is kept. Every money call carries
a PayPal-Request-Id, so a retry can never charge or refund twice.
On held-out test orders (the last 3,875 COD orders of a simulated shop) the policy adds +46% net margin (₹2,03,370) and prevents 77% of returns (649 of 841), against a merchant running no engine.
How we built it
- AI/ML decision engine: LightGBM exported to ONNX Runtime, isotonic calibration, and Mondrian split-conformal prediction sets (91.8% measured coverage). The resolver picks the action with the lowest expected cost in rupees, with a friction shadow price so merchants can cap how many buyers see friction.
- PayPal integration: Orders v2 (create, capture), Payments (refund), webhook receiver with signature verification and de-duplication, and the Disputes API for evidence. Every call is idempotent. The money loop is verified against the live PayPal sandbox: order, buyer approval, capture and refund.
- Around it: typed-graph fraud-ring detection with a shared-entity guard, an ε-greedy control band with inverse-propensity retraining so the model keeps learning from orders it blocked, a label-free drift monitor, per-merchant configuration and a shadow mode, and a deterministic dispute evidence packet.
- Stack: Python, FastAPI, ONNX Runtime, LightGBM, scikit-learn, NetworkX, Redis, Docker, a plain HTML/JS console, and 111 passing tests.
Challenges
- PayPal's sandbox accounts created in India could not take USD or INR (
CURRENCY_NOT_SUPPORTED, then "this seller doesn't accept payments in your currency"). Moving to US sandbox accounts fixed it, and the README says so. - Two details only the real API revealed: capture needs a JSON content type even with an empty body (otherwise
415), and PayPal reports "buyer has not approved" as a 422 whose real reason is in
details[].issue. Our mock hid both, so we added regression tests. - Serving bugs found by a real HTTP load test: concurrent LightGBM TreeSHAP corrupted the native heap, and a synchronous pipeline inside an async handler stalled the event loop.
- A model that learns only from the orders it let through collapses (calibration error 0.173). The 5% control band brings the worst case down to 0.060.
What we learned
Judge the system in rupees, not accuracy: "everything delivers" already scores 78%. Uncertainty is useful for decisions (an empty conformal set means "novel pattern"). And an offline mock is worth building, but only a real sandbox run finds the mismatches.
What's next
- Run the webhook and Disputes API calls against the real sandbox. They are implemented and tested on the mock only.
- Real merchant data with customer and address fields: our run on a public export with no such fields reached only AUC 0.55, and the policies correctly did nothing.
- Revisit deposit economics: PayPal's fixed fee is large against a $0.58 deposit.
How the project was significantly updated during the Submission Period
ChakraShield existed before the hackathon as a COD risk gateway (decisions only, no payments). During the Submission Period we
added the whole PayPal integration (src/chakrashield/paypal/), the payment, webhook and dispute routes, an offline mock,
a one-command demo (scripts/16_paypal_demo.py), 20 new tests, a MIT license, and a restyled console.
Testing instructions (for judges)
No credentials are needed: without PayPal keys the gateway runs an offline mock with the same state machine.
pip install -r requirements.txt
python scripts/01_generate_data.py # ~90 s
python scripts/serve.py --port 8080 # console at http://127.0.0.1:8080
python scripts/16_paypal_demo.py # decision -> PayPal order -> approve -> capture -> delivery -> refund
To use the real PayPal sandbox, create a Sandbox app plus a US Business and Personal sandbox account, copy
.env.example to .env, fill in the client ID and secret, and restart. GET /v1/paypal/status should say "mode": "sandbox".
Built With
- conformal-prediction
- css
- docker
- docker-compose
- fastapi
- github-actions
- html
- javascript
- lightgbm
- networkx
- numpy
- onnx-runtime
- pandas
- paypal-orders-v2
- paypal-refunds-api
- paypal-rest-api
- paypal-sandbox
- pydantic
- pytest
- python
- redis
- scikit-learn
- scipy
- uvicorn