Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://docs.ryzeapi.cloud/llms.txt

Use this file to discover all available pages before exploring further.

El webhook y el WebSocket comparten el mismo envoltorio y el mismo catálogo de eventos. La única diferencia es el canal de entrega, data es idéntico. Esta página documenta los 6 tipos: message.exchange, message.status, call.update, group.flow, instance.state y label.update.

Envoltorio

{
  "event": "<event-name>",
  "data": { /* event-specific payload */ },
  "instanceData": {
    "baseUrl": "https://api.example.com",
    "instance": "<name>",
    "token":    "<instance-token>"
  }
}
El filtrado se hace por el nombre del event en el campo events de la configuración. Vacío = todos los tipos.

Filtrado y enrutamiento

{ "events": ["message.exchange", "call.update", "instance.state"] }
Cuando byEvents=true (solo webhook), el nombre del evento se agrega a la URL:
  • Configuración: url: "https://app/wh", byEvents: true
  • Entrega: POST https://app/wh/message.exchange
Útil para enrutamiento basado en endpoints sin inspeccionar el payload.

message.exchange

Mensajes enviados y recibidos (texto, media, sticker, documento, audio, encuesta, contacto, ubicación, etc.), ediciones y revocaciones.

Payload

{
  "id": "wamid.msg.123",
  "message": {
    "id": "wamid.msg.123",
    "direction": "incoming | outgoing",
    "timestamp": "2026-04-28T10:30:00Z",
    "chat": {
      "jid": "5511999999999",
      "lid": "100@s.whatsapp.net",
      "name": "João Silva",
      "type": "private | group | newsletter",
      "isCommunity": true
    },
    "sender": {
      "jid": "5511999999999",
      "lid": "100@s.whatsapp.net",
      "name": "João Silva"
    },
    "content": { "text": "Hello" },
    "media": {
      "type": "image | video | audio | document | sticker | ptt | ptv",
      "url": "https://media-...whatsapp.net/...",
      "s3Url": "https://bucket.s3.amazonaws.com/...",
      "base64": "iVBORw0KGgo...",
      "mimetype": "image/jpeg",
      "size": 45678,
      "caption": "Event photo",
      "fileName": "doc.pdf"
    },
    "edit": {
      "original_id": "wamid.original",
      "originalContent": "Old text",
      "text": "New text"
    },
    "forward": { "count": 2 },
    "reply": {
      "message_id": "wamid.replied",
      "sender": { "jid": "...", "name": "..." },
      "text": "...",
      "media": { /* simplified media object */ }
    },
    "poll": {
      "title": "Which flavor?",
      "options": [{ "name": "Chocolate", "count": 0 }]
    },
    "location": {
      "latitude": -23.5505,
      "longitude": -46.6333,
      "address": "Av. Paulista, 1374"
    },
    "contact": {
      "display_name": "Maria",
      "phone_number": "5511987654321",
      "vcard": "BEGIN:VCARD..."
    },
    "list_response": {
      "title": "...",
      "body": "...",
      "list_type": "single_select",
      "single_select_reply": { "option_name": "p1" }
    },
    "button_response": {
      "title": "Buy",
      "body": "...",
      "selected_button_id": "buy_camiseta"
    },
    "interactive": { /* form / native flow / other surfaces */ }
  }
}

Campos condicionales

Solo se completan los campos relevantes para el tipo de mensaje. Las ediciones tienen edit poblado; las revocaciones llegan con type: "message_revoke" en data.message.type.
chat.isCommunity aparece solo cuando es true, indicando que el chat es el canal de anuncios (parent / announcement channel) de una comunidad de WhatsApp. Los subgrupos vinculados a una comunidad mantienen type: "group" y no incluyen el campo isCommunity. En grupos regulares y DMs el campo también se omite.
media.base64 solo aparece cuando mediaBase64=true en la configuración (webhook o WebSocket). De lo contrario, usa media.url (whatsapp.net, expira) o media.s3Url (si S3 está configurado en la instancia).

Ejemplo (imagen recibida)

