Saltar a contenido

Remitentes y mensajes entrantes

Estos endpoints responden una pregunta clave para enviar por WhatsApp Direct sin riesgo: "¿este número ya me escribió?". El patrón que hace que Meta restrinja una cuenta emisora es mandarle a números que nunca abrieron conversación; el circuito seguro es pedirle a la persona que te escriba primero y habilitarla como destino recién cuando lo hizo. Todo con la misma autenticación x-api-key y siempre acotado a tu cuenta.

Tip

Para enterarte en el momento en que un número escribe por primera vez, suscribite al evento sender.first_inbound de webhooks. Estos endpoints son la fuente de verdad consultable: sirven para verificar antes de un alta, reconciliar en lote o reconstruir estado después de un restore.

GET /inbound-senders/{phone}

Estado de un remitente: si ya escribió a tu cuenta, cuándo fue la primera y la última vez, y cuántos mensajes mandó. Disponible en todos los planes.

curl "https://api.arplyx.com/inbound-senders/%2B5493411234567?whatsappAccountId=9d2f81b3-…" \
  -H "x-api-key: ak_live_xxxxxxxx..."

Respuesta 200 (el número escribió):

{
  "phoneE164": "+5493411234567",
  "whatsappAccountId": "9d2f81b3-…",
  "hasWritten": true,
  "firstInboundAt": "2026-07-02T14:03:11.000Z",
  "lastInboundAt": "2026-07-20T09:12:44.000Z",
  "inboundCount": 3,
  "sandbox": false
}

Respuesta 200 (nunca escribió — no es un 404):

{
  "phoneE164": "+5491155551234",
  "whatsappAccountId": "9d2f81b3-…",
  "hasWritten": false,
  "firstInboundAt": null,
  "lastInboundAt": null,
  "inboundCount": 0,
  "sandbox": false
}
Campo Descripción
phoneE164 El número consultado, normalizado a E.164 canónico.
hasWritten Si el número escribió alguna vez a la cuenta.
firstInboundAt Momento del primer mensaje recibido. No cambia con mensajes posteriores.
lastInboundAt Momento del último mensaje recibido.
inboundCount Cantidad de mensajes recibidos (aproximada ante reintentos del proveedor; hasWritten y los timestamps son exactos).
sandbox true si la respuesta fue simulada por una key sandbox.

Formatos del número. {phone} acepta E.164 con + (URL-encodeado como %2B), el + literal, solo dígitos internacionales (5493411234567) o un número nacional resuelto contra el país por defecto. Formatos distintos del mismo número resuelven al mismo remitente — un formato diferente nunca da un falso negativo. Un número imparseable responde 400 validation_error.

Resolución de la cuenta. whatsappAccountId es opcional cuando la API key está scopeada a una cuenta o cuando tenés una sola cuenta vinculada; con más de una cuenta (o ninguna) es obligatorio.

Errores: 403 key_scope_violation si la key está scopeada a otra cuenta, 404 account_not_found si el whatsappAccountId no existe o no es tuyo, 422 whatsapp_account_required si hay ambigüedad y no lo indicaste.

POST /inbound-senders/lookup

Lo mismo, para varios números en una sola llamada (máximo 200 por request; más responde 400 validation_error).

curl -X POST https://api.arplyx.com/inbound-senders/lookup \
  -H "x-api-key: ak_live_xxxxxxxx..." \
  -H "Content-Type: application/json" \
  -d '{
    "whatsappAccountId": "9d2f81b3-…",
    "phones": ["+5493411234567", "+5491155551234"]
  }'

Respuesta 200:

{
  "senders": [
    { "phoneE164": "+5493411234567", "hasWritten": true,  "firstInboundAt": "2026-07-02T14:03:11.000Z", "lastInboundAt": "2026-07-20T09:12:44.000Z", "inboundCount": 3, "whatsappAccountId": "9d2f81b3-…", "sandbox": false },
    { "phoneE164": "+5491155551234", "hasWritten": false, "firstInboundAt": null, "lastInboundAt": null, "inboundCount": 0, "whatsappAccountId": "9d2f81b3-…", "sandbox": false }
  ]
}
  • Devuelve una entrada por número distinto (tras normalizar), incluidos los que nunca escribieron.
  • Si algún número es imparseable, la request completa responde 400 validation_error con el índice del número inválido (phones.3).

