Manejo y envío de plantillas de WhatsApp

Documentación del envío de mensajes plantillas mediante API

Descripción

El siguiente endpoint permite el envío de mensajes por medio de la aplicación WhatsApp. Algunas consideraciones a saber:

  • El envío de notificaciones push se realiza por medio del envío de mensajes que WhatsApp denomina templates. Un template contiene el formato que tendrá el mensaje. Por ejemplo: "Hola {{1}}, queremos recordarle que para el día de hoy a las {{2}} tiene un turno en {{3}}.". Al enviar una notificación, el endpoint realiza una verificación del mensaje para comprobar que respete el formato definido.

  • La secuencia de pasos son:

    1. Crear template.

    2. Esperar a que el template pase al estado aprobado.

    3. Enviar template en el momento que corresponda.

API para creación de plantillas

Este endpoint permite la creación de mensajes templates

Solicitud

  • URL: https://backend.optiwe.com/whatsapp-templates/

  • Verbo HTTP: POST

  • Encabezados de solicitud:

    • Content-Type: application/json

    • Authorization: Bearer YOUR_TOKEN

  • Cuerpo de solicitud:

{
   "key": "reminder",  // Solo puede contener letras en lower case, numeros y '_'
   "name": "reminder", // Solo puede contener letras en lower case, numeros y '_'
   "text": "Hola {{1}}, queremos recordarle que para el día de hoy a las {{2}} tiene un turno en {{3}}.",
   "example": "Hola Bob, queremos recordarle que para el día de hoy a las 14:00 tiene un turno en Clinica 2",
   "category": "UTILITY",
   "templateType": "TEXT",
   "language": "ENGLISH" | "SPANISH"
}

Ejemplo de plantilla con botones call to action y variables

Se pueden enviar hasta dos botones botones call to action. No se pueden enviar dos botones del mismo tipo. Es decir, solo se permite enviar un botón tipo URL y otro tipo PHONE_NUMBER.

Es posible crear plantillas con variables que luego sean reemplazadas mediante el uso de la api para envios bulk. Las variables tienen la forma {{<numero>}}y en el campo text las variables siempre deben empezar por {{1}}

Para las plantillas con botones con url dinámica, se puede usar una variable ya existente en el campo text o utilizar una nueva variable. Notar que solo se permite una variable en la url.

A continuación se presenta un ejemplo donde el campo texto posee dos variables y el botón con url posee otra variable adicional

{
   "key": "reminder",
   "name": "reminder",
   "text": "Hola {{1}}. Te escribimos desde {{2}}. Puedes llamarnos o vistar nuestra web para responder a tu consulta.",
   "example": "Hola Bob. Te tescribimos desde Argentina. Puedes llamarnos o vistar nuestra web para responder a tu consulta.",
   "category": "UTILITY",
   "templateType": "TEXT",
   "language": "ENGLISH" | "SPANISH",
   "buttons" : [
      {
         "type": "URL",
         "text": "Nuestra web", // 20 caracteres maximo
         "url": "https://example.com/{{3}}",
         "urlExample": "https://example.com/bobUrl"
      },
      {
         "type": "PHONE_NUMBER",
         "text": "Llamanos", // 20 caracteres maximo
         "phoneNumber":"543424010203"
      }
   ]
}

Ejemplo de plantilla con botones quick reply

{
   "key": "reminder",
   "name": "reminder",
   "text": "Hola. Responde este mensaje para actualizar tu consulta",
   "example": "Hola. Responde este mensaje para actualizar tu consulta",
   "category": "UTILITY",
   "templateType": "TEXT",
   "language": "ENGLISH" | "SPANISH",
   "buttons" : [ // Se permiten hasta 3 botones QUICK_REPLY
      {
         "type": "QUICK_REPLY",
         "text": "Responder", // 20 caracteres maximo
         "url": "https://example.com",
      }
   ]
}

Respuestas

Exitosa

  • Código de respuesta: HTTP 201 CREATED.

  • Cuerpo de respuesta:

{
    "id": int,
    "key": "reminder",
    "name": "reminder",
    "text" : "Hola {{1}}, queremos recordarle que para el día de hoy a las {{2}} tiene un turno en {{3}}.",
    "createdOn": "2023-10-06T13:41:54.746652Z",
    "updatedOn": "2023-10-06T13:41:54.746652Z",
    "status": "IN_REVIEW",
    "category": "MARKETING",
    "templateType": "TEXT",
    "language": "SPANISH" | "ENGLISH",
    "buttons" : [ // Campo presente si el template contiene buttones
        {
            "type":"PHONE_NUMBER",
            "text":"Llamanos",
            "phoneNumber":"543424010203"
        },
        {
            "type":"URL",
            "text":"Nuestra web",
            "url":"https://example.com/{{1}}",
            "urlExample":"https://example.com/bob/"
        }
    ]
}

