# Notificaciones por webhook

### Introducción y configuración

Optiwe permite el envío webhooks a sistemas externos para notificaciones de:

* Conversaciones nuevas
* Conversaciones actualizadas
* Mensajes salientes de WhatsApp fallidos
* Estado de campañas de Whatsapp

Estos webhooks se pueden configurar en la plataforma Dashboard (<https://app.optiwe.com/dashboard/home>) del espacio de trabajo, dentro de Configuración >> Webhooks. Allí, se debe especificar la URL a la cual  enviarán los webhooks y cuales se desean recibir:

<figure><img src="/files/spj9vNKCvTbtfLKaeY4b" alt=""><figcaption><p>1. Vista de configuración, 2. Pestaña Webhooks, 3. Configurar URL donde se recibirán los webooks, 4. Habilitar los tipos de webhooks que se desean recibir, 5. Guardar cambios.</p></figcaption></figure>

### Nueva conversación

El evento `NEW_CONVERSATION` se dispara una única vez cuando una conversación esta pendiente de ser resuelta por un agente de atención.

Dependiendo la configuración de cada espacio de trabajo, una conversación al ser iniciado por el usuario puede ser manejada por el bot o quedar pendiente a ser resuelta los agentes de atención.

A su vez las conversaciones manejadas por el bot, pueden requerir la intervención de un agente humano, por lo tanto el evento `NEW_CONVERSATION` se dispara cuando:

* Un espacio de trabajo no tiene un chatbot configurado y un usuario inicia una conversación
* Un usuario le solicita al chatbot la intervención de un agente humano.

**Payload**

```json
{
   "timestamp": int,
   "version": int,
   "type":"CONVERSATION_EVENT",
   "payload":{
      "type": "NEW_CONVERSATION"
      "payload": {
         "conversation": {
            "id": int,
            "customer": {
              "id": int,
              "fullName": Optional[str],
              "name": Optional[str],
              "email": Optional[str],
              "phone": Optional[str],
              "createdOn": datetime,
              "updatedOn": datetime,
              "lastActivity": datetime,
              "extraData": {},
              "hasWhatsappOptIn": bool
            },
            "customerChannel": {
              "type": "WHATSAPP|FACEBOOK|OPTIWE_CHAT|INSTAGRAM"
            },
            "createdOn": datetime,
            "updatedOn": datetime,
            "lastEndUserActivity": datetime,
            "status": "ACTIVE|ENDED",
            "amountNew": int,
            "startedWaitingOn": datetime
         },
         "workspace": {
            "id": int  
         }
      }
   }
}
```

### Nuevo mensaje

Se ejecuta ante cada nuevo mensaje del usuario. A diferencia del evento de nueva conversación, en este caso se recibe la información del mensaje enviado por el usuario.

#### Payload

```json
{
   "timestamp": int,
   "version": int,
   "type":"CONVERSATION_EVENT",
   "payload":{
      "type": "CONVERSATION_UPDATED"
      "payload": {
         "conversation": {
            "id": int,
            "customer": {
              "id": int,
              "fullName": Optional[str],
              "name": Optional[str],
              "email": Optional[str],
              "phone": Optional[str],
              "createdOn": datetime,
              "updatedOn": datetime,
              "lastActivity": datetime,
              "extraData": {},
              "hasWhatsappOptIn": bool
            },
            "customerChannel": {
              "type": "WHATSAPP|FACEBOOK|OPTIWE_CHAT|INSTAGRAM"
            },
            "createdOn": datetime,
            "updatedOn": datetime,
            "lastEndUserActivity": datetime,
            "status": "ACTIVE|ENDED",
            "amountNew": int,
            "startedWaitingOn": datetime
         },
         "workspace": {
            "id": int  
         },
         "message": {
            id: int
            messageFrom: "END_USER|FACEBOOK_MESSENGER_END_USER|
                          INSTAGRAM_END_USER|WHATSAPP_END_USER"
            createdOn: datetime
            updatedOn: datetime
            messagePayload: MessageObject
         }
      }
   }
}
```

#### Tipos de mensaje

El objeto `MessageObject` puede ser cualquiera de los siguientes tipos de mensaje:

* **Text message**

Mensaje de texto plano

```json
{
   "type": "TEXT",
   "text": str 
}
```

* **Image message**

Mensaje del tipo imagen

```json
{
   "type": "IMAGE",
   "text": Optional[str],
   "fileUrl": str
}
```

*Ejemplo:*

```json
{
   "type": "IMAGE",
   "fileUrl": "https://route/to/file/my_image.png"
}
```

* **Video message**

Mensaje del tipo video

```json
{
   "type": "VIDEO",
   "text": Optional[str],
   "fileUrl": str
}
```

*Ejemplo*

```json
{
   "type": "VIDEO",
   "fileUrl": "https://route/to/file/my_video.mp4"
}
```

* **Audio message**

Mensaje del tipo audio

```json
{
   "type": "AUDIO",
   "fileUrl": str
}
```

*Ejemplo*

```json
{
   "type": "AUDIO",
   "fileUrl": "https://route/to/file/my_aduio.mp3"
}
```

* **Document message**

Mensaje del tipo documento

```json
{
   "type": "DOCUMENT",
   "text": Optional[str],
   "fileUrl": str
}
```

*Ejemplo*

```json
{
   "type": "DOCUMENT",
   "fileUrl": "https://route/to/file/my_document.pdf"
}
```

### Mensajes salientes de Whatsapp

Estos webhooks se enviarán a la URL configurada cuando se envíe un mensaje saliente (desde la plataforma Agent o la API de mensajes salientes de Optiwe) a un cliente con número de WhatsApp.&#x20;

#### Payload

```
{
  "timestamp": int,
  "version": str,
  "type": str,
  "payload": {
    "type": str,
    "payload": {
      "statusCode": int, // Solo para eventos "failed"
      "metaErrorDescription": str, // Solo para eventos "failed"
      "conversationId": int,
      "messageId": int,
      "destination": str,
      "customerName": Optional[str]
    }
  }
}
```

* **timestamp**: Marca de tiempo del evento
* **version**: Version interna de la API de Optiwe
* **type**: Tipo de evento del webhook. Para eventos de mensajes salientes por Whatsapp este evento es de tipo "MESSAGE\_EVENT"
* **payload.type:** tipo de evento de Whatsapp. En la versión actual de la API, puede ser "failed", "sent" o "read"
* **payload.payload.statusCode**: Solo para eventos tipo "failed". Código de error de Meta. Para ver todos los códigos posibles de Meta dirigirse a <https://developers.facebook.com/docs/whatsapp/on-premises/errors>
* **payload.payload.metaErrorDescription**: Solo para eventos tipo "failed". Descripción del error de Meta correspondiente al código "statusCode".
* **payload.payload.conversationId**: Identificador de la conversación de Optiwe que contiene el mensaje correspondiente al webhook.
* **payload.payload.messageId**: Identificador del mensaje de Optiwe.
* **payload.payload.destination**: Número telefónico de destino al que se le envió el mensaje
* **payload.payload.customerName**: Nombre del cliente asociado al número que figura en destination (en caso de que sea un cliente existente

#### 1. Mensajes fallidos

Se enviará un evento de mensaje fallido en caso de que no se logre enviar el saliente. En el caso de que el saliente fallido sea de una campaña enviada a través de la plataforma Dashboard, éste quedará registrado en las estadísticas de la campaña pero no se enviará el webhook.

*Ejemplo*

```
{
  "timestamp": 1704219266303,
  "version": "1",
  "type": "MESSAGE_EVENT",
  "payload": {
    "type": "failed",
    "payload": {
      "statusCode": 1013,
      "metaErrorDescription": "User is not valid, Recipient is not a valid WhatsApp user",
      "conversationId": 30,
      "messageId": 170,
      "destination": "54911XX45XX89",
      "customerName": "John Doe"
    }
  }
}
```

#### 2. Mensajes enviados

Se enviará un evento de mensaje enviado en caso de que se logre enviar el saliente correctamente.

*Ejemplo*

```
{
  "timestamp": 1704219769334,
  "version": "1",
  "type": "MESSAGE_EVENT",
  "payload": {
    "type": "sent",
    "payload": {
      "conversationId": 31,
      "messageId": 179,
      "destination": "54911XX45XX89",
      "customerName": "John Doe"
    }
  }
}
```

#### 3. Mensajes leídos

Se enviará un evento de mensaje leído en caso de que el cliente lea el mensaje saliente. Para que esto suceda, el cliente debe tener habilitado la notificación de lectura de mensajes en Whatsapp, en caso contrario no se enviarán los webhooks de mensajes leídos.

*Ejemplo*

```
{
  "timestamp": 1704219289210,
  "version": "1",
  "type": "MESSAGE_EVENT",
  "payload": {
    "type": "read",
    "payload": {
      "conversationId": 29,
      "messageId": 171,
      "destination": "54911XX45XX89",
      "customerName": "John Doe"
    }
  }
}
```

### Campañas

&#x20;

Para campañas enviadas mediante el dashboard o mediante la [Manejo y envío de plantillas de WhatsApp](/developers/manejo-y-envio-de-plantillas-de-whatsapp.md#api-para-envios-bulk) se pueden habilitar webhooks que se enviarán a la URL configurada una vez la campaña haya finalizado su envío con el siguiente comportamiento:

* Durante las primeras 24 horas se envía un webhook por hora&#x20;
* Luego de las primeras 24 horas, se envía un webhook en cada cambio con respecto a los clientes. Por ejemplo, si un cliente respondió el mensaje de campaña pasadas las 24 horas, se envía un webhook.

Al usar la [Manejo y envío de plantillas de WhatsApp](/developers/manejo-y-envio-de-plantillas-de-whatsapp.md#api-para-envios-bulk) la misma devuelve `campaignId` que puede ser usado para identificar a que campaña pertenece un webhook.

El payload del webhook contiene el siguiente formato

```
{
    "campaignId": int, 
    "campaignName": string,
    "templateId": int,
    "campaignStatus": "SENT",
    "timestamp": int,
    "succeededCustomers": [
        {"optiweId": int, "whatsappNumber":string},
        ...
    ],
    "failedCustomers": [
        {
            "optiweId": int, 
            "whatsappNumber":string,
            "metaFailedCode": string | null,
            "metaFailedReason": string | null,
        },
        ...
    ],
    "readCustomers": [
        {"optiweId": int, "whatsappNumber":string},
        ...
    ],
    "answerCustomers": [
        {"optiweId": int, "whatsappNumber":string},
        ...
    ],
    "unsubscribeCustomers": [
        {"optiweId": int, "whatsappNumber":string},
        ...
    ]
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://soporte.optiwe.com/developers/notificaciones-por-webhook.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
