Meta Webhooks
Meta sends HTTP requests to a webhook URL you configure in the Meta for Developers app. For this project the webhook is exposed athttps://api.lokpanchang.com/webhook (production) or, in development, at a public URL provided by Ngrok (e.g. https://xxxx.ngrok.app/webhook).
Verification (GET)
When you register or save the webhook URL in Meta, Meta sends a GET request to verify ownership:- Query parameters:
hub.mode=subscribe,hub.verify_token=<your-token>,hub.challenge=<challenge-string>. - App behavior: The Flask route in
app.pycompareshub.verify_tokentoVERIFY_TOKEN(hardcoded as"test123"). If they match, the app responds with 200 and the body set tohub.challenge. Otherwise it returns 403. - Config in Meta: In the WhatsApp app’s webhook settings, set the Verify token to the same value as
VERIFY_TOKEN(e.g.test123).
Receiving events (POST)
After verification, Meta sends POST requests to the same URL for every event (user messages, delivery/read status, etc.):- Payload: JSON with
object: "whatsapp_business_account",entry[],changes[], and for messages avalue.messages[]array. Each message hasid,from(phone),type(e.g.text,location), and type-specific content. - App behavior: The POST
/webhookhandler inapp.pyonly processes entries that containmessages. Status updates (e.g. delivery receipts) are skipped. For each message it deduplicates by message ID, then dispatches:type == "location"→handle_location_message(geocode, save user, generate panchangam, send template + optional text).type == "text"→handle_text_message(e.g. “start” → request location; “stop” → unsubscribe; “help” → help text).
- Response: The handler must respond with 200 OK quickly so Meta does not retry. Heavy work (panchangam generation, sending replies) is done in the same request in this app.
Connection to WhatsApp Business API
- API base: Requests to send messages go to Meta Graph API:
https://graph.facebook.com/v18.0/(version and base URL are inmessaging.py). - Credentials:
WHATSAPP_PHONE_NUMBER_ID— The WhatsApp Business phone number ID (from Meta Business Suite / App Dashboard).WHATSAPP_ACCESS_TOKEN— A long-lived access token withwhatsapp_business_messagingandwhatsapp_business_management(or equivalent) permissions.
- Sending: The app builds the request URL as
{base}/{PHONE_NUMBER_ID}/messagesand sends POST with the token in theAuthorization: Bearer <token>header. Request body is JSON (see Template messages below for template format). - Where in code:
messaging.py—send_whatsapp_message(text),send_panchangam_template,send_whatsapp_template_message,send_location_request_message— all userequests.post(URL, headers=..., json=...)with the same base URL and token.
Using WhatsApp template messages
Business-initiated messages (e.g. daily panchangam at 6:30 AM) must use pre-approved templates so they are allowed outside the 24-hour customer service window. The app uses several templates:- Panchangam (primary): When
USE_SHORT_PANCHANGAM_TEMPLATEis true inmessaging.py, the app sends thenew_panchangam_shorttemplate (24 body parameters). When false, template choice is country-based: US (country code1) →dailymessage(utility); others →panchangam_global(marketing), both with 42 body parameters (location, date, weekday, panchangam elements, times, etc.). - Other templates:
tst_msg(test message, no params),user_unsubscribe(unsubscribe confirmation), and location request (interactive button) are used where appropriate.
messaging.py: generate_panchangam_template_parameters and generate_panchangam_template_parameters_short turn the panchangam dict (from Core Panchangam calculation) into the ordered list of body parameters. The request body follows the WhatsApp Cloud API format for template messages: type: "template", template: { name, language, components: [ { type: "body", parameters: [ { type: "text", text: "..." } ] } ] }.
Templates must be created and approved in the Meta Business Manager / WhatsApp Manager; once approved, the app only sends the template name and parameters. See Backend and Admin portal for how sends are triggered (webhook, Celery, admin actions).