← Blog

·

Cómo enviar imágenes, PDF, audio y video con la API de WhatsApp

Actualizado el 25/10/2026

Para enviar un archivo con la API de WhatsApp, haces un POST al endpoint de mensajes con type igual a image, document, audio o video e indicas el archivo de dos maneras: con el id de un medio que subiste antes al endpoint /media o con un link público. Meta recomienda subir el archivo y usar el id, y acepta imágenes JPEG y PNG de hasta 5 MB, audio y video de hasta 16 MB y documentos de hasta 100 MB. Fuera de la ventana de 24 horas, el archivo solo puede ir como encabezado de una plantilla aprobada.

Esta guía muestra los formatos aceptados, cuándo subir o enlazar, cuánto dura un media ID, cómo recibir y descargar los archivos que envía el cliente y ejemplos listos en cURL, Node.js y Python.

Carga o enlace: las dos formas de enviar multimedia

Todo mensaje multimedia de la Cloud API lleva un objeto con el nombre del tipo (image, document, audio, video o sticker). Dentro va uno de estos campos, nunca los dos:

CampoQué esCuándo usarlo
idID que devuelve POST /<PHONE_NUMBER_ID>/media después de la cargaRecomendado por Meta. Archivos reutilizados en muchos envíos, campañas, archivos privados
linkURL HTTPS pública donde está alojado el archivoEnvíos puntuales, archivos que ya están en un CDN. Meta marca esta opción como «no recomendada» por rendimiento

Con link, los servidores de Meta tienen que descargar el archivo de tu servidor en el momento del envío. Si la URL pide inicio de sesión, redirige a una página HTML o devuelve un Content-Type distinto del archivo real, el envío falla. Con id, el archivo ya está en Meta y el envío no depende de que tu servidor esté disponible.

Un patrón habitual: el archivo que va a mucha gente (el catálogo en PDF, el video tutorial) se sube una vez a /media y el id se reutiliza mientras esté vigente. Los archivos generados al momento (una factura, un comprobante) van por un link firmado de corta duración o por una carga justo antes del envío.

Formatos y límites de tamaño oficiales

La tabla resume la página de multimedia de la Cloud API:

TipoFormatos (MIME)Tamaño máximo
Imagenimage/jpeg, image/png (8 bits, RGB o RGBA)5 MB
Documentoapplication/pdf, text/plain, Word (.doc, .docx), Excel (.xls, .xlsx), PowerPoint (.ppt, .pptx)100 MB
Audioaudio/aac, audio/amr, audio/mpeg (MP3), audio/mp4 (M4A), audio/ogg (solo códec OPUS, mono)16 MB
Videovideo/mp4, video/3gpp (video H.264 y audio AAC)16 MB
Stickerimage/webp100 KB estático, 500 KB animado

Detalles que suelen provocar fallas:

  • Pie de foto. caption admite hasta 1.024 caracteres en imagen, video y documento. El audio no lleva pie.
  • Documento. El campo filename define el nombre que se muestra, y su extensión elige el ícono en la app. Solo los tipos de la tabla tienen visualización garantizada; otros se pueden enviar, pero Meta no garantiza cómo se verán.
  • Video en Android. Meta advierte que el perfil H.264 «High» con B-frames no es compatible con WhatsApp en Android. Usa el perfil «Main» sin B-frames o «Baseline» y coloca el átomo moov antes de mdat (en ffmpeg, -movflags faststart).
  • MIME incorrecto. Si la extensión o el tipo declarado no coincide con el contenido real, el envío falla con el error 131053. En Linux o macOS, file -I archivo.png muestra el tipo real.

Conversión de un video al formato más compatible:

ffmpeg -i entrada.mov -c:v libx264 -profile:v main -bf 0 \
  -c:a aac -ac 2 -movflags faststart salida.mp4

Audio común y mensaje de voz

La Cloud API distingue dos tipos de audio, según la documentación de mensajes de audio:

  • Audio común. Se muestra con ícono de descarga y de música. Acepta cualquier formato de la tabla.
  • Mensaje de voz. Envía "voice": true dentro del objeto audio. El archivo debe ser .ogg con códec OPUS, mono. Se muestra con la foto del perfil de la empresa y el ícono de micrófono, se descarga automáticamente y puede transcribirse en la app del cliente. El botón de reproducir solo aparece en archivos de hasta 512 KB; por encima de eso, el cliente ve el ícono de descarga.

Para convertir un MP3 en nota de voz compatible:

ffmpeg -i audio.mp3 -c:a libopus -ac 1 -b:a 32k voz.ogg

Paso 1: subir el archivo y obtener el media ID

La carga es un multipart/form-data con tres campos obligatorios: file, type (el MIME) y messaging_product=whatsapp.

curl -X POST "https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/media" \
  -H "Authorization: Bearer $WHATSAPP_TOKEN" \
  -F "file=@catalogo.pdf;type=application/pdf" \
  -F "type=application/pdf" \
  -F "messaging_product=whatsapp"