Error template ya existente

  • Código de respuesta: HTTP 400 BAD REQUEST.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "TEMPLATE_ALREADY_EXISTS",
        "message": "The template already exists."
    }
}

Error de autenticación

  • Código de respuesta: HTTP 401 UNAUTHORIZED.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "NOT_AUTHENTICATED",
        "message": ""
    }
}

Error de validacion

  • Código de respuesta: HTTP 400 BAD REQUEST.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Posibles cuerpos de la respuesta

{
    "error": {
        "key": "BAD_REQUEST_BODY",
        "message": "Validation error",
        "details": {
            "buttons": "Buttons length must be greater than 0 and up to 3 buttons"
        }
    }
}
{
    "error": {
        "key": "BAD_REQUEST_BODY",
        "message": "Validation error",
        "details": {
            "name": "Key and name are only allowed to have small letters, numbers and underscore. Found: N"
        }
    }
}

API para listar plantillas

El siguiente endpoint permite obtener el estado de aprobación de los templates creados.

Los estados posibles son:

  • IN_REVIEW: El template se encuentra a la espera de la aprobación de WhatsApp.

  • APPROVED: El template ha sido aprobado por WhatsApp y está listo para ser utilizado.

  • DENIED: El template fue rechazado por WhatsApp.

Solicitud

  • URL: https://backend.optiwe.com/whatsapp-templates/

  • Verbo HTTP: GET

  • Encabezados de solicitud:

    • Authorization: Bearer YOUR_TOKEN

  • Cuerpo de solicitud: Vacio

Respuestas

Exitosa

  • Código de respuesta: HTTP 200 OK.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "templates": [{
            "id": 75,
            "key": "plantilla_1",
            "name": "plantilla_1",
            "text": "Hola",
            "createdOn": "2023-08-18T17:47:18.031649Z",
            "updatedOn": "2023-08-18T17:47:18.031701Z",
            "status": "IN_REVIEW",
            "category": "UTILITY",
            "templateType": "TEXT",
            "language": "SPANISH",
            "buttons": [
                {
                    "url": "https://optiwe.com/es/",
                    "text": "Nuestra web ",
                    "type": "URL",
                    "urlExample": "https://optiwe.com/es/"
                }
            ]
        }]
}

Error de autenticación

  • Código de respuesta: HTTP 401 UNAUTHORIZED.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "NOT_AUTHENTICATED",
        "message": ""
    }
}

API para envío de plantillas

Solicitud

  • URL: https://backend.optiwe.com/whatsapp-campaigns/customers/

  • Verbo HTTP: POST

  • Encabezados de solicitud:

    • Content-Type: application/json

    • Authorization: Bearer YOUR_TOKEN

  • Cuerpo de solicitud:

{
    "customerFullName": "Diego Optiwe",
    "customerEmail": "diego@email.com",
    "customerFields": {"dni": 123456789, "customerField1": "value"},
    "customerPhone": "1155174499",
    "customerCountryCode": "+54",
    "overrideCustomerData": true,
    "messagePayload": {
        "text": "Hola Diego, queremos recordarle que para el día de hoy a las 15:30 tiene un turno en Centro Medico Deragopyan."
    }
}
  • customerFullName (campo opcional): Nombre completo con el que se creará el cliente.

  • customerEmail (campo opcional): Email con el que se creará el cliente.

  • customerFields (campo opcional): JSON que contiene los campos de cliente con los que se creará el cliente. Los campos de cliente deben haber sido definidos previamente en el espacio de trabajo.

  • customerPhone (campo obligatorio): Número telefónico del cliente.

  • customerCountryCode (campo obligatorio): Código país del número telefónico.

  • overrideCustomerData (campo opcional): Si este campo es verdadero, los datos del cliente que figuren en el body reemplazarán a los datos del cliente ya creado. En caso contrario, solo se usarán los campos customerFullName, customerEmail y customerFields solo si el cliente no existe y será creado a partir del envío del saliente.

  • messagePayload (campo obligatorio): Mensaje que debe coincidir con un template ya aprobado. Si el template posee variables, pueden ser reemplazadas en este campo.

Envio de plantillas con botones

Se debera incluir en el campo "text" los botones formateados segun el siguiente ejemplo. Notar que se respeta el orden en el cual los botones fueron definidos cuando se creo la plantilla

{
    "customerFullName": "Diego Optiwe",
    "customerEmail": "diego@email.com",
    "customerFields": {"dni": 123456789, "customerField1": "value"},
    "customerPhone": "1155174499",
    "customerCountryCode": "+54",
    "overrideCustomerData": true,
    "messagePayload": {
        "text": "Hola Diego. Puedes llamarnos o vistar nuestra web para responder a tu consulta | [Llamanos,543424010203] | [Nuestra web,https://example.com/bob/]"
    }
}

Para el caso de botones quick reply


