| ← All Docs WhatsApp

WhatsApp Integration

Verified Last updated: September 2026

AquaDealers uses a dual WhatsApp implementation: client-side wa.me links for manual sends, and a server-side Edge Function via the authkey.io API for automated bill delivery.

Both methods share the same phone normalization logic. The API method fires automatically after bill creation; the link method is user-initiated from various report and statement screens.

Method A: wa.me Links (Client-Side / Manual)

How It Works

Builds https://wa.me/91{phone}?text={encoded} URLs and opens them in a new browser tab. The user must then press "Send" in WhatsApp Web or the WhatsApp app. No server round-trip required.

Phone Normalization

All phone numbers are cleaned before use:

Entry Points

FunctionPurposeUsage
openWhatsAppText()Send a text messageReports, statements, reminders
sharePdfViaWhatsApp()Share a PDF fileDownloads the PDF via a hidden <a download> link, then opens a blank wa.me chat for the user to manually attach the file
requirePhone()Guard functionPrompts user to add farmer phone number if missing before attempting send

10 Message Templates

All templates are defined in whatsAppMessages.ts. Each template builds a formatted text string with dynamic data:

#TemplateVariablesUsed In
1InvoiceBill items, total, balance, dateBill details page, checkout success
2Balance ReminderFarmer name, outstanding amountFarmer ledger, dues page
3StatementFarmer name, period dates, closing balance, shop nameFarmer statement page
4Delivery PIN4-digit confirmation PINDelivery confirmation flow
5Collection ReminderFarmer name, amount due, shop nameDues page
6Daily SummaryToday's sales, cash received, credit given, shop name, dateDaily book / end-of-day
7Dues ReportFarmer count with dues, total outstanding, shop nameDues report page
8Stock ReportPeriod dates, shop nameStock report page
9Farmer ItemsProducts a farmer has purchasedFarmer detail page
10Expiry ReportExpiring item count, shop nameDashboard expiry widget

Method B: API (Server-Side / Automated)

Architecture

Edge Function: send-bill-whatsapp

Environment Variables

VariablePurpose
AUTHKEY_TOKENAPI authentication token for authkey.io
AUTHKEY_BILL_WIDWhatsApp template ID for bill messages

Trigger Flow

1
Bill created via useCheckout.ts (online) or synced via offlineBillStore.ts (offline bills)
2
Edge function called fire-and-forget: .catch(() => {}) — failure never blocks checkout
3
Edge function sends request to authkey.io requestjson.php
4
authkey.io returns HTTP 200 = "accepted into queue" (not delivery confirmation)
CORS: The edge function uses Access-Control-Allow-Origin: *. This is a known security issue (see Security page).

Status Tracking

Status Flow

null → 'sending' → 'sent' | 'failed'

The whatsapp_status column on the bills table tracks delivery status:

StatusMeaningUI Treatment
nullNot yet attemptedNo indicator
sendingRequest in flightSpinner / "Sending..."
sentAccepted by authkey.ioGreen checkmark
failedRequest failed or quota exceeded"Retry" button shown

Polling

Failure Details

The failure_reason column stores a human-readable reason for debugging. Failed sends show a "Retry" button in:

Quota System

Database Tables

TablePurposeKey Columns
whatsapp_addon_plansPlan definitionsplan name, messages_per_month, price
whatsapp_message_usageMonthly usage trackingdealer_id, month_year, messages_sent

Validation Flow

1
Before sending, check_and_increment_whatsapp_usage RPC is called
2
RPC atomically checks messages_sent against plan's messages_per_month and increments the counter if within quota
3
If quota exceeded: status set to 'failed', reason set to 'quota_exceeded'

Failure Handling

Important: There is no automatic retry queue. Failed messages require manual retry via the UI button.
ScenarioBehavior
Edge function HTTP errorCheckout succeeds; bill status = failed; "Retry" button shown
authkey.io rejects requestSame as above
Quota exceededStatus = failed, reason = quota_exceeded
Network timeoutCheckout succeeds; status may stay sending indefinitely
authkey.io HTTP 200 but no deliveryNo way to detect. authkey.io does not provide delivery webhooks
Known limitation: authkey.io HTTP 200 means "accepted into queue" only. There is no delivery webhook, so AquaDealers cannot confirm actual delivery to the farmer's phone. The sent status means "sent to authkey.io", not "delivered to WhatsApp".