Zippi includes a WhatsApp bot that accepts delivery orders directly from customers via the Meta Cloud API. Incoming messages are routed through a conversation session service, parsed for intent, and — when recognized — converted into platform orders with real-time status updates sent back to the customer’s phone.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CRISTIANCAMACH34/Zippi/llms.txt
Use this file to discover all available pages before exploring further.
Prerequisites
Before you configure the integration you need:- A Meta Business Account with WhatsApp Business API access granted
- A WhatsApp Business phone number registered in Meta Business Manager
- A publicly reachable HTTPS URL for the webhook (use
BACKEND_PUBLIC_URLor a tunnel like ngrok in local dev)
Required Environment Variables
Add the following to your.env file (copy from .env.example):
WHATSAPP_DEFAULT_COUNTRY_CODE is used to normalize incoming phone numbers before storing or routing them. The default value 57 targets Colombia.
Setting Up the Webhook
Generate a secure verify token
Choose a random, unguessable string and set it as
WHATSAPP_VERIFY_TOKEN in your environment. This value is sent back to Meta during the handshake to prove ownership of the endpoint.Expose your backend publicly
Your webhook URL must be reachable over HTTPS. In development, use a tunnel:The full webhook URL is:
Register the webhook in Meta Business Manager
- Open Meta Business Manager → WhatsApp → Configuration → Webhook.
- Enter your webhook URL (from step 2).
- Enter the same string you set as
WHATSAPP_VERIFY_TOKEN. - Subscribe to the messages field.
- Click Verify and Save. Meta sends a
GETrequest withhub.challenge; the Zippi backend echoes it back automatically.
Set the App Secret for signature validation
Copy your App Secret from Meta App Dashboard → Settings → Basic and set it as
WHATSAPP_WEBHOOK_SECRET. This is distinct from the access token and is used only for HMAC verification.Webhook Security
Every inboundPOST /api/v1/whatsapp/webhook request from Meta includes an X-Hub-Signature-256 header. Zippi verifies this before processing any payload:
- The comparison uses
secrets.compare_digestto prevent timing attacks. - If
WHATSAPP_WEBHOOK_SECRETis not set, all requests are rejected (return False— fail-closed). - The raw request body is signed, not the parsed JSON, so the header must be read before any JSON decoding.
Message Templates
Zippi uses lightweight Python functions as message templates. All outbound message strings are defined inapp/infrastructure/external/whatsapp/message_templates.py:
| Function | When used | Example output |
|---|---|---|
welcome_template() | When the bot cannot parse an intent from the message | "Hola, gracias por escribir a Zippi. Cuéntanos qué servicio necesitas y te ayudamos." |
unsupported_message_template() | When the inbound message type is not text (e.g. image, audio) | "Por ahora solo procesamos mensajes de texto." |
order_status_template(order_id, status) | When an order changes state and the customer is notified | "Pedido ORD-00123: en camino" |
message_templates.py and call it from the appropriate handler in webhook_service.py or the notification layer.
The Ordering Conversation Flow
TheWhatsAppClient in app/infrastructure/external/whatsapp/client.py wraps the Meta Graph API /{api_version}/{phone_number_id}/messages endpoint. It validates that the base URL is https:// before making any outbound call (SSRF mitigation):
order_status_template(order_id, status) is sent to the customer’s phone number.
Disabling the Integration
IfWHATSAPP_PHONE_NUMBER_ID or WHATSAPP_ACCESS_TOKEN is empty, get_whatsapp_client() returns None and all outbound sends are skipped silently. The webhook endpoint remains active for verification but will not dispatch messages.