Enviar y recibir archivos por WhatsApp

Imagen, video, audio y documento, con ejemplos de envío y del evento que recibes

Cómo funciona

Enviar. Mandas la URL pública del archivo y Meta lo descarga desde ahí.

Flujo de envío

Recibir. Pontiun guarda el archivo y después llama a tu webhook con un link listo para abrir.

Flujo de recepción

Antes de enviar

  • Autentica con Authorization: Bearer pk_live_….
  • Idempotency-Key es obligatoria. Si reintentas con la misma key, no se manda un duplicado.
  • Destino: conversationId (del webhook) o pageId + recipientId (teléfono con código de país).
  • Mandas texto (reply) o un adjunto (attachment), nunca los dos.
  • caption es el pie de foto. Funciona en imagen, video y archivo; en audio da 400. Máximo 1024 caracteres.
  • La URL debe ser https y pública. Meta la cachea unos 10 minutos, así que no uses links que venzan en segundos.
  • Si el contacto no te escribió en las últimas 24 h, la respuesta es 409 con requiresTemplate: true. En ese caso usa una plantilla.

Imagen

Enviar

curl -X POST https://pontiun.com/api/meta/whatsapp/send \
  -H "Authorization: Bearer pk_live_<secreto>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-8841-foto" \
  -d '{
    "conversationId": "6f0e5a2c-8a5e-4a3d-9c2b-1f2e3d4c5b6a",
    "attachment": {
      "type": "image",
      "url": "https://cdn.example.com/pedidos/8841.jpg",
      "caption": "Así quedó tu pedido #8841"
    }
  }'

Recibir. El pie de foto llega en message.text.

"message": {
  "id": "cce03202-3f6d-4379-b85e-6cc11063ccd5",
  "text": "¿La tienen en rojo?",
  "attachment": {
    "type": "image",
    "url": "https://pontiun.com/api/meta/whatsapp/media/cce03202-3f6d-4379-b85e-6cc11063ccd5?exp=1792526083&sig=1pQ2o3r4S5t6",
    "title": null,
    "details": {
      "status": "available",
      "mimeType": "image/jpeg",
      "sizeBytes": 32671,
      "urlExpiresAt": "2026-10-20T19:54:43.000Z"
    }
  }
}

Video

Enviar

curl -X POST https://pontiun.com/api/meta/whatsapp/send \
  -H "Authorization: Bearer pk_live_<secreto>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: demo-producto-12" \
  -d '{
    "conversationId": "6f0e5a2c-8a5e-4a3d-9c2b-1f2e3d4c5b6a",
    "attachment": {
      "type": "video",
      "url": "https://cdn.example.com/videos/demo.mp4",
      "caption": "Así se arma"
    }
  }'

Recibir

"attachment": {
  "type": "video",
  "url": "https://pontiun.com/api/meta/whatsapp/media/<id>?exp=…&sig=…",
  "details": {
    "status": "available",
    "mimeType": "video/mp4",
    "sizeBytes": 2483120,
    "urlExpiresAt": "2026-10-20T19:54:43.000Z"
  }
}

Audio

Enviar. No uses caption.

curl -X POST https://pontiun.com/api/meta/whatsapp/send \
  -H "Authorization: Bearer pk_live_<secreto>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: audio-bienvenida-77" \
  -d '{
    "conversationId": "6f0e5a2c-8a5e-4a3d-9c2b-1f2e3d4c5b6a",
    "attachment": {
      "type": "audio",
      "url": "https://cdn.example.com/audios/bienvenida.mp3"
    }
  }'

Recibir. voice: true indica que es una nota de voz.

"attachment": {
  "type": "audio",
  "url": "https://pontiun.com/api/meta/whatsapp/media/<id>?exp=…&sig=…",
  "details": {
    "status": "available",
    "mimeType": "audio/ogg; codecs=opus",
    "voice": true,
    "sizeBytes": 18234,
    "urlExpiresAt": "2026-10-20T19:54:43.000Z"
  }
}

Archivo (PDF y otros documentos)

Enviar. Usa type: "file"; WhatsApp lo muestra como documento.

curl -X POST https://pontiun.com/api/meta/whatsapp/send \
  -H "Authorization: Bearer pk_live_<secreto>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: factura-8841" \
  -d '{
    "conversationId": "6f0e5a2c-8a5e-4a3d-9c2b-1f2e3d4c5b6a",
    "attachment": {
      "type": "file",
      "url": "https://cdn.example.com/facturas/8841.pdf",
      "caption": "Tu factura del pedido #8841"
    }
  }'

Recibir. filename es el nombre con el que lo mandó el contacto.

"attachment": {
  "type": "file",
  "url": "https://pontiun.com/api/meta/whatsapp/media/<id>?exp=…&sig=…",
  "details": {
    "status": "available",
    "mimeType": "application/pdf",
    "filename": "comprobante.pdf",
    "sizeBytes": 84512,
    "urlExpiresAt": "2026-10-20T19:54:43.000Z"
  }
}

Respuesta del envío

Es igual para los cuatro tipos:

{
  "meta": { "messages": [{ "id": "wamid.HBgN…" }] },
  "resender": {
    "conversationId": "6f0e5a2c-8a5e-4a3d-9c2b-1f2e3d4c5b6a",
    "messageId": "0c9d2f6e-3b7a-4e1d-8f5c-2a1b3c4d5e6f",
    "status": "sent"
  }
}

Vencimiento del link

CampoQué es
expVencimiento del link, en segundos epoch. Viene incluido en la URL.
sigFirma del link. Si la modificas, el link deja de funcionar.
details.urlExpiresAtEl mismo vencimiento en ISO 8601: 24 h después de la entrega.
  • Durante las primeras 24 h, el link se abre tal cual, sin cabeceras: en el navegador, en un <img> o en n8n.
  • Después de las 24 h, quita exp y sig y manda tu API key:
curl https://pontiun.com/api/meta/whatsapp/media/cce03202-3f6d-4379-b85e-6cc11063ccd5 \
  -H "Authorization: Bearer pk_live_<secreto>" \
  -o foto.jpg
  • El archivo se guarda 180 días. Después la ruta responde 409 con status: deleted.
  • Quien tenga el link puede abrir el archivo hasta que vence, así que no lo publiques.
  • Soporta Range: puedes adelantar un audio o un video en el reproductor.

No necesitas providerMediaId

El link ya apunta a tu archivo. No necesitas una app ni un token de Meta para descargarlo.

Si el archivo no se pudo bajar

Pontiun espera hasta 2 minutos a que el archivo esté listo. Si no lo consigue, el evento llega igual, con url: null:

"attachment": {
  "type": "file",
  "url": null,
  "details": { "status": "failed", "failureReason": "media_download_timeout" }
}
details.statusurlSignificado
availablelink firmadoListo para descargar.
failednullNo se pudo bajar de WhatsApp.
unavailablenullWhatsApp no lo envió (historial de más de 14 días).
deletednullPasaron los 180 días.

Orden de los mensajes

Orden por conversación

  • Los mensajes de una conversación llegan en el orden en que se escribieron. Un texto que llega después de una foto espera a que la foto esté lista.
  • Las otras conversaciones no esperan.
  • Si recibes un mensaje que Meta entregó tarde, ordena por message.createdAt.

Más detalle

On this page