{
  "event": "message.exchange",
  "data": {
    "id": "wamid.123",
    "message": {
      "id": "wamid.123",
      "direction": "incoming",
      "timestamp": "2026-04-28T10:30:00Z",
      "chat":   { "jid": "5511999999999", "name": "João", "type": "private" },
      "sender": { "jid": "5511999999999", "name": "João" },
      "media": {
        "type":     "image",
        "url":      "https://media-abc.whatsapp.net/...",
        "mimetype": "image/jpeg",
        "size":     45678,
        "caption":  "Photo"
      }
    }
  },
  "instanceData": { "baseUrl": "https://api...", "instance": "minha", "token": "..." }
}

message.status

Acuses de entrega: delivered, read, played, etc.

Payload

{
  "status": "delivered | read | played | sender | read_self | played_self | retry | inactive | server_error",
  "messageIds": ["wamid.123", "wamid.124"],
  "timestamp":  "2026-04-28T10:45:00Z",
  "chat": {
    "jid": "5511999999999",
    "type": "private | group | broadcast",
    "isCommunity": true
  },
  "recipient":     "5511999999999",
  "messageSender": null,
  "isFromMe":      false
}

Enum status

ValorSignificado
deliveredEl mensaje llegó al dispositivo del destinatario.
readEl destinatario lo leyó (con confirmaciones de lectura activas).
playedAudio/nota de voz reproducida.
senderEco interno (la propia fuente reportando entrega).
read_selfEl propio usuario lo marcó como leído en otro dispositivo.
played_selfEl propio usuario lo reprodujo en otro dispositivo.
retryEl servidor solicitó re-entrega (transitorio).
inactiveEl destinatario lleva demasiado tiempo offline.
server_errorError genérico del servidor de WhatsApp.
  • messageSender en grupos: JID del autor original del mensaje (relevante cuando alguien lee un mensaje de otro participante).
  • chat.isCommunity sigue la misma regla que message.exchange: presente y true solo cuando el chat es el canal de anuncios de una comunidad.

call.update

Eventos de llamadas: offer, accepted, rejected, terminated, latency.

Payload

{
  "type": "offer | accepted | rejected | terminated | notification | latency",
  "direction": "incoming | outgoing",
  "callId": "call-abc123",
  "from": "5511999999999",
  "to":   "5511888888888",
  "timestamp": "2026-04-28T10:35:00Z",
  "groupJid": null,
  "callMedia": "audio | video | null",
  "remotePlatform": "Android | iPhone | null",
  "remoteVersion": "2.23.15.74",
  "noticeType": "group | null",
  "reason": null,
  "duration": 123,
  "latency":  45.6,
  "latencyStatus": "Excellent | Good | Average | Poor"
}

Enum type

ValorCuándo se dispara
offerLlamada recibida/enviada (timbre inicial).
acceptedEl lado remoto contestó.
rejectedEl lado remoto rechazó.
terminatedLlamada finalizada, se completa duration en segundos.
notificationNotificación contextual de llamada (p. ej., llamada perdida en grupo).
latencyMétrica de latencia durante la llamada (latency en ms, latencyStatus).
Para auto-rechazar llamadas, configura autoRejectCalls=true en el bloque de configuración de la instancia, aún recibirás los eventos offer + rejected en el webhook.

group.flow

Cambios de grupo: miembros, metadatos, configuraciones.

Payload, cambio de participante

{
  "type": "joined | left | promoted | demoted",
  "groupJid": "120363406289005073@g.us",
  "groupName": "Dev Team",
  "timestamp": "2026-04-28T11:00:00Z",
  "participants": [
    { "jid": "5511999999999", "action": "joined" }
  ]
}

Subtipos de metadatos

typeSignificado
nameNombre del grupo cambiado
topicDescripción cambiada
locked / unlockedLos miembros pueden/no pueden editar la información
announce / not_announceLos miembros pueden/no pueden enviar mensajes
ephemeral / not_ephemeralMensajes efímeros activados/desactivados
inviteEnlace de invitación generado
link / unlinkSubgrupo vinculado/desvinculado de la comunidad
deleteGrupo eliminado
membership_approvalModo de aprobación para nuevos miembros cambiado
suspended / unsuspendedGrupo suspendido/reactivado por WhatsApp

