Canal WhatsApp
Summit Notify entrega WhatsApp mediante AWS End User Messaging Social. Las cuentas, plantillas, conversaciones y eventos se aíslan por la identidad autenticada.
Para el contrato de envío de POST /api/v1/notifications, consulta Enviar notificaciones por WhatsApp. Esta página conserva la configuración de cuentas, plantillas, eventos y adjuntos.
Identidad de envío
Sección titulada «Identidad de envío»Una cuenta WhatsApp contiene:
| Campo | Descripción |
|---|---|
ownership_type |
notify_managed o customer_owned. |
aws_region |
Región utilizada por el cliente de AWS. |
waba_id |
Identificador de la WABA enlazada en AWS. |
origination_phone_number_id |
Identificador AWS que empieza por phone-number-id-. |
meta_waba_id |
Identificador numérico de Meta usado para enrutar eventos. |
meta_phone_number_id |
Identificador numérico del número en Meta y las conversaciones. |
is_default |
Cuenta usada cuando se omite whatsapp_account_id. |
Las cuentas se administran actualmente desde /admin/whatsapp-accounts; no existe un CRUD público /api/v1/whatsapp-accounts.
Configuración del despliegue
Sección titulada «Configuración del despliegue»| Variable | Propósito |
|---|---|
WHATSAPP_META_API_VERSION |
Versión de Meta enviada a AWS. |
WHATSAPP_TEMPLATE_SYNC_INTERVAL |
Frecuencia de reconciliación de plantillas. |
WHATSAPP_SNS_TOPIC_ARN |
ARN exacto del topic SNS permitido. |
WHATSAPP_MEDIA_BUCKET |
Bucket privado para adjuntos entrantes. Vacío deshabilita la recuperación protegida. |
WHATSAPP_MEDIA_REGION |
Región del bucket y la WABA. |
WHATSAPP_MEDIA_PREFIX |
Prefijo S3; valor usual notify/whatsapp. |
WHATSAPP_MEDIA_CLOUDFRONT_URL |
Dominio HTTPS de la distribución. |
CLOUDFRONT_PUBLIC_KEY_ID |
ID de la clave pública confiable, no el ID del grupo ni de la distribución. |
CLOUDFRONT_PRIVATE_KEY_PATH |
Ruta interna al PEM RSA usado para firmar URLs. |
WHATSAPP_MEDIA_URL_TTL |
Vigencia de una URL firmada, por ejemplo 10m. |
Cuando WHATSAPP_MEDIA_BUCKET tiene valor, región, URL CloudFront, ID público y ruta privada son obligatorios. La clave privada debe montarse en modo sólo lectura y permanecer fuera del repositorio y de la imagen Docker.
La identidad AWS del proceso necesita las operaciones Social Messaging utilizadas por la instancia, incluidas social-messaging:SendWhatsAppMessage, social-messaging:PostWhatsAppMessageMedia y social-messaging:GetWhatsAppMessageMedia. Para los objetos necesita s3:PutObject bajo el prefijo configurado; CloudFront debe leer mediante OAC con s3:GetObject. No agregues s3:HeadObject: esa acción no existe en IAM y las solicitudes HEAD se autorizan mediante s3:GetObject.
API de conversaciones
Sección titulada «API de conversaciones»Además del panel, las conversaciones se pueden operar desde sistemas externos y desde agentes de Summit AI. Ambas rutas usan la API key de Summit Notify (Authorization: Bearer <SUMMIT_NOTIFY_API_KEY>) y respetan el mismo aislamiento por propietario.
Endpoints JSON
Sección titulada «Endpoints JSON»| Método | Ruta | Descripción |
|---|---|---|
GET |
/api/v1/whatsapp-conversations |
Lista paginada por cursor. Filtros: window=open|closed, q=<teléfono>, limit (1–100, default 25), cursor. |
GET |
/api/v1/whatsapp-conversations/{id} |
Detalle de la conversación. |
GET |
/api/v1/whatsapp-conversations/{id}/messages |
Historial (limit, default 100, máx 500) con window_open y service_window_expires_at. |
POST |
/api/v1/whatsapp-conversations/{id}/reply |
Encola una respuesta; devuelve 202 con {"notification_id": "..."}. |
POST |
/api/v1/whatsapp-conversations/{id}/media-upload |
Sube un adjunto (multipart file + media_type, máx 20 MB) y devuelve 201 con el media_id. |
GET |
/api/v1/whatsapp-conversations/{id}/messages/{messageID}/media |
Devuelve JSON con URL firmada de CloudFront (url, expires_at, content_type, filename). Responde 503 con Retry-After mientras se copia a S3. |
El cuerpo de reply admite message_type (text, image, video, audio, document, location), text, media_id (de un media-upload previo) o media_url (HTTPS pública), caption, filename, latitude, longitude, location_name, address, y opcionalmente fallback_template_id con fallback_parameters. Si la ventana de 24 horas está cerrada y no hay fallback válido, responde 409; los errores de validación responden 400.
MCP para Summit AI
Sección titulada «MCP para Summit AI»Summit AI puede invocar las conversaciones como tools MCP en el endpoint:
POST /mcpAuthorization: Bearer SUMMIT_NOTIFY_API_KEY| Tool | Descripción |
|---|---|
list_conversations |
Lista conversaciones del tenant. Filtros: window, q, limit, cursor. |
get_conversation |
Detalle de una conversación por UUID. |
get_conversation_messages |
Historial de mensajes. |
reply_to_conversation |
Encola una respuesta; devuelve notification_id y status. |
Los tools aplican las mismas reglas de ventana y fallback que los endpoints JSON. No soportan carga/descarga de archivos binarios; usá los endpoints JSON para multimedia. Consulta la referencia MCP de Summit Notify.
Crear una notificación WhatsApp
Sección titulada «Crear una notificación WhatsApp»Usa el endpoint común:
POST /api/v1/notificationsAuthorization: Bearer SUMMIT_NOTIFY_API_KEYContent-Type: application/jsonCampos superiores:
| Campo | Requerido | Descripción |
|---|---|---|
channel |
Sí | Debe ser whatsapp. |
recipient |
Sí | Teléfono E.164, por ejemplo +593999999999. |
whatsapp_account_id |
No | UUID de la cuenta; se usa la predeterminada si se omite. |
whatsapp |
Sí | Payload específico del canal. |
Texto libre
Sección titulada «Texto libre»{ "channel": "whatsapp", "recipient": "+593999999999", "whatsapp_account_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "whatsapp": { "type": "text", "text": { "body": "Hola, ¿en qué podemos ayudarte?" }, "fallback_template": { "type": "template", "template_id": "c7a4e210-9d2b-4f6a-8e1c-3b5d7f9a0c2e", "values": { "parameter_1": "Cliente" } } }}El texto admite hasta 4096 caracteres. El mensaje libre exige una conversación con ventana de servicio abierta; de lo contrario responde 409 Conflict o utiliza fallback_template.
Multimedia
Sección titulada «Multimedia»image, video, audio y document aceptan exactamente uno de id o link:
{ "channel": "whatsapp", "recipient": "+593999999999", "whatsapp": { "type": "document", "document": { "link": "https://media.example.com/documento.pdf", "caption": "Documento solicitado", "filename": "documento.pdf" } }}El enlace debe ser HTTPS y accesible para WhatsApp.
El panel permite subir el archivo directamente. El endpoint autenticado acepta multipart, limita el
archivo a 20 MB, lo guarda bajo el prefijo outbound, invoca PostWhatsAppMessageMedia y devuelve
el mediaId. El formulario envía después ese ID en lugar de una URL. El mismo endpoint recibe los
blobs creados por el grabador del navegador.
La migración 0020_add_whatsapp_media_uploads.sql registra propietario, cuenta, conversación,
mediaId, clave S3, MIME, nombre y tamaño. Cuando el worker confirma el envío, el mensaje saliente
recupera esa asociación y continúa mostrando el adjunto después de actualizar la conversación.
Ubicación y reacción
Sección titulada «Ubicación y reacción»La ubicación requiere coordenadas válidas. Una reacción requiere el ID del mensaje al que responde:
{ "type": "reaction", "reaction": { "message_id": "wamid.EXAMPLE", "emoji": "👍" }}Plantillas de WhatsApp
Sección titulada «Plantillas de WhatsApp»| Método | Ruta | Éxito |
|---|---|---|
GET |
/api/v1/whatsapp-templates |
200 |
POST |
/api/v1/whatsapp-templates |
201 |
GET |
/api/v1/whatsapp-templates/{id} |
200 |
POST |
/api/v1/whatsapp-templates/{id}/sync |
200 |
DELETE |
/api/v1/whatsapp-templates/{id} |
200 |
Estos endpoints usan un access token OpenID Connect. La creación se envía inmediatamente a AWS/Meta. Sólo los estados remotos APPROVED o ACTIVE establecen can_send: true.
El API de notificaciones recibe el template_id interno y valores con nombre; resuelve internamente el nombre externo, idioma y componentes para evitar que el consumidor suplante la definición aprobada.
Eventos SNS y estados
Sección titulada «Eventos SNS y estados»El endpoint público es:
POST /webhooks/aws/sns/whatsappAcepta confirmaciones y notificaciones únicamente desde el Topic ARN configurado. Valida la firma SNS y procesa duplicados de forma idempotente. La notificación pasa por submitted, sent o failed; los eventos delivered y read registran sus fechas manteniendo el estado sent. Los mensajes entrantes abren o renuevan conversaciones.
Adjuntos entrantes
Sección titulada «Adjuntos entrantes»Los mensajes multimedia conservan el mediaId y un estado local: pending, retrieving, available, failed o expired. El endpoint autenticado del panel recupera bajo demanda el archivo hacia S3 y redirige a una URL firmada de CloudFront. El bucket, WABA y llamada de AWS deben operar en la misma cuenta y región.
La clave S3 sigue esta estructura:
{prefix}/{whatsapp-account-id}/{conversation-id}/{message-id}/{media-id}.{extension}Los mensajes antiguos se incorporan mediante la migración de metadatos siempre que el payload almacenado conserve el mediaId.