Saltar a contenido

Enviar mensajes

POST /messages — encola un mensaje de WhatsApp para un destinatario. La respuesta es inmediata (el envío real lo hace el worker de Arplyx); el estado se sigue desde el portal o vía los estados del mensaje.

Request

{
  "externalId": "pedido-10045",
  "channel": "whatsapp_meta",
  "to": { "type": "phone", "phoneE164": "+15550100123" },
  "content": { "type": "text", "text": "Hola! Tu pedido fue confirmado." },
  "whatsappAccountId": "0b8e2c1a-...",
  "metadata": { "orderId": 10045 },
  "ttlSeconds": 86400
}

Campos

Campo Tipo Requerido Default Detalle
externalId string Sí — Tu identificador único (1–200 caracteres). Base de la idempotencia.
channel string No whatsapp_meta whatsapp_meta.
to.type string Sí — Siempre phone.
to.phoneE164 string Sí — Número en formato E.164: + seguido de 7 a 15 dígitos (ej.: +15550100123).
content.type string Sí — text, template, image o document (ver abajo).
content.text string Sí para text — Cuerpo del mensaje, 1–10.000 caracteres.
whatsappAccountId string (UUID) Depende — Solo si tenés más de una cuenta Meta conectada. Debe ser una cuenta tuya (si no: 422).
metadata object No — Datos arbitrarios tuyos; se guardan junto al mensaje y se ven en el portal.
ttlSeconds int No 604800 (7 días) Vigencia del mensaje en cola. Máximo 30 días; además se recorta por la retención de tu plan (Free: 3 días).

Mensajes de plantilla (template)

Las plantillas (HSM de Meta, solo canal whatsapp_meta) son lo que te permite iniciar conversaciones — enviar fuera de la ventana de 24 h, sin que el usuario haya escrito primero.

{
  "externalId": "pedido-10045",
  "channel": "whatsapp_meta",
  "content": {
    "type": "template",
    "template": {
      "name": "pedido_confirmado",
      "language": "es_AR",
      "components": { "body": ["Juan", "10045"] }
    }
  },
  "to": { "type": "phone", "phoneE164": "+15550100123" }
}
  • name y language: nombre y código de idioma de la plantilla, tal como figuran en tu WhatsApp Manager.
  • components.body (y components.header): los valores de las variables ({{1}}, {{2}}…) en orden. En el ejemplo, {{1}} = "Juan" y {{2}} = "10045".

Las plantillas se crean en Meta

La plantilla tiene que estar creada y aprobada en tu WhatsApp Manager antes de usarla; Arplyx la envía por nombre. La aprobación y el costo por conversación corren por tu cuenta de Meta (sos dueño de la WABA).

Disponible en planes pagos

El envío de plantillas (mensajería proactiva) está disponible desde el plan Starter. En el plan Free, Meta solo responde dentro de la ventana de 24 h: un intento de enviar una plantilla devuelve 403 templates_not_available.

Imágenes y documentos

Además de texto, podés enviar una imagen (JPEG o PNG) o un documento (PDF, Office, texto plano) por cualquiera de los dos canales. El archivo se referencia de una de dos formas, excluyentes: por URL pública HTTPS (el proveedor lo descarga en el momento del envío) o por mediaId de un archivo que subiste antes con POST /media. Disponible en todos los planes; cuenta como un mensaje más contra tu cuota.

