Enviar mensajes de WhatsApp con Python
Código mínimo funcional contra la Cloud API, con la librería requests.
Necesitas pip install requests, tu Phone Number ID y un token de acceso.
1. Enviar un mensaje de texto libre
Solo funciona si el usuario te escribió en las últimas 24 horas (ventana de servicio abierta):
import os
import requests
PHONE_NUMBER_ID = os.environ["WHATSAPP_PHONE_NUMBER_ID"]
ACCESS_TOKEN = os.environ["WHATSAPP_ACCESS_TOKEN"]
URL = f"https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages"
def enviar_texto(numero_destino, mensaje):
respuesta = requests.post(
URL,
headers={
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json"
},
json={
"messaging_product": "whatsapp",
"to": numero_destino, # formato E.164 sin "+", ej. "34600000000"
"type": "text",
"text": {"body": mensaje}
}
)
respuesta.raise_for_status()
return respuesta.json()
if __name__ == "__main__":
print(enviar_texto("34600000000", "Hola, ¿en qué puedo ayudarte?"))
2. Enviar una plantilla (fuera de la ventana de 24h)
Si no hay conversación abierta, tienes que usar una plantilla aprobada por Meta, referenciada por su nombre e idioma:
def enviar_plantilla(numero_destino, nombre_plantilla, idioma, parametros=None):
parametros = parametros or []
body = {
"messaging_product": "whatsapp",
"to": numero_destino,
"type": "template",
"template": {
"name": nombre_plantilla,
"language": {"code": idioma}, # ej. "es" o "es_ES"
}
}
if parametros:
body["template"]["components"] = [{
"type": "body",
"parameters": [{"type": "text", "text": p} for p in parametros]
}]
respuesta = requests.post(
URL,
headers={
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json"
},
json=body
)
respuesta.raise_for_status()
return respuesta.json()
# Ejemplo: plantilla "confirmacion_pedido" con 1 variable {{1}}
enviar_plantilla("34600000000", "confirmacion_pedido", "es", ["#48213"])
Comprueba antes qué categoría tendrá tu plantilla (afecta al coste) con el comprobador de categoría.
3. Recibir mensajes y estados (webhooks)
El envío es solo la mitad: para recibir mensajes entrantes y confirmaciones de entrega necesitas un endpoint propio (por ejemplo con Flask o FastAPI) que reciba los webhooks de Meta. Cómo montarlo y qué significa cada campo, en la guía de webhooks, y valida cualquier payload real con el validador de webhooks.