Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/rahul-baberwal/django-meta-whatsapp/llms.txt

Use this file to discover all available pages before exploring further.

django-meta-whatsapp defines four Django signals. Two are dispatched automatically by the built-in WebhookView; two are defined in the library but not dispatched by any built-in code — they are provided as hooks for you to fire from your own views or tasks. Connect to any of them in your app’s AppConfig.ready(). All signals are importable from django_meta_whatsapp.signals.

Import

from django_meta_whatsapp.signals import (
    whatsapp_message_received,
    whatsapp_message_sent,
    whatsapp_campaign_completed,
    whatsapp_user_subscribed,
)

whatsapp_message_received

Fired by: WebhookView._process() when an inbound message is ingested and saved. kwargs:
NameTypeDescription
messageWhatsAppMessageThe newly created inbound message instance.
from django.dispatch import receiver
from django_meta_whatsapp.signals import whatsapp_message_received

@receiver(whatsapp_message_received)
def on_message_received(sender, message, **kwargs):
    # message.phone_number  — who sent it
    # message.message_body  — text content (if text message)
    # message.message_type  — "text", "image", "document", etc.
    # message.direction     — always "inbound" here
    print(f"New message from {message.phone_number}: {message.message_body}")

whatsapp_message_sent

Fired by: Not dispatched by any built-in library code. This signal is defined and exported so that your project can fire it from a custom outbound send view or Celery task after successfully calling send_text_message(), send_template_message(), or any other send util. kwargs:
NameTypeDescription
messageWhatsAppMessageThe outbound message instance that was just sent.
# Example: fire the signal yourself after saving an outbound message
from django_meta_whatsapp.signals import whatsapp_message_sent
from django_meta_whatsapp.models import WhatsAppMessage

msg = WhatsAppMessage.objects.create(
    phone_number="919876543210",
    direction="outbound",
    message_type="text",
    message_body="Hello!",
    message_id=resp["messages"][0]["id"],
)
whatsapp_message_sent.send(sender=None, message=msg)
# Example: receive the signal in a handler
from django.dispatch import receiver
from django_meta_whatsapp.signals import whatsapp_message_sent

@receiver(whatsapp_message_sent)
def on_message_sent(sender, message, **kwargs):
    print(f"Message {message.message_id} sent to {message.phone_number}")

whatsapp_campaign_completed

Fired by: Not dispatched by any built-in library code. run_campaign() and run_campaign_async() in utils.py do not emit this signal. Define a receiver and fire it yourself at the end of a custom campaign runner or Celery task if you need post-campaign hooks. kwargs:
NameTypeDescription
campaignWhatsAppCampaignThe completed campaign instance.
sentintNumber of messages successfully sent.
failedintNumber of messages that failed to send.
# Example: fire the signal yourself after run_campaign() returns
from django_meta_whatsapp.signals import whatsapp_campaign_completed
from django_meta_whatsapp.utils import run_campaign

result = run_campaign(campaign.id, account=account)
whatsapp_campaign_completed.send(
    sender=None,
    campaign=campaign,
    sent=result["sent"],
    failed=result["failed"],
)
# Example: receive the signal in a handler
from django.dispatch import receiver
from django_meta_whatsapp.signals import whatsapp_campaign_completed

@receiver(whatsapp_campaign_completed)
def on_campaign_done(sender, campaign, sent, failed, **kwargs):
    print(
        f"Campaign '{campaign.name}' finished: "
        f"{sent} sent, {failed} failed out of {campaign.total_count} total."
    )

whatsapp_user_subscribed

Fired by: WebhookView._process() when a user subscribes through an In-App Signup link (in_app_signup webhook event). kwargs:
NameTypeDescription
contactWhatsAppContactThe contact record for the new subscriber (created or updated).
signupWhatsAppSignupThe signup link the user subscribed through.
from django.dispatch import receiver
from django_meta_whatsapp.signals import whatsapp_user_subscribed

@receiver(whatsapp_user_subscribed)
def on_user_subscribed(sender, contact, signup, **kwargs):
    # contact.phone         — subscriber's phone number
    # contact.name          — subscriber's name (if available)
    # signup.display_name   — internal label for the signup link
    # signup.promo_code     — promo code attached to the link (if any)
    print(
        f"{contact.phone} subscribed via '{signup.display_name}' "
        f"(promo: {signup.promo_code or 'none'})"
    )

Connecting Receivers

The recommended pattern is to define all receiver functions in a handlers.py (or signals.py) module inside your app, then import it inside AppConfig.ready() to ensure the decorators are registered at startup.
myapp/apps.py
from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = "myapp"

    def ready(self):
        import myapp.handlers  # noqa — triggers @receiver decorators
myapp/handlers.py
from django.dispatch import receiver
from django_meta_whatsapp.signals import (
    whatsapp_message_received,
    whatsapp_campaign_completed,
    whatsapp_user_subscribed,
)

@receiver(whatsapp_message_received)
def handle_inbound(sender, message, **kwargs):
    # Auto-reply to any inbound text message
    if message.message_type == "text":
        from django_meta_whatsapp.utils import send_text_message
        send_text_message(
            message.phone_number,
            "Thanks for your message! We'll get back to you shortly.",
            reply_message_id=message.message_id,
        )

@receiver(whatsapp_campaign_completed)
def notify_on_campaign_complete(sender, campaign, sent, failed, **kwargs):
    # Send an internal Slack/email notification, log to analytics, etc.
    pass

@receiver(whatsapp_user_subscribed)
def welcome_new_subscriber(sender, contact, signup, **kwargs):
    from django_meta_whatsapp.utils import send_template_message
    send_template_message(
        contact.phone,
        "welcome_message",
        language_code="en",
    )
Signal handlers run synchronously inside the webhook request/response cycle. Keep receivers fast — avoid database-heavy queries, external HTTP calls, or file I/O directly inside a handler. Use Celery tasks (triggered from the handler) for any heavy processing.

Build docs developers (and LLMs) love