Actors


High-Level Architecture

The App and Dashboard talk directly to Aarokya Backend. PBA is only contacted at the tail end of a debit cycle — once to record the pending ledger entry when the debit is dispatched, and again to mark it completed after the settlement webhook arrives. Mandate setup, activation, and scheduling do not touch PBA.

End-to-End Sequence

The complete journey — setup, activation, scheduling, and debit — in one view.

Flow ① — Mandate Registration (Setup Autopay)

The driver opts into autopay. Aarokya Backend persists the mandate shell, creates a Juspay session scoped to the mandate amount, and returns an SDK payload that the app will hand to the Juspay SDK in the next step. Key writes on Aarokya Backend side: a mandates row in PENDING state with the order_id returned by Payment Servers.
With the SDK payload in hand, the app opens the Juspay SDK’s payment page. The user picks their UPI app; the SDK deep-links into it with an autopay consent intent; the user approves the mandate inside their UPI app; control returns to Aarokya. Aarokya Backend is not called during this phase — all interactions are between the app, the SDK, and the UPI app / rails.
The UPI app talks to Payment Servers (not to Aarokya) when the user approves. Aarokya Backend only learns that the mandate is active via the status poll and/or the Payment Servers MANDATE_ACTIVE webhook in the next flow.

Flow ③ — Mandate Activation — Status Poll

After returning from the UPI app, the app polls Aarokya Backend for the mandate status. Aarokya Backend queries Payment Servers, stores the order data, and returns the status to the app.

Flow ④ — Mandate Activation — Webhook

Independently of the poll, Payment Servers fire a MANDATE_ACTIVE webhook to Aarokya Backend, which writes the final mandate status to DB.
Both the poll (Flow ③) and this webhook can arrive in either order — both paths are idempotent. Use order_id + status as the idempotency key when writing mandates.status.

Flow ⑤ — Start Autopay (Schedule Recurring Job)

Ops (or an automated upstream) flips a mandate from “active” to “actively debiting” by scheduling a job on Kronos. Kronos owns the cron; Aarokya Backend owns the state. State transitions: ACTIVE → SCHEDULING → SCHEDULED. The intermediate SCHEDULING state lets us recover if the Kronos call fails — a retry worker can re-issue the schedule without double-booking.

Flow ⑥ — Recurring Debit — Job Fires

Kronos fires the scheduled job. Aarokya Backend fetches mandate data, creates a txn entry, calls Payment Servers with the mandate txn order ID, and records a pending ledger entry with PBA.

Flow ⑦ — Settlement & Ledger Completion

Payment Servers fire an ORDER webhook once the debit settles. Aarokya Backend updates the txn and closes the ledger entry with PBA.
Why two ledger calls? The PENDING call (Flow ⑥) gives the partner a real-time hold on funds the moment we dispatch to Payment Servers. The COMPLETED call only fires after the ORDER webhook confirms money has moved. If the webhook reports a failure, Aarokya Backend calls PBA with FAILED instead — the partner never sees a phantom settlement.

State Machine — Mandate


State Machine — Debit Transaction


Idempotency & Recovery