# WhatsApp Business Platform (Cloud API) — Tipos de mensajes, payloads y límites > Investigación sobre la documentación oficial de Meta (developers.facebook.com), 2026-09-26. > Nota: Meta migró la doc de `/docs/whatsapp/cloud-api/...` a `/documentation/business-messaging/whatsapp/...`. > Los tipos text/media/location/contacts siguen accesibles en las URLs legacy; interactive/templates ya > solo viven en la nueva ruta. Los datos citados provienen de las páginas listadas en "Fuentes". ## 1. Convención común de todos los mensajes Endpoint: `POST https://graph.facebook.com///messages` con header `Authorization: Bearer ` y `Content-Type: application/json` (Fuente: Message API reference — §Fuentes [17]). Sobre (envelope) común a todo mensaje (BaseMessageProperties, [17]): ```json { "messaging_product": "whatsapp", // requerido, siempre "whatsapp" "recipient_type": "individual", // "individual" (o "group" para grupos) "to": "", // requerido "type": "", "context": { "message_id": "wamid..." } // opcional: responde a un mensaje previo } ``` Respuesta de éxito: `contacts[].input`, `contacts[].wa_id` y `messages[].id` (`wamid.HBgL...`); el `message_status` inicial puede ser `accepted` (también existen `held_for_quality_assessment` y `paused`) [17]. ## 2. Text Payload [1]: ```json { "messaging_product": "whatsapp", "recipient_type": "individual", "to": "16505551234", "type": "text", "text": { "preview_url": false, "body": "Hola mundo" } } ``` | Campo | Descripción | Límite | |---|---|---| | `text.body` | Texto del mensaje (requerido). El cliente hipervincula URLs automáticamente | **4096 caracteres** | | `text.preview_url` | `true` = el cliente intenta renderizar preview del enlace | opcional | Vista en el teléfono: burbuja de solo texto; con `preview_url: true` **solo el primer URL** del body recibe preview (requiere `http://` o `https://`); si no se puede obtener, queda como enlace clicable [1]. El preview usa el Open Graph de la página: `og:title` (negrita, máx 2 líneas), `og:description` (~80 caracteres), `og:url` y `og:image` (thumbnail <600 KB, ≥300 px de ancho) renderizados encima del texto de la burbuja [22]. **Formato de texto** (`*negrita*`, `_cursiva_`, `~tachado~`, ` ```mono``` `): la página oficial actual de text-messages **ya no documenta la sintaxis** de formateo (verificado [1]); lo único oficial vigente leído es que el body/footer interactivos "soportan emojis y markdown" [17] y que el header de plantillas tipo TEXT **prohíbe** caracteres markdown [20]. La sintaxis con `*asteriscos*`, `_guiones bajos_`, `~tildes~` y triple acento grave es la estándar del cliente WhatsApp, pero su referencia oficial en el site de developers está retirada: dato NO verificable contra fuentes oficiales en esta investigación. ## 3. Media (image, video, audio, document, sticker) Patrón común: el objeto de media admite `id` (asset subido vía Media API — recomendado por performance) **o** `link` (URL pública — "no recomendado"); se provee solo uno [2]–[6]. **Image** [2] — `type: "image"`, objeto `image`: `{ id | link, caption }`. Caption máx **1024 caracteres**. Formatos: JPEG (`image/jpeg`) y PNG (`image/png`), 8-bit RGB/RGBA, máx **5 MB**. **Video** [3] — `type: "video"`, objeto `video`: `{ id | link, caption }`. Caption máx **1024**. Solo códecs **H.264 (video) + AAC (audio)**, un solo stream de audio o ninguno; MP4 (`video/mp4`) y 3GP (`video/3gpp`), máx **16 MB**. H.264 "High" con B-frames no funciona en Android; usar Main/Baseline y `moov` antes de `mdat` (ffmpeg `-movflags faststart`). **Audio** [4] — `type: "audio"`, objeto `audio`: `{ id | link, voice }`. `voice: true` = mensaje de voz (requiere OGG con codec OPUS, mono; el OGG base no es soportado). Formatos: AAC, AMR, MP3 (`audio/mpeg`), M4A (`audio/mp4`), OGG (`audio/ogg`); máx **16 MB**. Vista: archivos ≤512 KB muestran icono de play como mensaje de voz; los mayores muestran icono de descarga [4]. **Document** [5] — `type: "document"`, objeto `document`: `{ id | link, caption, filename }`. Caption máx **1024**; `filename` (con extensión) define el icono del tipo de archivo en el cliente. Tipos soportados (máx **100 MB**): TXT, XLS/XLSX, DOC/DOCX, PPT/PPTX, PDF. Otros tipos pueden enviarse pero no están soportados oficialmente. **Sticker** [6] — `type: "sticker"`, objeto `sticker`: `{ id | link }` (sin caption). Formato **WebP** únicamente: animado máx **500 KB**, estático máx **100 KB**. Vista: se muestra como sticker (sin texto); error si el WebP no es soportado o excede el tamaño. Vista general media: la burbuja muestra el recurso y, si aplica, el caption debajo; en document aparece icono por extensión + filename; en image/video el caption va bajo el recurso [2][3][5]. ## 4. Location Payload [7] — `type: "location"`, objeto `location`: | Campo | Requerido | Ejemplo | |---|---|---| | `latitude` | sí | `"37.44216251868683"` (grados decimales) | | `longitude` | sí | `"-122.16153582049394"` | | `name` | no | `"Philz Coffee"` | | `address` | no | `"101 Forest Ave, Palo Alto, CA 94301"` | Vista: tarjeta de mapa con las coordenadas; nombre y dirección se muestran como título/detalle. La página no especifica límites de caracteres ni renderizado adicional [7]. ## 5. Contacts Payload [8] — `type: "contacts"`, array `contacts[]` de objetos contacto. Cada mensaje puede incluir **hasta 257 contactos** (se recomienda menos por usabilidad). Único campo requerido por contacto: `name.formatted_name` (es lo que aparece en la burbuja junto al botón de flecha de perfil). Resto opcionales [8]: - `name`: `formatted_name`, `first_name`, `last_name`, `middle_name`, `suffix`, `prefix` - `phones[]`: `phone`, `type` (CELL/MAIN/IPHONE/HOME/WORK), `wa_id` — si falta `wa_id`, el botón Message/Save se sustituye por **"Invite to WhatsApp"** - `emails[]`: `email`, `type` (PERSONAL/WORK) - `urls[]`: `url`, `type` (COMPANY/WORK/PERSONAL/FACEBOOK_PAGE/INSTAGRAM) - `org`: `company`, `department`, `title` - `addresses[]`: `street`, `city`, `state`, `zip`, `country`, `country_code` (ISO-2), `type` - `birthday`: formato `YYYY-MM-DD` Vista: tarjeta de contacto con avatar, nombre formateado y filas por cada dato presente; algunos metadatos (direcciones, cumpleaños) pueden no mostrarse según el dispositivo del usuario [8]. ## 6. Interactive `type: "interactive"` + objeto `interactive` con `type` de: `button`, `list`, `cta_url`, `product`, `product_list`, `catalog_message`, `carousel`, `flow` (y `call_permission_request`) [17]. Objetos internos: `header` (`HeaderObject`: text/image/video/document; requerido para `product_list`, **no permitido** en `product`), `body` (`text`, requerido — "emojis y markdown soportados"), `footer` (`text`, opcional — "emojis, markdown y links soportados"), `action` (estructura varía por tipo) [17]. ### 6.1 Botones reply (quick replies) — `interactive.type: "button"` [10] ```json { "type": "interactive", "interactive": { "type": "button", "header": { "type": "text", "text": "Detalles" }, "body": { "text": "¿Confirmas tu cita?" }, "footer": { "text": "Elige una opción" }, "action": { "buttons": [ { "type": "reply", "reply": { "id": "id_si", "title": "Sí" } }, { "type": "reply", "reply": { "id": "id_no", "title": "No" } } ] } } } ``` | Campo | Límite | |---|---| | Botones | **máx 3** | | `reply.title` | **20 caracteres**, único entre botones | | `reply.id` | **256 caracteres**, único por botón | | `body.text` | **1024 caracteres** (URLs se hipervinculan) | | `footer.text` | **60 caracteres** | | `header` | tipos text/image/video/document (límite de header text no declarado en esta página) [10] | Vista: header arriba (media o texto), body, footer y los botones como filas-blanco fijas bajo la burbuja. Al tocar, webhook `messages` con `button_reply.id`/`title` + `context.id` del mensaje original [10]. ### 6.2 Lista — `interactive.type: "list"` [9] ```json { "type": "interactive", "interactive": { "type": "list", "header": { "type": "text", "text": "Menú" }, "body": { "text": "Selecciona un producto" }, "footer": { "text": "Catálogo 2026" }, "action": { "button": "Ver opciones", "sections": [ { "title": "Bebidas", "rows": [ { "id": "r1", "title": "Café", "description": "Chico" } ] } ] } } } ``` | Campo | Límite | |---|---| | Secciones | **mín 1, máx 10** | | Filas (total, sumando secciones) | **máx 10** | | `action.button` (etiqueta que despliega) | **20 caracteres** | | `header.text` | **60 caracteres** (solo type text) | | `body.text` | **4096 caracteres** | | `footer.text` | **60 caracteres** | | Título de sección | **24 caracteres** (requerido solo si hay >1 sección, [17]) | | `row.title` | **24 caracteres** | | `row.description` | opcional, **72 caracteres** | | `row.id` | **200 caracteres** | Vista: burbuja con header/body/footer y **un único botón** (`action.button`) que abre la lista de opciones seleccionables a pantalla (las filas muestran title y description); el webhook devuelve `list_reply` con `id`, `title`, `description` + `context` [9]. ### 6.3 CTA URL — `interactive.type: "cta_url"` [11] ```json "interactive": { "type": "cta_url", "header": { "type": "image", "image": { "link": "https://…/promo.jpg" } }, "body": { "text": "Aprovecha la promo" }, "footer": { "text": "Vence hoy" }, "action": { "name": "cta_url", "parameters": { "display_text": "Abrir tienda", "url": "https://mitienda.com" } } } ``` Límites: `display_text` **20 caracteres**; `body.text` **1024**; `footer.text` **60**; `header.text` **60**. Header opcional de tipo image/video/document/text. Un solo botón URL por acción; la doc menciona etiquetas únicas "si se usan múltiples botones" sin declarar máximo [11]. Vista: media/texto del header, body, footer y un botón azul que abre el navegador con la URL [11]. ### 6.4 Producto único — `interactive.type: "product"` [15] ```json "interactive": { "type": "product", "body": { "text": "Texto opcional" }, "footer": { "text": "Texto opcional" }, "action": { "catalog_id": "123456789", "product_retailer_id": "SKU-001" } } ``` `action` requiere `catalog_id` + `product_retailer_id` (SKU del producto); `header` **no permitido** en este tipo [15][17]; body/footer opcionales. Sin límites de caracteres declarados en la página [15]. Vista: tarjeta con imagen/nombre/precio actuales del producto; al tocar se abre una **Product Detail Page (PDP)** con los datos en tiempo real (solo imágenes; videos/GIF no se muestran); hay botón para escribir al negocio; reenviable, no puede enviarse como notificación [15]. ### 6.5 Multi-producto — `interactive.type: "product_list"` [16] ```json "interactive": { "type": "product_list", "header": { "type": "text", "text": "Nuestra tienda" }, "body": { "text": "Elige productos" }, "footer": { "text": "Envío gratis" }, "action": { "catalog_id": "123456789", "sections": [ { "title": "Cafés", "product_items": [ { "product_retailer_id": "SKU-001" } ] } ] } } ``` Requeridos: header type **text**, body, `action.catalog_id` + `sections[]` (`title` + `product_items[].product_retailer_id`). Límite documentado: **hasta 30 productos** en secciones; máximo de secciones y límites de texto NO declarados en la página (el título de sección es el `SectionObject.title` de máx 24 chars según [17]). Si el SKU no existe se descarta y llega error pidiendo actualización de catálogo [16]. Vista: carrusel horizontal de productos que abre PDP y permite armar carrito por dispositivo (el carrito no sincroniza entre dispositivos) [16]. ### 6.6 Catálogo — `interactive.type: "catalog_message"` [14] ```json "interactive": { "type": "catalog_message", "body": { "text": "Explora nuestro catálogo" }, "action": { "name": "catalog_message", "parameters": { "thumbnail_product_retailer_id": "SKU-001" } }, "footer": { "text": "Tienda oficial" } } ``` `body.text` máx **1024**; `footer.text` máx **60**; `thumbnail_product_retailer_id` opcional (define la miniatura; si falta se usa la imagen del primer artículo del catálogo) [14]. Vista: miniatura de producto, texto fijo de encabezado, body, footer y botón **"View catalog"** que abre el catálogo completo dentro de WhatsApp [14]. ### 6.7 Carrusel de productos — `interactive.type: "carousel"` (cards tipo product) [13] ```json "interactive": { "type": "carousel", "body": { "text": "Lo más vendido" }, "action": { "cards": [ { "card_index": 0, "type": "product", "action": { "product_retailer_id": "SKU-001", "catalog_id": "123456789" } } ] } } ``` Límites: **2 a 10 cards**; `card_index` entero **0–9**, sin repetir; todas las cards deben referenciar el **mismo `catalog_id`**; `body.text` máx **1024**. **Sin header, footer ni botones** a nivel de mensaje [13]. Vista: tarjetas desplazables horizontalmente, cada una abre su PDP [13][15]. ### 6.8 Carrusel de media — cards con header image/video [12] ```json "interactive": { "type": "carousel", "body": { "text": "Nuevos cursos" }, "action": { "cards": [ { "card_index": 0, "header": { "type": "image", "image": { "link": "https://…/a.jpg" } }, "body": { "text": "Curso A" }, "action": { "name": "cta_url", "parameters": { "display_text": "Inscribirme", "url": "https://…" } } } ] } } ``` Límites exactos [12]: **2–10 cards**; header por card **solo image o video** (`link` o `id`); body por card máx **160 caracteres y 2 saltos de línea**; body del mensaje máx **1024**; quick-reply `id` máx **256**, etiquetas (quick reply y URL) máx **20**; cada card lleva **un botón URL o uno o más quick replies**; tipos y cantidades de botones deben ser idénticos en todas las cards. Sin header/footer a nivel de mensaje. Vista: cards con media arriba, texto y botón, desplazables izquierda→derecha desde índice 0 [12]. ## 7. Template messages Único tipo enviable **fuera de la ventana de servicio** al cliente; se crean vía Template API o WhatsApp Manager y deben quedar `APPROVED` antes de enviarse [19]. Creación: `name` (máx 512, minúsculas/guiones bajos), `category` (AUTHENTICATION/MARKETING/UTILITY), `language`, `parameter_format` (`named` p.ej. `{{first_name}}`, o `positional` p.ej. `{{1}}`) y `components` [19]. Límites de cuenta: **250 plantillas/WABA** (6000 con portafolio verificado + display name aprobado), **100 plantillas creadas por hora** por WABA [19]. ### 7.1 Envío por Cloud API [21] ```json { "messaging_product": "whatsapp", "recipient_type": "individual", "to": "16505551234", "type": "template", "template": { "name": "reservation_confirmation", "language": { "code": "en_US" }, "components": [ { "type": "header", "parameters": [ { "type": "image", "image": { "id": "2871834006348767" } } ] }, { "type": "body", "parameters": [ { "type": "text", "parameter_name": "day", "text": "Saturday" } ] }, { "type": "buttons", "sub_type": "URL", "index": 0, "parameters": [ { "type": "text", "text": "abc123" } ] } ] } } ``` El header solo se envía si la plantilla usa header de media (image/video/document; los header text/location no llevan parámetros en el envío) [21]. En plantillas posicionales los parámetros van por orden, sin `parameter_name` [21]. En webhook los botones responden con `button_reply`/`list_reply`; COPY_CODE entrega el código y CATALOG/MPM abren catálogo (los sub_types de botón definidos por la API son: `CATALOG`, `COPY_CODE`, `FLOW`, `MPM`, `OTP`, `PHONE_NUMBER`, `QUICK_REPLY`, `URL` [18]). ### 7.2 Componentes y límites de caracteres (creación) [20] | Componente | Formatos / tipos | Límites | |---|---|---| | **HEADER** (1 máx) | `format`: TEXT, IMAGE, VIDEO, DOCUMENT, LOCATION | TEXT: **60 caracteres**, sin markdown, admite 1 parámetro. Media: handle de Resumable Upload API (GIF mp4 ≤3.5 MB, solo Marketing). LOCATION: sin parámetros al crear; al enviar `latitude`, `longitude`, `name`, `address`; solo UTILITY/MARKETING | | **BODY** (requerido, 1) | texto | **1024 caracteres**; parámetros múltiples named/posicionales con ejemplos obligatorios | | **FOOTER** (opcional, 1) | texto | **60 caracteres** | | **BUTTONS** (array `buttons`) | ver abajo | **máx 10 botones en total** por plantilla | Botones por tipo [20]: - **QUICK_REPLY**: hasta **10**; etiqueta máx **25 caracteres**; deben agruparse (no intercalar `QR, URL, QR`); el orden en el teléfono lo define `index` al enviar. - **URL**: hasta **2**; etiqueta 25; `url` máx **2000 caracteres**, admite **1 variable** al final (requiere `example`; valores con caracteres especiales deben ir percent-encoded: `%20`, `%3A`, `%7C`… o el envío falla). El título corto del botón puede sobreescribirse (`tap-target-url-title-override`). - **PHONE_NUMBER**: solo **1**; `phone_number` máx **20 caracteres** (se recortan ceros a la izquierda tras el código de país); etiqueta 25. - **COPY_CODE**: solo **1**; código copiable en `example`, **máx 20 caracteres**. - **CATALOG**: abre el catálogo; **MPM** (multi-producto) muestra hasta **30 productos en hasta 10 secciones**; ambos no personalizables. - **VOICE_CALL**: inicia llamada de WhatsApp al negocio; **OTP** (URL/ONE_TAP/ZERO_TAP) para plantillas de autenticación, con `autofill_text`, `package_name`, `signature_hash`. Rendimiento en pantalla [20]: con **>3 botones** WhatsApp muestra 2 y un botón **"See all options"** que expande el resto; plantillas con **4+ botones**, o quick replies mezcladas con otros tipos, **no se ven en clientes de escritorio**. Vista general: header arriba del body; body con variables resaltadas; footer en gris pequeño; botones como filas fijas al pie de la burbuja [20]. ### 7.3 Plantillas de carrusel (marketing) Existen `media-card-carousel-templates` (cards de media) y `product-card-carousel-template-messages` [19]; su estructura de componentes en la Template API incluye `type: CAROUSEL` y `LIMITED_TIME_OFFER` [18]. Detalle no extraído en esta investigación (fuera del alcance directo). ## 8. Tabla resumen de límites clave | Elemento | Límite | Fuente | |---|---|---| | `text.body` / body de lista | 4096 | [1][9] | | Caption de image/video/document | 1024 | [2][3][5] | | Tamaño image / video / audio / document | 5 MB / 16 MB / 16 MB / 100 MB | [2][3][4][5] | | Sticker WebP animado / estático | 500 KB / 100 KB | [6] | | Contactos por mensaje | 257 | [8] | | Botones reply / list rows / secciones | 3 / 10 / 10 | [10][9] | | Título botón (interactive) / display_text | 20 / 20 | [10][11][12] | | `reply.id` / `row.id` | 256 / 200 | [10][9] | | Header / footer interactivos | 60 / 60 | [9][11] | | Section title / row title / row description | 24 / 24 / 72 | [9][17] | | Body de card de carrusel de media | 160 (2 saltos) | [12] | | Cards de carrusel | 2–10 (índices 0–9) | [12][13] | | Productos por product_list / MPM | 30 (en ≤10 secciones) | [16][20] | | Plantilla: header TEXT / body / footer | 60 / 1024 / 60 | [20] | | Plantilla: botones totales / QR / URL / PHONE / COPY_CODE | 10 / 10 / 2 / 1 / 1 | [20] | | Plantilla: etiqueta botón / URL / phone / código | 25 / 2000 / 20 / 20 | [20] | | Plantillas por WABA / creación por hora | 250 (6000 verificada) / 100 | [19] | ## 9. Fuentes consultadas (oficiales, developers.facebook.com) [1] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/text-messages [2] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/image-messages [3] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/video-messages [4] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/audio-messages [5] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/document-messages [6] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/sticker-messages [7] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/location-messages [8] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/contacts-messages [9] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-list-messages [10] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-reply-buttons-messages [11] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-cta-url-messages [12] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-media-carousel-messages.md [13] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/interactive-product-carousel-messages.md [14] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/catalog-messages.md [15] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/single-product-messages.md [16] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/multi-product-messages.md [17] https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-phone-number/message-api.md [18] https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-account/message-template-api.md [19] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/overview.md [20] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/components.md [21] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/utility-templates/utility-templates.md [22] https://developers.facebook.com/documentation/business-messaging/whatsapp/link-previews.md **Declaraciones de cobertura**: (a) la sintaxis de formateo de texto (*bold*, _italic_, ~tachado~, mono) ya no está documentada en las páginas oficiales consultadas — solo consta la nota de que body/footer interactivos soportan markdown [17] y la prohibición de markdown en header TEXT de plantillas [20]; (b) límites no declarados: máximo de secciones en product_list, límites de texto en `product`, límite de header text en `interactive.type: button`, y máximo de botones en `cta_url` — se reportan como no documentados, no como valores asumidos; (c) varias páginas nuevas (carousel-messages, product-messages en su slug HTML) solo renderizan con JavaScript y se accedió a su contenido vía las versiones `.md` publicadas por Meta en el índice `llms.txt`.