{
    "customerFullName": "Diego Optiwe",
    "customerEmail": "diego@email.com",
    "customerFields": {"dni": 123456789, "customerField1": "value"},
    "customerPhone": "1155174499",
    "customerCountryCode": "+54",
    "overrideCustomerData": true,
    "messagePayload": {
        "text": "Hola. Responde este mensaje para actualizar tu consulta | [Responder]"
    }
}

Respuestas

Respuesta exitosa

  • Código de respuesta: HTTP 201 OK

  • Cuerpo de respuesta: Vacío

Error template no coincidente

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "TEMPLATE_NOT_FOUND",
        "message": "The text sent do not match any template format."
    }
}

Error template no aprobado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "TEMPLATE_NOT_APPROVED",
        "message": "Template can not be used because is not approved."
    }
}

Error teléfono inválido

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "INVALID_WHATSAPP_NUMBER",
        "message": "Whatsapp number is not valid. Please, check if the country code and phone number are correct"
    }
}

Error cliente desuscrito

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "CUSTOMER_OPTED_OUT",
        "message": "Message will not be sent because the customer has opted out for outbound messages"
    }
}

Error limite de salientes superado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "WHATSAPP_OUTBOUND_LIMIT_EXCEEDED",
        "message": "Outbound message exceeds available tier limit"
    }
}

Error campo de cliente no existente

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "INVALID_CUSTOMER_FIELDS",
        "message": "Customer fields {invalid_customer_fields} do not exist in workspace. Valid fields are {valid_customer_fields}"
    }
}

Error cuota de uso de API alcanzado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "REQUESTS_LIMIT_REACHED",
        "message": "Maximum amount of HTTP request reached for endpoint /whatsapp-campaigns/customers/"
    }
}

Error de autenticación

  • Código de respuesta: HTTP 401 UNAUTHORIZED.

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "NOT_AUTHENTICATED",
        "message": ""
    }
}

API para envíos bulk

Esta API permite enviar mensajes a varios clientes con una sola request HTTP a nuestros servidores. Recomendamos usar este endpoint para una mejor utilización de recursos.

Al enviar una campaña mediante esta API, los resultados de la misma se podrán visualizar mediante el dashboard.

Solicitud

  • URL: https://backend.optiwe.com/whatsapp-campaigns/bulk/customers/

  • Verbo HTTP: POST

  • Encabezados de solicitud:

    • Content-Type: application/json

    • Authorization: Bearer YOUR_TOKEN

  • Cuerpo de solicitud:

{
    "templateId": 10,
    "campaignName": "Mi campaña con template 1",     // Opcional
    "customers" : [
        {
           "countryCode": "+54",
           "phone" : "3442000000",
           "fullName": "Customer1", // Opcional
           "email": "customer1@example.com", // Opcional
           "extraFields": { // Opcional
              "street": "Street 1"
           },
           // templatePlaceholders es necesario si
           // el template posee placeholders de la forma {{<numero>}} tanto en
           // el cuerpo como en los botones. E.g {{1}}
           // Para el caso de placeholders de la forma {{<objeto>.<propiedad>}} E.g {{customer.name}}
           // Optiwe completa automaticamente estos campos.
           "templatePlaceholders" : { 
                 1: "Nombre",
                 2: "Segundo nombre"
           }
        }, ...
    ]
}

Respuestas

Respuesta exitosa

Nótese que una campaña puede crease de manera exitosa y aun así no tener clientes con números validos. En cuyo caso, los mismos son informados en el cuerpo de la respuesta.

  • Código de respuesta: HTTP 201 OK

  • Encabezados de solicitud:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
     "campaignId": 1,
     "invalidCustomers" : [
         {
             "phone" : "+543442567890",
             "reason" : "INVALID_EXTRA_FIELDS" | "INVALID_NUMBER",
         }, ...
     ]
}

Error template no encontrado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "TEMPLATE_NOT_FOUND",
        "message": "Template 10, not found"
    }
}

Error template no aprobado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "TEMPLATE_NOT_APPROVED",
        "message": "Template 10 is not approved"
    }
}

Error placeholders invalidos

  • Código de respuesta: HTTP 422 UNPROCESSABLE ENTITY

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "INVALID_TEMPLATE_PLACEHOLDER",
        "message": "Invalid placeholders for customers ['+543442506786', '+112345454', ...]"
    }
}

Error limite de salientes superado

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "WHATSAPP_OUTBOUND_LIMIT_EXCEEDED",
        "message": "Outbound message exceeds available tier limit"
    }
}

Error whatsapp outbound no activada

  • Código de respuesta: HTTP 400 BAD REQUEST

  • Encabezados de respuesta:

    • Content-Type: application/json

  • Cuerpo de respuesta:

{
    "error": {
        "key": "WHATSAPP_OUTBOUND_NOT_ENABLED",
        "message": "Whatsapp outbound config not enabled"
    }
}

Última actualización