Sending Transactional SMS
Fee payment confirmations, payment receipts, and status updates — sending structured messages using DLT-approved templates.
Why First — The Scenario
A parent pays their child's tuition fee through EduTrack. They pay ₹2,500 via Razorpay. The payment succeeds. Now what?
From the parent's perspective, the screen shows a success state. They close the app. Twenty minutes later, they are not sure if the payment was really confirmed or if something went wrong. They have no proof. No receipt.
Now imagine instead: the moment the Razorpay webhook confirms payment, your system sends:
"Payment of Rs.2500 received for Tuition Fee - April for Arjun Sharma. Receipt ID: FEE-2025-0412. View on EduTrack app. - EDTRCK"
The parent has a record. They feel confident. Your support requests drop by half. This is transactional SMS — triggered by a real action, expected by the user, immediately useful.
The Excel Analogy
Think about how a CA firm sends engagement letters. Each letter is the same template — same structure, same clauses — but with the client's name, the fee amount, and the financial year filled in for each client.
DLT message templates work identically. You define the fixed structure once, get it approved, and at runtime your code fills in the {#var#} placeholders for each specific user and event.
The Architecture (Why Edge Function, Not Frontend)
Never Call MSG91 from Your Frontend
Your MSG91 auth key gives anyone who has it the ability to send unlimited SMS using your credits. If this key is in your React code, it is visible to anyone who opens your app in a browser's developer tools. Edge functions run on the server — the auth key never reaches the browser.
This is the only correct architecture. The edge function is the gatekeeper — it validates the request, looks up the fee record from your DB, and only then calls MSG91.
The Supabase Table for SMS Audit Logs
Always log every SMS send. This is your audit trail — useful for debugging, customer support ("I never got the message"), and compliance.
The Send Transactional SMS Edge Function
Create this at supabase/functions/send-fee-sms/index.ts:
Handling Delivery Status Webhooks
MSG91 can notify you when a message is delivered (or fails). This is optional but useful for support.
Configure Webhook in MSG91 Dashboard
Go to Settings → Webhook in MSG91. Enter your webhook URL:
Rate Limiting — Do Not Spam Users
Rate limits protect users from receiving too many messages and protect your credits from bugs.
A common bug: a database trigger fires twice, sending two confirmation SMS for one fee payment. Always implement idempotency.
When to Send Each SMS Type
| Event | SMS? | Timing |
|---|---|---|
| Fee payment confirmed | Yes | Immediately on payment webhook |
| Fee marked overdue | Yes | On due date if still unpaid |
| Result published | Yes | Immediately when teacher submits results |
| Attendance marked absent | Yes | Same day, once per day |
| New announcement | Optional | Immediately on announcement publish |
| Payment refund initiated | Yes | Immediately when refund is triggered |
| Enrollment confirmed | Yes | Immediately on enrollment |
| Promotional offer | No (separate flow) | Only with promotional DLT template |
Required Secrets
Next Step
Move to WhatsApp API — a richer alternative to SMS that often works better for high-value customer communications in India.