GET /inbound-messages (listado — plan Pro)

Lista tus mensajes entrantes, los más recientes primero — espejo de GET /messages, con la misma paginación por cursor. Sirve para auditoría o para ver qué escribió la persona, no solo si escribió.

curl "https://api.arplyx.com/inbound-messages?from=%2B5493411234567&limit=50" \
  -H "x-api-key: ak_live_xxxxxxxx..."

Parámetros de query (todos opcionales):

Parámetro Descripción
from Número del remitente (mismos formatos que /inbound-senders/{phone}).
whatsappAccountId Solo entrantes de esa cuenta.
since / until Rango sobre receivedAt (ISO 8601).
limit 1–100, default 50.
cursor El nextCursor de la página anterior.

Respuesta 200:

{
  "inboundMessages": [
    {
      "inboundMessageId": "c81d3a6f-…",
      "whatsappAccountId": "9d2f81b3-…",
      "channel": "whatsapp_direct",
      "from": "+5493411234567",
      "fromDisplayName": "Juan",
      "messageType": "text",
      "text": "sí, confirmo",
      "displayText": null,
      "receivedAt": "2026-07-20T09:12:44.000Z",
      "replyTo": null
    }
  ],
  "nextCursor": null
}
  • replyTo tiene el mismo shape que en el evento message.inbound: cuando la persona respondió citando un mensaje tuyo, trae messageId/externalId propios (o null si el citado no salió vía Arplyx o ya fue purgado).
  • Requiere plan Pro (espejo del Inbox); en otros planes responde 403 feature_not_available.
  • Está sujeto a la retención habitual de tu plan (3–30 días). Para "¿este número ya escribió?" usá /inbound-senders, que sobrevive a la purga.

Qué cuenta como "escribió"

El agregado de remitentes registra toda recepción real, con una semántica pensada para que una verificación de identidad no cambie retroactivamente:

  • Sobrevive a la purga de mensajes. El contenido de los entrantes se purga según la retención de tu plan, pero el hecho de que un número escribió (y cuándo fue la primera vez) persiste mientras la cuenta exista. Si eliminás la cuenta de WhatsApp, su historial de remitentes se elimina con ella.
  • Se registra antes de los filtros del Inbox. Un número descartado por tu blacklist/whitelist igual cuenta como "escribió": cambiar los filtros no altera verificaciones pasadas ni futuras.
  • Se registra en todos los planes, aunque tu plan no almacene los mensajes entrantes en el Inbox (que es Pro).
  • Cualquier tipo de mensaje cuenta (texto, audio, imagen, sticker…), de cualquiera de los dos canales.
  • Limitación: si WhatsApp oculta el número del remitente (privacidad LID) y no se puede resolver, esa recepción no se registra — el remitente no es identificable por teléfono.
  • firstInboundAt es el primer mensaje que la plataforma procesó: mensajes anteriores a la vinculación de la cuenta (o recibidos durante una caída del servicio) no están.

Probar en sandbox

Con una API key sandbox (ak_test_…) estos endpoints no tocan datos reales: la respuesta se simula con números mágicos, para que puedas testear el circuito de alta sin un teléfono real.

Número consultado termina en Respuesta simulada
77 hasWritten: true (con timestamps y inboundCount: 3 simulados)
cualquier otro hasWritten: false

GET /inbound-messages con key sandbox devuelve una lista vacía. Todas las respuestas sandbox llevan "sandbox": true.

El circuito completo, de punta a punta

  1. Le pedís a la persona (por otro canal) que le escriba a tu número de WhatsApp.
  2. Cuando escribe, te llega el webhook sender.first_inbound (si estás suscripto) — o la detectás consultando GET /inbound-senders/{phone} en tu alta.
  3. Con hasWritten: true, habilitás el número y empezás a enviarle con POST /messages.