{
  "externalId": "pedido-10045-foto",
  "channel": "whatsapp_meta",
  "to": { "type": "phone", "phoneE164": "+15550100123" },
  "content": {
    "type": "image",
    "image": { "url": "https://cdn.tuempresa.com/pedidos/10045/foto.jpg" },
    "caption": "Tu pedido salió a reparto."
  },
  "whatsappAccountId": "TU_ACCOUNT_ID"
}
{
  "externalId": "factura-A-0001-00012345",
  "channel": "whatsapp_meta",
  "to": { "type": "phone", "phoneE164": "+15550100123" },
  "content": {
    "type": "document",
    "document": {
      "url": "https://cdn.tuempresa.com/facturas/A-0001-00012345.pdf",
      "filename": "Factura A-0001-00012345.pdf"
    },
    "caption": "Te adjunto la factura de este mes."
  },
  "whatsappAccountId": "TU_ACCOUNT_ID"
}
Campo Tipo Requerido Detalle
content.image.url / content.document.url string Uno de los dos URL pública HTTPS (sin login, sin host privado), hasta 2048 caracteres. Tiene que responder directamente con el archivo; se siguen hasta 3 redirects.
content.image.mediaId / content.document.mediaId string (UUID) Uno de los dos Id devuelto por POST /media. Si no existe, no es tuyo o no es una imagen cuando el tipo es image: 422 invalid_media.
content.caption string No Texto que acompaña al archivo, hasta 1024 caracteres.
content.document.filename string No Nombre con el que el destinatario ve el archivo (hasta 255 caracteres). Default: el nombre subido o el último segmento de la URL.

Límites y formatos

  • Imágenes: JPEG o PNG, hasta 5 MB. Se detecta el formato por el contenido, no por la extensión.
  • Documentos: PDF, Word, Excel, PowerPoint o texto plano, hasta 20 MB. Meta acepta solo esa lista.
  • Si la URL no se puede descargar (404, tamaño excedido, formato inválido), el mensaje pasa a failed con lastErrorCode: MEDIA_UNAVAILABLE y no se reintenta. Corregí la URL y volvé a enviar con un externalId nuevo.

Ventana de 24 h en Meta Official

Una imagen o un documento es un mensaje libre, igual que el texto: por whatsapp_meta solo llega dentro de la ventana de 24 h. Fuera de ella seguís necesitando una plantilla.

Respuesta

201 Created (mensaje nuevo) o 200 OK (repetición idempotente — mismo externalId y payload):

{
  "messageId": "7f9b3c30-...",
  "externalId": "pedido-10045",
  "status": "pending",
  "queued": true
}

El messageId es el ID interno de Arplyx; te sirve para ubicar el mensaje en el portal. Los errores posibles (400, 401, 409, 422, 429) están catalogados en Errores y estados.

Ejemplos

curl -X POST https://api.arplyx.com/messages \
  -H "x-api-key: $ARPLYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "pedido-10045",
    "channel": "whatsapp_meta",
    "to": { "type": "phone", "phoneE164": "+15550100123" },
    "content": { "type": "text", "text": "Hola! Tu pedido fue confirmado." },
    "whatsappAccountId": "TU_ACCOUNT_ID"
  }'
const response = await fetch('https://api.arplyx.com/messages', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.ARPLYX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    externalId: 'pedido-10045',
    channel: 'whatsapp_meta',
    to: { type: 'phone', phoneE164: '+15550100123' },
    content: { type: 'text', text: 'Hola! Tu pedido fue confirmado.' },
    whatsappAccountId: 'TU_ACCOUNT_ID',
  }),
})

const data = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${data.error}`)
console.log(data.messageId, data.status)
import os
import requests

response = requests.post(
    'https://api.arplyx.com/messages',
    headers={'x-api-key': os.environ['ARPLYX_API_KEY']},
    json={
        'externalId': 'pedido-10045',
        'channel': 'whatsapp_meta',
        'to': {'type': 'phone', 'phoneE164': '+15550100123'},
        'content': {'type': 'text', 'text': 'Hola! Tu pedido fue confirmado.'},
        'whatsappAccountId': 'TU_ACCOUNT_ID',
    },
    timeout=10,
)
response.raise_for_status()
print(response.json())

Para enviar por Meta Official, usá "channel": "whatsapp_meta" y omití whatsappAccountId si tenés una sola cuenta Meta conectada. Recordá la ventana de 24 horas del canal oficial para texto libre.

Reintentos automáticos

Si el proveedor falla con un error transitorio (red, 5xx, rate limit), Arplyx reintenta solo, con backoff exponencial, hasta 5 intentos por defecto. No reenvíes vos por tu cuenta: usá el mismo externalId si querés re-disparar de forma segura.