WhatsApp Flows

Los eventos whatsapp.flows.* son especiales: Platica no sólo te notifica que algo ocurrió, también espera tu respuesta para continuar el flow de WhatsApp.

Úsalos cuando quieras que tu backend controle pantallas dinámicas, validaciones, opciones de dropdown, precios, confirmaciones o cualquier dato que deba calcularse en tiempo real.

Eventos

EventoCuándo ocurre
whatsapp.flows.initEl usuario abre el flow (action: "INIT")
whatsapp.flows.screen_advanceEl usuario avanza de pantalla (action: "data_exchange")
whatsapp.flows.backEl usuario regresa a la pantalla anterior (action: "BACK")
whatsapp.flows.exchangesSuscripción paraguas para recibir los tres eventos anteriores

Ciclo de entrega

Payload recibido

{
  "id": "8f2c4d6a-1b3e-4f5d-8a9c-2e7b6d1a3f4e",
  "event": "whatsapp.flows.screen_advance",
  "workspaceId": "ws_456",
  "timestamp": "2026-05-06T19:00:30.000Z",
  "source": "whatsapp.flows",
  "resourceType": "flow_response",
  "resourceId": "ZmxvdyQwMQ==",
  "changes": null,
  "data": {
    "client": {
      "id": "client_123",
      "phoneNumber": "+5215555555555",
      "creationDate": "2026-05-01T12:00:00.000Z",
      "lastUpdate": "2026-05-06T18:59:00.000Z",
      "name": "Juan Pérez",
      "firstname": "Juan",
      "email": "juan@empresa.com"
    },
    "conversation": {
      "id": "conv_123",
      "conversationId": "conv_123",
      "canSendDirectMessage": true,
      "workspaceId": "ws_456",
      "channelId": "channel_wa_123",
      "contactName": "Juan Pérez",
      "phoneNumber": "+5215555555555",
      "topic": "",
      "platform": "whatsapp",
      "owners": [],
      "tags": [],
      "creationDate": "2026-05-06T18:58:00.000Z",
      "lastUpdate": "2026-05-06T19:00:00.000Z",
      "status": "open",
      "operation": "automatic",
      "messageCount": 3
    },
    "flow": {
      "id": "flow_doc_abc",
      "wabaId": "1234567890",
      "name": "Cotizador",
      "status": "PUBLISHED",
      "categories": ["LEAD_GENERATION"],
      "dataApiVersion": "3.0",
      "endpointUri": "https://app.platica.mx/api/whatsapp/flows/1234567890/data",
      "jsonVersion": "7.1",
      "creationDate": "2026-05-01T12:00:00.000Z",
      "lastUpdate": "2026-05-06T18:55:00.000Z",
      "lastSyncAt": "2026-05-06T18:55:00.000Z"
    },
    "flowResponse": {
      "flowToken": "ZmxvdyQwMQ==",
      "status": "IN_PROGRESS",
      "sentAt": "2026-05-06T18:59:00.000Z",
      "openedAt": "2026-05-06T19:00:00.000Z",
      "lastActivityAt": "2026-05-06T19:00:30.000Z",
      "completedAt": null,
      "expiresAt": "2026-05-07T18:59:00.000Z",
      "clientId": "client_123",
      "conversationId": "conv_123",
      "messageId": "wamid.HBgN...",
      "campaignId": null,
      "agentId": null,
      "channelId": "channel_wa_123"
    },
    "flowExchange": {
      "action": "data_exchange",
      "screen": "WELCOME",
      "version": "3.0",
      "payload": {
        "selected_product": "p2",
        "email": "juan@empresa.com"
      }
    }
  }
}
CampoTipoDescripción
eventstringEvento recibido
idstringUUID del envío
workspaceIdstringWorkspace propietario
timestampstringFecha ISO-8601 del envío
sourcewhatsapp.flowsOrigen estable del evento
resourceTypeflow_responseTipo de recurso afectado
resourceIdstring \| nullflow_token de Meta cuando existe
changesnullReservado para compatibilidad con el envelope común
data.clientobject \| nullResumen del cliente asociado, si Platica pudo resolverlo
data.conversationobject \| nullConversación asociada, si existe un conversationId
data.flowobjectSnapshot normalizado del flow
data.flowResponseobject \| nullEstado de la respuesta/sesión del flow
data.flowExchangeobjectDatos del intercambio recibido desde Meta

Campos de data.flowExchange

CampoTipoDescripción
actioninit \| data_exchange \| backAcción recibida desde Meta, normalizada a minúsculas
screenstring \| nullPantalla actual enviada por Meta
versionstring \| nullVersión del protocolo de WhatsApp Flows
payloadobjectDatos capturados o enviados por Meta para ese paso

Respuesta esperada