Respuesta:

{ "id": "1037543291543636" }

El token necesita el permiso whatsapp_business_messaging. En producción, usa un token permanente de usuario del sistema en lugar del token temporal del panel.

Cuánto dura un media ID

Origen del IDVigencia
Carga hecha por ti30 días (el archivo queda cifrado hasta que se elimine o venza)
Multimedia recibida por webhook7 días para descargarla
URL de descarga obtenida con GET /<MEDIA_ID>5 minutos

Guarda la fecha de carga junto con el id y vuelve a subir el archivo antes de los 30 días si lo vas a usar más tiempo. Para borrarlo antes, usa DELETE /<MEDIA_ID>.

Paso 2: enviar el mensaje multimedia

Con el id, el envío es igual al de un mensaje de texto por la API, cambiando el tipo:

curl -X POST "https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/messages" \
  -H "Authorization: Bearer $WHATSAPP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "5215512345678",
    "type": "document",
    "document": {
      "id": "1037543291543636",
      "filename": "catalogo-octubre.pdf",
      "caption": "Te enviamos el catálogo de octubre"
    }
  }'

La respuesta trae el wamid del mensaje. Solo confirma que Meta aceptó la solicitud; la entrega, la lectura y las fallas llegan después por webhook, como explica el artículo sobre estados de mensaje por webhook.

Ejemplo en Node.js (carga + envío)

Usa fetch, FormData y Blob nativos de Node.js 18 o superior:

import { readFile } from 'node:fs/promises';

const GRAPH = 'https://graph.facebook.com/v26.0';
const PHONE_ID = process.env.PHONE_NUMBER_ID;
const TOKEN = process.env.WHATSAPP_TOKEN;

