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:
Crear template.
Esperar a que el template pase al estado aprobado.
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": "[email protected]",
"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": "[email protected]",
"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": "[email protected]",
"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
"campaignExtraFields": { // Opcional
"campaign_extra_field_example": 1
},
"customers" : [
{
"countryCode": "+54",
"phone" : "3442000000",
"fullName": "Customer1", // Opcional
"email": "[email protected]", // Opcional
"extraFields": { // Opcional
"street": "Street 1"
},
"campaignExtraFields": { // Opcional
"customer_campaign_extra_field_example": 2
},
// 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"
}
}
Derivación de conversación saliente por email de agente
La API de envíos Bulk permite el envío de mensajes salientes uno-a-uno con la posibilidad de derivar la conversación a un agente particular ingresando su dirección de email (campo userEmail
) en el cuerpo de la solicitud. Los campos sendAsync
y whatsappCampaignType
deben ser false
y "ONE_CUSTOMER" respectivamente para que la derivación funcione correctamente.
{
"templateId":10,
"customers": [
{
"countryCode": "+54",
"phone":"3442000000"
}
],
"sendAsync": false,
"whatsappCampaignType": "ONE_CUSTOMER",
"userEmail": "[email protected]"
}
Error de agente no encontrado
Código de respuesta:
HTTP 404 NOT FOUND
Encabezados de respuesta:
Content-Type:
application/json
Cuerpo de respuesta:
{
"error": {
"key": "INVALID_AGENT_EMAIL",
"message": "No agent found with email [email protected]"
}
}
Última actualización