Tu endpoint debe responder 2xx con JSON. Platica acepta la respuesta si cumple al menos una de estas condiciones:

  • Tiene data y data es un objeto.
  • Tiene screen y screen es un string no vacío.

Ejemplo para poblar datos dinámicos:

{
  "data": {
    "products": [
      { "id": "p1", "title": "Plan Básico" },
      { "id": "p2", "title": "Plan Premium" }
    ]
  }
}

Ejemplo para avanzar a una pantalla:

{
  "screen": "PAYMENT",
  "data": {
    "amount_mxn": 499
  }
}

Ejemplo para mostrar un error:

{
  "data": {
    "error_message": "El código postal no es válido"
  }
}

Headers y firma

HeaderDescripción
Content-Typeapplication/json
User-AgentPlatica-Webhooks/1.0
X-Webhook-EventIgual a payload.event
X-Webhook-IdIdentificador del webhook configurado
X-Webhook-Event-IdIgual a payload.id
X-Webhook-Resource-Typeflow_response
X-Webhook-Resource-IdIgual a payload.resourceId
X-Webhook-TimestampIgual a payload.timestamp
X-Webhook-Signaturesha256=<hex> si configuraste secret

La firma se calcula con HMAC-SHA256 usando el cuerpo crudo:

sha256=<hmac_sha256(secret, rawBody)>

Ejemplo en Node.js:

const crypto = require('crypto');

function verifyFlowsWebhook(secret, rawBody, signatureHeader) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

whatsapp.flows.init

Ocurre cuando el usuario abre el flow. Normalmente se usa para precargar datos iniciales.

{
  "id": "5e3a1b9c-7d12-4a8e-9c5f-1e6b8d0a2c4f",
  "event": "whatsapp.flows.init",
  "workspaceId": "ws_456",
  "timestamp": "2026-05-06T19:00:00.000Z",
  "source": "whatsapp.flows",
  "resourceType": "flow_response",
  "resourceId": "ZmxvdyQwMQ==",
  "changes": null,
  "data": {
    "client": null,
    "conversation": null,
    "flow": {
      "id": "flow_doc_abc",
      "wabaId": "1234567890"
    },
    "flowResponse": {
      "flowToken": "ZmxvdyQwMQ==",
      "status": "IN_PROGRESS"
    },
    "flowExchange": {
      "action": "init",
      "screen": null,
      "version": "3.0",
      "payload": {}
    }
  }
}

whatsapp.flows.screen_advance

Ocurre cuando el usuario llena una pantalla y pulsa continuar. data trae los valores capturados.

{
  "id": "8f2c4d6a-1b3e-4f5d-8a9c-2e7b6d1a3f4e",
  "event": "whatsapp.flows.screen_advance",
  "workspaceId": "ws_456",
  "timestamp": "2026-05-06T19:00:30.000Z",
  "source": "whatsapp.flows",
  "resourceType": "flow_response",
  "resourceId": "ZmxvdyQwMQ==",
  "changes": null,
  "data": {
    "client": null,
    "conversation": null,
    "flow": {
      "id": "flow_doc_abc",
      "wabaId": "1234567890"
    },
    "flowResponse": {
      "flowToken": "ZmxvdyQwMQ==",
      "status": "IN_PROGRESS"
    },
    "flowExchange": {
      "action": "data_exchange",
      "screen": "WELCOME",
      "version": "3.0",
      "payload": {
        "selected_product": "p2",
        "email": "juan@empresa.com"
      }
    }
  }
}

whatsapp.flows.back

Ocurre cuando el usuario pulsa regresar. Úsalo para restaurar datos de una pantalla anterior.

{
  "id": "3a5b7c9d-2e4f-4a6b-8c1d-5e7f9a2b4c6d",
  "event": "whatsapp.flows.back",
  "workspaceId": "ws_456",
  "timestamp": "2026-05-06T19:01:00.000Z",
  "source": "whatsapp.flows",
  "resourceType": "flow_response",
  "resourceId": "ZmxvdyQwMQ==",
  "changes": null,
  "data": {
    "client": null,
    "conversation": null,
    "flow": {
      "id": "flow_doc_abc",
      "wabaId": "1234567890"
    },
    "flowResponse": {
      "flowToken": "ZmxvdyQwMQ==",
      "status": "IN_PROGRESS"
    },
    "flowExchange": {
      "action": "back",
      "screen": "PAYMENT",
      "version": "3.0",
      "payload": {}
    }
  }
}

whatsapp.flows.exchanges

Es una suscripción paraguas para recibir init, screen_advance y back en un solo webhook.

Usa whatsapp.flows.exchanges si tu backend quiere manejar todos los pasos del flow con el mismo endpoint y la misma lógica.

Si necesitas separar lógica por paso, suscríbete a los eventos granulares:

  • whatsapp.flows.init
  • whatsapp.flows.screen_advance
  • whatsapp.flows.back