async function subirMedio(ruta, mime) {
  const form = new FormData();
  form.append('messaging_product', 'whatsapp');
  form.append('type', mime);
  form.append('file', new Blob([await readFile(ruta)], { type: mime }), ruta.split('/').pop());

  const r = await fetch(`${GRAPH}/${PHONE_ID}/media`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${TOKEN}` },
    body: form,
  });
  const cuerpo = await r.json();
  if (!r.ok) throw new Error(JSON.stringify(cuerpo.error));
  return cuerpo.id;
}

async function enviarImagen(para, mediaId, pie) {
  const r = await fetch(`${GRAPH}/${PHONE_ID}/messages`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      messaging_product: 'whatsapp',
      to: para,
      type: 'image',
      image: { id: mediaId, caption: pie },
    }),
  });
  return r.json();
}

const id = await subirMedio('./producto.jpg', 'image/jpeg');
console.log(await enviarImagen('5215512345678', id, 'Llegó el nuevo modelo'));

Ejemplo en Python (enlace público y nota de voz)

import os
import requests

GRAPH = "https://graph.facebook.com/v26.0"
PHONE_ID = os.environ["PHONE_NUMBER_ID"]
HEADERS = {"Authorization": f"Bearer {os.environ['WHATSAPP_TOKEN']}"}


def enviar(payload: dict) -> dict:
    payload = {"messaging_product": "whatsapp", **payload}
    r = requests.post(f"{GRAPH}/{PHONE_ID}/messages", json=payload, headers=HEADERS, timeout=30)
    r.raise_for_status()
    return r.json()


# Video alojado en tu CDN
enviar({
    "to": "5215512345678",
    "type": "video",
    "video": {"link": "https://cdn.ejemplo.com/tutorial.mp4", "caption": "Cómo instalar"},
})

# Nota de voz a partir de una carga
with open("voz.ogg", "rb") as f:
    up = requests.post(
        f"{GRAPH}/{PHONE_ID}/media",
        headers=HEADERS,
        data={"messaging_product": "whatsapp", "type": "audio/ogg"},
        files={"file": ("voz.ogg", f, "audio/ogg")},
        timeout=60,
    )
up.raise_for_status()
enviar({"to": "5215512345678", "type": "audio", "audio": {"id": up.json()["id"], "voice": True}})

Multimedia fuera de la ventana de 24 horas: encabezado de plantilla

Los mensajes de imagen, video, audio y documento son mensajes libres. Solo se pueden enviar con la ventana de atención de 24 horas abierta por el cliente. Para mandar un archivo a alguien que no te escribió en las últimas 24 horas, crea una plantilla con encabezado multimedia (imagen, video o documento) y completa el archivo en el envío:

{
  "messaging_product": "whatsapp",
  "to": "5215512345678",
  "type": "template",
  "template": {
    "name": "copia_factura",
    "language": { "code": "es_MX" },
    "components": [
      {
        "type": "header",
        "parameters": [
          { "type": "document", "document": { "id": "1037543291543636", "filename": "factura.pdf" } }
        ]
      },
      { "type": "body", "parameters": [{ "type": "text", "text": "María" }] }
    ]
  }
}

En Brasil, así es como las empresas envían el boleto (comprobante de pago bancario) en PDF a clientes que no escribieron hace poco. Las categorías y la aprobación de plantillas se explican en cómo Meta clasifica tu plantilla.

Recibir y descargar archivos que envía el cliente

Cuando el cliente manda una foto, un PDF o un audio, el webhook trae el objeto del tipo con id, mime_type y sha256 (y caption o filename, cuando existan):

{
  "from": "5215512345678",
  "id": "wamid.HBgM...",
  "type": "image",
  "image": { "id": "1489362375523190", "mime_type": "image/jpeg", "sha256": "8f2c..." }
}

Descargarlo requiere dos llamadas:

# 1. Obtener la URL temporal (vale 5 minutos)
curl "https://graph.facebook.com/v26.0/1489362375523190" \
  -H "Authorization: Bearer $WHATSAPP_TOKEN"

# 2. Descargar el binario de la URL devuelta, con el mismo token
curl -L "URL_DEVUELTA" -H "Authorization: Bearer $WHATSAPP_TOKEN" -o foto.jpg

Sin el header Authorization, la descarga falla. Si da 404, pide una URL nueva y vuelve a intentar. Descarga enseguida y guarda el archivo en tu almacenamiento: el ID recibido vence a los 7 días. El límite de multimedia entrante es de 100 MB; por encima, el webhook llega con el error 131052, y lo ideal es pedirle al cliente un archivo más pequeño.

Errores más comunes al enviar multimedia

SíntomaCausa probableQué hacer
Error 131053MIME declarado distinto del contenido o formato no compatibleRevisa el tipo real del archivo y usa un formato de la tabla
Error 131052 (multimedia entrante)Archivo del cliente de más de 100 MBPide un archivo más pequeño
Falla el envío con linkURL privada, redirección a HTML, certificado inválidoPrueba la URL con curl -I desde fuera de tu red o sube el archivo
Falla el envío con idID vencido (más de 30 días) o subido en otro númeroVuelve a subirlo con el mismo phone_number_id
El video no abre en AndroidH.264 High con B-framesRecodifica en Main o Baseline
El audio llega sin botón de reproducirArchivo de más de 512 KB o fuera de OGG OPUSBaja el bitrate y envíalo como voice

Para la lista completa de códigos, consulta errores de la API de WhatsApp.

Cómo hacerlo con Vectalk

En Vectalk, los payloads multimedia son los mismos de la Cloud API. Cambian la URL base y el token:

  • Carga: POST https://apis.vectalk.com.br/api/media (multipart, con file, type y messaging_product), con un token de instancia.
  • Envío: POST https://apis.vectalk.com.br/api/messages con el mismo JSON de imagen, documento, audio o video.
  • Multimedia recibida: GET /api/media/{mediaId} devuelve la URL temporal, y GET /api/media/{mediaId}/download devuelve el binario directamente.
  • Eliminar: DELETE /api/media/{mediaId}.
curl -X POST https://apis.vectalk.com.br/api/media \
  -H "Authorization: Bearer $VECTALK_TOKEN" \
  -F "file=@producto.jpg" \
  -F "type=image/jpeg" \
  -F "messaging_product=whatsapp"

Las rutas están en Carga de multimedia e Imagen (documentación en portugués). El costo de los mensajes se incluye en la factura de Vectalk, sin tarjeta registrada en Meta. Para empezar, crea tu cuenta en apps.vectalk.com.br/register.

Preguntas frecuentes

¿Puedo enviar una imagen WebP?

No como mensaje de imagen. La Cloud API acepta JPEG y PNG para imágenes. WebP se usa solo en stickers. Conviértela antes de subirla.

¿Cuál es el tamaño máximo de un PDF en la API de WhatsApp?

100 MB, el mismo límite de todos los documentos compatibles (PDF, TXT, Word, Excel y PowerPoint).

¿Enviar multimedia cuesta más que enviar texto?

No. Meta cobra por mensaje entregado según su categoría, no por el tipo de contenido. Una imagen enviada dentro de la ventana de atención es un mensaje de servicio, igual que un texto libre: desde el 1 de octubre de 2026, cada número tiene 1.000 mensajes de servicio gratis al mes, y el cobro empieza en el 1.001. El cálculo está en cuánto cuesta una campaña de WhatsApp.

¿Puedo reutilizar el mismo media ID en miles de envíos?

Sí, mientras esté vigente (30 días después de la carga). Es la forma recomendada para campañas con el mismo archivo, porque evita que Meta descargue el archivo de tu servidor en cada envío.

¿Cómo envío varios archivos en un mismo mensaje?

No existe un tipo de mensaje de álbum. Cada archivo es un mensaje aparte, con su propio wamid y estado.


Fuentes oficiales consultadas el 25/10/2026: Media (Cloud API), Image messages, Document messages, Audio messages, Video messages, Documentación de Vectalk: carga de multimedia.

Integre o WhatsApp oficial ao seu sistema

A Vectalk entrega a Cloud API da Meta com os mesmos payloads e webhooks, um token para todas as contas e documentação completa.