Canal API: el contrato estructurado de eventos

Conversa Labs

Conversa Labs

Última actualización el Jul 16, 2026

Visión general

El canal API es una bandeja de entrada de primera clase. Cualquier módulo de la plataforma la alcanza de la misma forma en que alcanza WhatsApp o el widget web: crea un mensaje en una conversación. Ese mensaje luego se envía por POST — firmado — a la URL del webhook de tu bandeja de entrada. Como cada payload de mensaje lleva el content_type completo y los content_attributes, el contenido estructurado (botones interactivos, CTAs de pago, tarjetas de catálogo, eventos de calendario y reacciones) llega a tu integración de forma nativa — tú lo renderizas.

Todo lo aquí descrito es aditivo y retrocompatible: las integraciones existentes siguen funcionando y pueden ignorar cualquier campo que no reconozcan. No hay nuevos campos obligatorios.

Requisitos previos

  • Una bandeja de entrada API con una URL de webhook configurada.
  • El secreto de la bandeja de entrada para verificar la firma del webhook (y opcionalmente hmac_token para HMAC de entrada).
  • Un token de acceso para la API REST cuando envías datos de vuelta.

Paso a paso

  1. Crea una bandeja de entrada API y define su URL de webhook.
  2. Recibe eventos en esa URL y verifica la firma con el secreto de la bandeja de entrada.
  3. Lee content_type + content_attributes en cada payload de mensaje para renderizar contenido enriquecido.
  4. Envía mensajes de entrada, acuses de recibo y reacciones de vuelta a través de la API REST.
  5. (Opcional) Restringe qué eventos recibes con webhook_subscriptions.

Tipos de contenido de salida (lo que el webhook entrega)

Cada payload message_created / message_updated incluye content_type, content, content_attributes y attachments. Más allá del text plano, la bandeja de entrada API puede entregar:

  • input_select — opciones interactivas en content_attributes.items ([{title, value}]). Cuando un canal no puede renderizar opciones, la plataforma también agrega un menú numerado a content.
  • content_attributes.payment_interactive — una acción de pago: { body, buttons: [{ type: "cta_url", text, url } | { type: "cta_copy", text, code }] }. El cobro completo (importe, código PIX, boleto, enlaces) también llega como content_attributes.payment_charge en el mensaje resumen.
  • content_attributes.catalog_product — una tarjeta de producto: { mode: "single" | "list", products: [{ id, name, price, currency, image_url, ... }] }.
  • content_attributes.calendar_event — una confirmación de reserva o recordatorio: { id, title, starts_at, ends_at, location, meet_url, kind: "confirmation" | "reminder" } (horas en ISO-8601).
  • content_attributes.reactions — un array de { emoji, sender_jid }. El operador es me; un contacto se guarda bajo su propio identificador. Las reacciones viajan en el evento message_updated.
  • Plantillas — los metadatos de la plantilla enviada viajan en additional_attributes.template_params ({ name, language, category, processed_params }).
  • Multimedia, ubicación, contactos, stickers — entregados como attachments reales (además de content_attributes.media_kind para los stickers).

Entrada (lo que envías de vuelta)

  • Mensaje entrantePOST /api/v1/accounts/{account_id}/conversations/{conversation_id}/messages con message_type: "incoming". Acepta content, content_type, content_attributes y attachments, de modo que una respuesta interactiva es simétrica con el contrato de salida.
  • Acuses de reciboPUT/PATCH .../messages/{id} (solo bandejas de entrada API) con status de sent / delivered / read / failed (y un external_error opcional). Esto cambia el estado del mensaje, que se retransmite vía message_updated.
  • ReaccionesPOST .../messages/{id}/react con emoji (un emoji vacío la elimina). Pasa by=contact para registrar la reacción del contacto (por defecto se registra la del operador). No se contacta a ningún proveedor para una bandeja de entrada API — la reacción se persiste y se retransmite vía message_updated.

Campañas

Las campañas puntuales pueden dirigirse a una bandeja de entrada API. Cada contacto de la audiencia recibe una conversación real y un mensaje saliente, que viaja por tu webhook exactamente como cualquier otro mensaje de salida.

Configuración y opciones

  • webhook_subscriptions — un array opcional en los additional_attributes del canal API (actualiza la bandeja vía API con channel[additional_attributes][webhook_subscriptions]). Cuando se define, solo esos eventos se entregan; cuando está ausente o vacío, se entregan todos los eventos (el valor por defecto). Los nombres de eventos deben ser eventos válidos de la plataforma (por ejemplo, message_created, message_updated, conversation_created, conversation_status_changed, conversation_typing_on).
  • hmac_mandatory — rechaza las solicitudes de entrada que no puedan verificarse por HMAC.

Casos de uso

  • Conecta la bandeja de entrada con una aplicación personalizada que renderice CTAs de pago, tarjetas de catálogo y reservas de calendario.
  • Retransmite la reacción de un contacto desde tu propio cliente de vuelta al mensaje.
  • Refleja confirmaciones de reserva y recordatorios en el canal de registro del cliente.

Consejos, límites y buenas prácticas

  • Verifica siempre la firma del webhook antes de actuar sobre un payload.
  • Deduplica por el id de entrega / evento; espera reintentos.
  • Prefiere content_attributes para el renderizado estructurado; content es el respaldo en texto plano.
  • Suscríbete solo a los eventos que uses para reducir el ruido.

Solución de problemas

  • No llegan eventos: confirma que la URL del webhook está definida y, si configuraste webhook_subscriptions, que el evento que esperas está en la lista.
  • 422 en las suscripciones: la lista contiene un nombre de evento desconocido — elimínalo.
  • La reacción no se atribuye al contacto: pasa by=contact en la llamada de reacción.

Ver también