instance.state

Cambios en el estado de la propia instancia (conexión, QR, ban, emparejamiento).

Payload

{
  "instance": "minha",
  "state": "connected | disconnected | logged_out | stream_replaced | temp_banned | client_outdated | connect_failure | stream_error | cat_refresh_error | qr_ready | pair_success | pair_error | qr_scanned_no_multidevice | keepalive_timeout | keepalive_restored | manual_reconnect",
  "timestamp": "2026-04-28T10:50:00Z",
  "reason": "...",
  "reasonCode": 123,
  "message": "...",
  "expireAt": "2026-04-28T11:50:00Z",
  "expireInSeconds": 3600,
  "onConnect": true,
  "codes": ["1@abc...,xyz==,base64string"],
  "jid": "5511999999999@s.whatsapp.net",
  "platform": "iPhone | Android | Desktop",
  "errorMsg": "..."
}

Enum state

EstadoSignificadoCampos extra completados
connectedSesión activa, lista para enviar/recibir.
disconnectedDesconectado (transitorio, usualmente reconecta solo).
logged_outSesión invalidada (requiere nuevo connect).reason
stream_replacedOtra sesión tomó el control (conflicto multi-dispositivo).
temp_bannedBan temporal aplicado por WhatsApp.expireAt, expireInSeconds, reason
client_outdatedLa versión de WhatsApp Web en uso está desactualizada, contactar soporte.message
connect_failureFalla durante la conexión.reason, reasonCode
stream_errorError de stream de WhatsApp.errorMsg
cat_refresh_errorFalla al refrescar credenciales (cat).errorMsg
qr_readyNuevo QR disponible para emparejamiento.codes[], onConnect
pair_successEmparejamiento completado.jid, platform
pair_errorError durante el emparejamiento.errorMsg
qr_scanned_no_multideviceQR escaneado pero el dispositivo destino no soporta multi-dispositivo.
keepalive_timeoutConexión inestable, keepalive no respondido.
keepalive_restoredConexión estabilizada después de keepalive_timeout.
manual_reconnectReconexión disparada manualmente vía REST.
Para que tu cliente sepa cuándo refrescar el QR en la UI, escucha instance.state con state=qr_ready y renderiza data.codes[0].

label.update

Ediciones/asociaciones de etiquetas (etiquetas de WhatsApp Business).

Payload

{
  "type":   "edit | chat | message",
  "labelId": "1",
  "timestamp": "2026-04-28T10:00:00Z",
  "action": "updated | deleted | add | remove",

  // type=edit:
  "name": "Important",
  "color": 0,
  "labelType": "CUSTOM",
  "isActive": true,
  "isImmutable": false,
  "orderIndex": 1,
  "deleted": false,

  // type=chat:
  "chatJid": "5511999999999@s.whatsapp.net",
  "labeled": true,

  // type=message:
  "messageId": "wamid.abc"
}

Combinaciones type × action

typeaction válidaCampos extra
editupdated, deletedname, color, labelType, isActive, isImmutable, orderIndex, deleted
chatadd, removechatJid, labeled
messageadd, removechatJid, messageId

Eventos no emitidos (internos)

Capturados por el handler de whatsmeow pero no propagados vía webhook/WS:
  • *events.Picture, cambio de foto de perfil (solo registrado en log).
  • *events.FBMessage, Facebook Business (solo registrado en log).
  • *events.HistorySync, sincronización de historial (procesado y almacenado en BD).
Si necesitas consumir alguno de estos cambios, haz polling de los endpoints REST correspondientes (perfil, historial).

Referencias

Configurar webhook

Filtra eventos vía events[] en la configuración.

Configurar WebSocket

Misma sintaxis de filtro que el webhook.

Conectar vía WebSocket

Recibe eventos en tiempo real.

Resumen de eventos

Comparación webhook vs WebSocket.