NAV Navbar
cURL Ruby Python PHP Java

en es pt

Introduction

Welcome to our documentation for developers. Here you’ll find everything you need to integrate your business to our messaging platform.

Here are the possible ways of integrating with us:

API HTTPS Allows sending and receiving messages and their statuses over HTTPS protocol, using GET or POST methods
API SMPP Standard protocol for SMS messages exchange, allows a permanent connection to be kept with our SMPP server, its use is encouraged for clients expecting traffic of over 5 million messages per month
API SFTP Protocol used for file transfer, its use is encouraged for mass delivery of messages (bulk). The files are tranfered by the client to our servers and are immediately processed
Websphere MQ Protocol used for transfer of messages between Webserver MQ servers, its use is encouraged for clients with traffic of over 30 million messages per month, specially financial institutions, which the company already has the system in place for internal messages. This integration option has setup and maintenance costs, fixed at R$50.000,00 and R$2.000,00 respectively

You can also visit our Web portal. There, your business is able to manage users, projects and configurations, send and receive messages, and obtain reports, without the need of any development of integration on your side

SMS API

Key Terms

MT Mobile Terminated A message that has a user (device) as destination. That is, a message that was sent by your company to be delivered to a user (device)
Response Synchronous Wavy response The immediate answer of a request made to our API, where we let you know whether the message was accepted by our platform, or not
Callback Sent status The first delivery status that we return, where we let you know whether it was possible to deliver the message to the carrier, or not
DR or DLR Delivery Receipt The second delivery status we return, where we let you know whether it was possible to deliver the message to the device, or not. The carriers deliver this information to Wavy, and we relay it to the client. The time it takes for a DLR to be delivered varies, for example, if the device was turned off at the moment the MT was sent, and the user only turns it on two hours later, this DLR status will be delivered to the client two hours later.
Obs1: This confirmation of delivery on the device will only exist when the message was successfully delivered to the carrier, that is, only if the first status (Callback) was successful.
Obs2: It is very important to make it clear that sadly, some carriers like OI and Sercomtel do not have this functionality. Therefore, they do not give Wavy any information of the message being delivered to devices. The deliveries made to these carriers will only have information of delivery to the carrier (Callback).
MO Mobile Originated A message that has your business as destination, that is, messages that were sent by the user (device). MOs are used, for example, during question and answer flows via SMS, when a confirmation is necessary by the user.
LA Short Code Short number of 5 or 6 digits, used for delivering and receiving SMS messages. They possess anti-fraud and anti-spam rules and carriers only distribute and allow their usage by homologated integrators like Wavy

Message Flow

Simplified Flow - MT, Callback, DLR, e MO.

alt text

API HTTPS

This API allows you to automatize both single and bulk message requests and the recovery of sent status through its endpoints. It uses HTTP protocol with TLS and accepts GET requests with query string parameters and POST requests with JSON parameters.

Authentication

To send messages and get status through the API, it is necessary to authenticate using a combination of either username or email and and authentication token.

Field Details Data Type
UserName Your username or email String
AuthenticationToken Your authentication token. Get yours here String
Type Details
Administrator Administrator user of your company, it is used to create/edit/deactivate sub accounts and other users, can see reports of the whole company.
This user does not send messages, not through the portal or through the HTTPS API integration.
Regular Regular user used to send messages through the HTTPS API and portal. Can see reports specific to his sub account.
A user is always paired with a single sub account.
A sub account may contain multiple users.
Each sub account is a cost center in our platform, messages will be separated in financial reports by sub account, not by user.

Connection Details

Hostname api-messaging.wavy.global
APIs Single message /v1/send-sms
Bulk messages /v1/send-bulk-sms
Port 443 (https)
Protocol HTTPS (TLS encryption)
Authentication username + token
Portal messaging.wavy.global

Encoding

The standard of encoding is UTF-8, all message texts must follow this standard.

You can also escape special characters or use HTTP format.

You can see some encoding examples besides.

“messageText”:“A combinação foi perfeita :)”

You may escape special characters:

“messageText”:“A combina\u00e7\u00e3o foi perfeita :)”

Sending Messages (MT)

Sending with GET method - Individual

require 'uri'
require 'net/http'

url = URI("https://api-messaging.wavy.global/v1/send-sms")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["username"] = '<username>'
request["authenticationtoken"] = '<authenticationtoken>'
request["content-type"] = 'application/json'
request.body = "{\"destination\": \"5511900000000\" ,  \"messageText\": \"linha\\nquebrada\"}"

response = http.request(request)
puts response.read_body
import requests

url = "https://api-messaging.wavy.global/v1/send-sms"

payload = "{\"destination\": \"5511900000000\" ,  \"messageText\": \"linha\\nquebrada\"}"
headers = {
    'username': "<username>",
    'authenticationtoken': "<authenticationtoken>",
    'content-type': "application/json"
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)
curl -X POST \
  https://api-messaging.wavy.global/v1/send-sms \
  -H 'authenticationtoken: <authenticationtoken>' \
  -H 'username: <username>' \
  -H 'content-type: application/json' \
  -d '{"destination": "5511900000000" , "messageText": "linha\nquebrada"}'

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api-messaging.wavy.global/v1/send-sms",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"destination\": \"5511900000000\" ,  \"messageText\": \"linha\\nquebrada\"}",
  CURLOPT_HTTPHEADER => array(
    "authenticationtoken: <authenticationtoken>",
    "username: <username>",
    "content-type: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class SendSms {

    public static void main(String[] args) {
        String url = "https://api-messaging.wavy.global/v1/send-sms";

        String userName = "<username>";
        String authenticationToken = "<authenticationtoken>";

        String body = "{\"destination\": \"5511900000000\" ,  \"messageText\": \"linha\\nquebrada\"}";

        String response = doPost(url, body, userName, authenticationToken);
        System.out.println(response);
    }

    public static String doPost(String strUrl, String request, String userName, String authenticationToken) {
        HttpURLConnection conn = null;
        OutputStreamWriter wr = null;
        BufferedReader br = null;
        try {
            URL url = new URL(strUrl);

            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setInstanceFollowRedirects(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);

            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("UserName", userName);
            conn.setRequestProperty("AuthenticationToken", authenticationToken);

            // write the request
            wr = new OutputStreamWriter(conn.getOutputStream());
            wr.write(request);
            wr.close();

            // read the response
            br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            StringBuilder resp = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                resp.append(line).append("\n");
            }
            return resp.toString();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (wr != null) {
                    wr.close();
                }
                if (br != null) {
                    br.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

As response, you will receive a JSON informing the id that was generated for this message. (Response or Wavy’s synchronous response):

[
  {
  "id":"9cb87d36-79af-11e5-89f3-1b0591cdf807"
  }
]

Using GET, you can make a message request sending all parameters in the query string.

Single Message GET Request URL

GET https://api-messaging.wavy.global/v1/send-sms?destination=..

Using POST, you can make a message request sending all parameters in the body.

Single Message POST Request URL

POST https://api-messaging.wavy.global/v1/send-sms - Content-Type: application/json

Request Parameters

* Required Field

Field Details Type
destination* Phone to which the message will be sent to (including country code). E.g.: 5511900000000 String
messageText* Message text to be sent (max 1280 chars) String
correlationId A unique ID defined by you for matching with sent statuses (callback and DLR). This parameter is optional, and you can use the ID generated by Wavy for the same porpuse (max 64 chars). String
extraInfo Any information you want to add to the message (max 255 chars). String
timeWindow Messages will be sent only during the specified hours. E.g., configuring a time window of [11, 12, 18], the messages will be sent between 11:00 and 11:59, 12:00 and 12:59, and 18:00 and 18:59, this parameter must be added on the root of the JSON object Integer[]
expiresAt Messages will not be delivered after this date. Date format is Unix time . Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) Long
expiresInMinutes Messages will expire after the time set in this field. Time starts to count as soon as the message request is received by Wavy. Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) Long
expiresDate The message will not be sent after this date. Date format is yyyy-MM-dd’T'HH:mm:ss. Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) String
scheduledAt Messages will not be delivered before this date. IMPORTANT! Its possible to schedule only a period superior to 30 minutos because scheduled mesasges are processed by a differentiated flow from non scheduled messages. Date format is Unix time . Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) Long
delayedInMinutes Messages will only be sent after the time set on this field. Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) Long
scheduledDate The message will not be sent before this date. Date format is yyyy-MM-dd’T'HH:mm:ss. Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) String
timeZone Specifies the timezone to be used directly on the fields expiresDate, scheduledDate and timeWindow (that will be changed if dynamic timezones are chosen, e.g. Daylight Saving Time). If a timezone is not set on the request, it will use the the timezone of the user - if the user’s timezone is not set as well, it will use the timezone of that user’s country. Last case scenario, UTC timezone will be used. String
campaignAlias Identification of a previously created campaign. You can create a new campaign here String
flashSMS Set this option to true to send a message that pops-up on the user’s device. Boolean
flowId Bot flow identifier. The message text will come from the flow String
subAccount SubAccount reference. It can only be used by Administrators String
params Map of placeholders that will be replaced in the message. If one or more params are incorrect, the message will be marked as invalid, but the bulk will not be canceled. You must use a flowId to pass the parameters Map

Sending Messages with POST - Single and Bulk

require 'uri'
require 'net/http'

url = URI("https://api-messaging.wavy.global/v1/send-bulk-sms")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["username"] = '<username>'
request["authenticationtoken"] = '<authenticationtoken>'
request["content-type"] = 'application/json'
request.body = '{ "messages":[{ "destination":"5519999999999", "messageText":"First message" }, { "destination":"5519999999999" }, { "destination":"5519999999999" }], "defaultValues":{"messageText":"Default message" }}'

response = http.request(request)
puts response.read_body
import requests

url = "https://api-messaging.wavy.global/v1/send-bulk-sms"

payload = '{ "messages":[{ "destination":"5519999999999", "messageText":"First message" }, { "destination":"5519999999999" }, { "destination":"5519999999999" }], "defaultValues":{"messageText":"Default message" }}'
headers = {
    'username': "<username>",
    'authenticationtoken': "<authenticationtoken>",
    'content-type': "application/json"
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)
curl --request POST \
  --url https://api-messaging.wavy.global/v1/send-bulk-sms \
  --header 'authenticationtoken: <Token de autenticação>' \
  --header 'username:<Usuário Wavy Messaging>' \
  --header 'content-type: application/json' \
  --data '{ "messages":[{ "destination":"5519999999999", "messageText":"First message" }, { "destination":"5519999999999" }, { "destination":"5519999999999" }], "defaultValues":{"messageText":"Default message" }}'

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api-messaging.wavy.global/v1/send-bulk-sms",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{ \"messages\":[{ \"destination\":\"5519999999999\", \"messageText\":\"First message\" }, { \"destination\":\"5519999999999\" }, { \"destination\":\"5519999999999\" }], \"defaultValues\":{\"messageText\":\"Default message\" }}",
  CURLOPT_HTTPHEADER => array(
    "authenticationtoken: <authenticationtoken>",
    "content-type: application/json",
    "username: <username>"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class SendSms {

    public static void main(String[] args) {
        String url = "https://api-messaging.wavy.global/v1/send-bulk-sms";

        String userName = "<username>";
        String authenticationToken = "<authenticationtoken>";

        String body = "{ \"messages\":[{ \"destination\":\"5519999999999\", \"messageText\":\"First message\" }," +
                " { \"destination\":\"5519999999999\" }, { \"destination\":\"5519999999999\" }]," +
                " \"defaultValues\":{\"messageText\":\"Default message\" }}";

        String response = doPost(url, body, userName, authenticationToken);
        System.out.println(response);
    }

    public static String doPost(String strUrl, String request, String userName, String authenticationToken) {
        HttpURLConnection conn = null;
        OutputStreamWriter wr = null;
        BufferedReader br = null;
        try {
            URL url = new URL(strUrl);

            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setInstanceFollowRedirects(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);

            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("UserName", userName);
            conn.setRequestProperty("AuthenticationToken", authenticationToken);

            // write the request
            wr = new OutputStreamWriter(conn.getOutputStream());
            wr.write(request);
            wr.close();

            // read the response
            br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            StringBuilder resp = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                resp.append(line).append("\n");
            }
            return resp.toString();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (wr != null) {
                    wr.close();
                }
                if (br != null) {
                    br.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

As response, you will receive a JSON object with the UUID of the bulk and its individual messages:


{
    "id": "592e6940-31cd-11e7-9369-8e79624807c4",
    "messages": [{
        "id": "592e6941-31cd-11e7-9369-8e79624807c4"
    }, {
        "id": "592e6942-31cd-11e7-9369-8e79624807c4"
    }, {
        "id": "592e6943-31cd-11e7-9369-8e79624807c4"
    }]
}

Allows sending messages, both single and bulk, passing parameters in a JSON object

HTTP Request using POST

JSON example for sending bulk messages

Example 1:

{
  "messages":[
    {
      "destination":"5519900001111",
      "messageText":"First message"
    },
    {
      "destination":"5519900002222"
    },
    {
      "destination":"5519900003333"
    }
  ],
  "defaultValues":{
    "messageText":"Default message"
  }
}

Example 2:

{
  "messages":[
    {
      "destination":"5519900001111",
      "messageText":"First message"
    },
    {
      "destination":"5519900002222"
    }
  ],
  "timeZone":"America/Sao_Paulo",
  "scheduledDate": "2017-01-28T02:30:43",
  "timeWindow": [12, 15, 20],
  "defaultValues":{
    "messageText":"Default message"
  }
}

Example 3:

{
  "messages":[
    {
      "destination":"5519900001111"
    },
    {
      "destination":"5519900002222"
    }
  ],
  "defaultValues":{
    "messageText":"Default message",
    "flashSMS":"true"
  }
}

Example 4, with flowId and params:

{
  "messages":[
    {
      "destination":"5519900001111",
      "params": {
        "param1": "other_value1",
        "param2": "other_value2"
      }
    },
    {
      "destination":"5519900002222"
    }
  ],
  "defaultValues":{
    "params": {
      "param1": "value1",
      "param2": "value2"
    }
  },
  "flowId": "14f8142d-e731-4971-8220-5a76a12c413f"
}

Observe that in the examples above, some of the messages do not have a “messageText”. In these cases, the message text will be the “messageText” field inside “defaultValues”. This feature is useful when it is necessary to send the same message to many different numbers.

POST https://api-messaging.wavy.global/v1/send-bulk-sms Content-Type: application/json

The request body must contain the JSON object according to the fields below:

* Required Field

Field Details Type
destination* Phone to which the message will be sent to (including country code). E.g.: 5511900000000 String
messageText* Message text to be sent (max 1280 chars). String
correlationId A unique ID defined by you for matching with sent statuses (callback and DLR). This parameter is optional, and you can use the ID generated by Wavy for the same porpuse (max 64 chars). String
extraInfo Any information you want to add to the message (max 255 chars). String
timeWindow Messages will be sent only during the specified hours. E.g., configuring a time window of [11, 12, 18], the messages will be sent between 11:00 and 11:59, 12:00 and 12:59, and 18:00 and 18:59 Integer[]
expiresAt Messages will not be delivered after this date. Date format is Unix time . Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) Long
expiresInMinutes Messages will expire after the time set in this field. Time starts to count as soon as the message request is received by Wavy. Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) Long
expiresDate The message will not be sent after this date. Date format is yyyy-MM-dd’T'HH:mm:ss. Obs: The fields expiresAt, expiresInMinutes and expiresDate are mutually exclusive (use only one of them) String
scheduledAt Messages will not be delivered before this date. Date format is Unix time . Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) Long
delayedInMinutes Messages will only be sent after the time set on this field. Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) Long
scheduledDate The message will not be sent before this date. Date format is yyyy-MM-dd’T'HH:mm:ss. Obs: The fields scheduledAt, delayedInMinutes and scheduledDate are mutually exclusive (use only one of them) String
timeZone Specifies the timezone to be used directly on the fields expiresDate, scheduledDate and timeWindow (that will be changed if dynamic timezones are chosen, e.g. Daylight Saving Time). If a timezone is not set on the request, it will use the the timezone of the user - if the user’s timezone is not set as well, it will use the timezone of that user’s country. Last case scenario, UTC timezone will be used. String
campaignAlias Identification of a previously created campaign. You can create a new campaign here String
flashSMS Sett this option to true to send a message that pops-up on the user’s device. Boolean
flowId Bot flow identifier. The message text will come from the flow String
subAccount SubAccount reference. It can only be used by Administrators String
params Map of placeholders that will be replaced in the message. If one or more params are incorrect, the message will be marked as invalid, but the bulk will not be canceled. You must use a flowId to pass the parameters Map

Bulk message response

The response of a bulk message request will have a JSON object with the required tracking information. A unique ID will be generated for the bulk as well as for every message. Messages that were sent with a correlationId will have it listed as well.

Field Details Type
id UUID generated for this bulk String
messages This field is an array with the responses of every single message request of the bulk. It contais the id and correlationId of every message sent. SingleSMSResponse[]

HTTP Status Code Response

Status Code of HTTP response common:

Group Description
2xx Success
4xx Client Error
5xx Server Error
Code Description
200 Success
400 Bad request
401 Unauthorized
403 Forbidden
404 Not found
500 Internal Server Error
503 Service Unavailable
504 Gateway Timeout

Sent Status (Callback and DLR)

There are two ways of obtaining the sent status of a message:

As soon as we send a message to the carrier, or as soon as the carrier informs us if it has delivered a message to a device, the information is relayed immediately to you.

The statuses are available for three days, and they can be retrieved using the UUID returned when Wavy accepts a message of your company or the correlation ID provided by you to identify the message.
The disadvantage of this option comparing with webhooks is that you may request information on messages that may not yet have been sent to the carrier or to the device, this way, a series of unnecessary requests can be made. E.g.: If a device is turned off when you send it a message, and only turned on two hours later, you may spend two hours making unnecessary requests with its ID. On the other hand, using status through webhook, the information will be delivered to you as soon as it is delivered to the device, without any empty requests.

Status through webhook (delivered to your webservice)

To configure the delivery of Callbacks and DRs (if you have doubts about the terms, check the area Important Terms) first you need to login to Wavy Messaging at the API configuration area, where using the form, you will be able to configure to which URLs our sent status (Callbacks) and delivered to the device status (DRs) should be delivered to.

It may take up to 10 minutes for the information of the webhook configuration to take effect. After it has, we will call your URLs when the following actions happen:

Action Return status sent
After a message is delivered, or not, to the carrier. Message sent status API (callback)
When a message is delivered, or not, to a user’s device. Delivery report API (DRs)

JSON Message sent status example (callback - delivered to the carrier)

POST https://example.com/callback/
Content-Type: application/json

{
  "id":"f9c100ff-aed0-4456-898c-e57d754c439c",
  "correlationId":"client-id",
  "carrierId":1,
  "carrierName":"VIVO",
  "destination":"5511900009999",
  "sentStatusCode":2,
  "sentStatus":"SENT_SUCCESS",
  "sentAt":1266660300000,
  "sentDate":"2010-02-20T10:05:00Z",
  "campaignId":"64",
  "extraInfo":"",
}

JSON response fields on Callbacks (sent status)

Fields Description
id UUID for messge reference
correlationId ID provided by you when you send the message
carrierId Carrier Identification
carrierName Carrier Name
destination Phone the message was delivered to
sentStatusCode Status code generated by Wavy for the message stating the sent status. Take a look at message status codes for more information
sentStatus Description of the sent status. Take a look at message status codes for more information
sentAt Time the message was sent, using Unix_time format
sentDate Date the message was set. Format: yyyy-MM-dd’T'HH:mm:ssZ
campaignId Campaign Identification if it exists
extraInfo Any other information added by the client during the act of sending the message

JSON response fields on Delivery Reports (DRs)

Field Description
id UUID for messge reference
correlationId ID provided by you when you send the message
carrierId Carrier Identification
carrierName Carrier Name
destination Phone the message was delivered to
sentStatusCode Status code generated by Wavy for the message stating the sent status. Take a look at message status codes for more information
sentStatus Description of the sent status. Take a look at message status codes for more information
sentAt Time the message was sent, using Unix_time format
sentDate Date the message was set. Format: yyyy-MM-dd’T'HH:mm:ssZ
deliveredStatusCode Status code generated by Wavy for the message stating the delivery status. Take a look at message status codes for more information
deliveredStatus Description of the delivery status. Take a look at message status codes for more information
deliveredAt Time of the delivery, using Unix_time format
deliveredDate Date of the delivery. Format: yyyy-MM-dd’T'HH:mm:ssZ
campaignId Campaign Identification if it exists
extraInfo Any other information added by the client during the act of sending the message

Message Status through HTTP requests

To get a list of the status not yet consulted, you can make a GET request to the URL below:

GET https://api-messaging.wavy.global/v1/sms/status/list

Look that this endpoint only returns the statuses that aren’t sent by this endpoint.

Response

JSON fields:

Field Description
id UUID for messge reference
correlationId ID provided by you when you send the message
carrierId Carrier Identification
carrierName Carrier Name
destination Phone the message was delivered to
sentStatusCode Status code generated by Wavy for the message stating the sent status. Take a look at message status codes for more information
sentStatus Description of the sent status. Take a look at message status codes for more information
sentStatusAt Time the message was sent, using Unix_time format
sentStatusDate Date the message was set. Format: yyyy-MM-dd’T'HH:mm:ssZ
deliveredStatusCode Status code generated by Wavy for the message stating the delivery status. Take a look at message status codes for more information
deliveredStatus Description of the delivery status. Take a look at message status codes for more information
deliveredAt Time of the delivery, using Unix_time format
deliveredDate Date of the delivery. Format: yyyy-MM-dd’T'HH:mm:ssZ
campaignId Campaign Identification if it exists
extraInfo Any other information added by the client during the act of sending the message

JSON Delivery Report Exemple (DR ou DLR - Delivery to a Device)

{
  "id":"8f5af680-973e-11e4-ad43-4ee58e9a13a6",
  "correlationId":"myId",
  "carrierId":5,
  "carrierName":"TIM",
  "destination":"5519900001111",
  "sentStatusCode":2,
  "sentStatus":"SENT_SUCCESS",
  "sentStatusAt":1420732929252,
  "sentStatusDate":"2015-01-08T16:02:09Z",
  "deliveredStatusCode":4,
  "deliveredStatus":"DELIVERED_SUCCESS",
  "deliveredAt":1420732954000,
  "deliveredDate":"2015-01-08T16:02:34Z",
  "campaignId":1234
}

User response (MO)

The MO API alllows automation of the process of retrieving the answers given by users to the messages you sent them. Every request uses the GET method and the responses are sent as JSON objects.

It is also possible to configure a webhook for the MOs to be delivered to as they are received. This is the most efficient way, because it makes it unnecessary to make any requests, only handle the messages as they arrive. For this configuration to be made, it is necessary to open a Ticket with our tech support team sending a request through our Service Center including the URL that should receive the MOs.

JSON example sent to your API (POST method)

{
     "id": "25950050-7362-11e6-be62-001b7843e7d4",
     "subAccount": "iFoodMarketing",
     "campaignAlias": "iFoodPromo",
     "carrierId": 1,
     "carrierName": "VIVO",
     "source": "5516981562820",
     "shortCode": "28128",
     "messageText": "Eu quero pizza",
     "receivedAt": 1473088405588,
     "receivedDate": "2016-09-05T12:13:25Z",
     "mt": {
       "id": "8be584fd-2554-439b-9ba9-aab507278992",
       "correlationId": "1876",
       "username": "iFoodCS",
       "email": "customer.support@ifood.com"
     }
   }

Each request made will return the MOs received during the last 5 days, up to a limit of 1,000 MOs. For previous times of larger quantities, please get in contact with our tech support team through our Service Center.

The behavior of the query List MO will be different for each authenticated user, according to his permission level.

We recommend the method of delivering the MOs to a webhook, every MO will be automatically delivered and can be immediately handled after it is received

Role Permission
Regular Each request made through the MO API will only return the MOs corresponding to the sub account that user belongs to. It is not possible for a regular user to retrieve the MOs of other sub accounts.
Administrator The default behavior for the Administrator user is to recover all MOs from all sub accounts. If an administrator user desires to retrieve the MOs of only one sub account, it is necessary to specify the sub account in the parameter subAccount with the id or reference of the sub account it wishes to recover MOs from.

Default MO response format

JSON response example (Wavy API request):

{
  "total": 1,
  "start": "2016-09-04T11:12:41Z",
  "end": "2016-09-08T11:17:39.113Z",
  "messages": [
    {
      "id": "25950050-7362-11e6-be62-001b7843e7d4",
      "subAccount": "iFoodMarketing",
      "campaignAlias": "iFoodPromo",
      "carrierId": 1,
      "carrierName": "VIVO",
      "source": "5516981562820",
      "shortCode": "28128",
      "messageText": "Eu quero pizza",
      "receivedAt": 1473088405588,
      "receivedDate": "2016-09-05T12:13:25Z",
      "mt": {
        "id": "8be584fd-2554-439b-9ba9-aab507278992",
        "correlationId": "1876",
        "username": "iFoodCS",
        "email": "customer.support@ifood.com"
      }
    },
    {
      "id": "d3afc42a-1fd9-49ff-8b8b-34299c070ef3",
      "subAccount": "iFoodMarketing",
      "campaignAlias": "iFoodPromo",
      "carrierId": 5,
      "carrierName": "TIM",
      "source": "5519987565020",
      "shortCode": "28128",
      "messageText": "Meu hamburguer está chegando?",
      "receivedAt": 1473088405588,
      "receivedDate": "2016-09-05T12:13:25Z",
      "mt": {
        "id": "302db832-3527-4e3c-b57b-6a481644d88b",
        "correlationId": "1893",
        "username": "iFoodCS",
        "email": "customer.support@ifood.com"
      }
    }
  ]
}

Both listing (list) and searching (search) requests return a JSON object with the following fields:

Field Details Type
total Total number of MOs returned by the request Integer
start The minimum limit of the query String
end The maximum limit of the query String
messages A list of the message objects List

Each message object has the following fields:

Field Details Type
id message id String
subAccount subconta responsible for sending the message that generated this MO String
carrierId Carrier ID Integer
carrierName Carrier Name String
source Phone number that sent the MO String
shortCode The shortcode of the message that generated this MO and to which the answer was sent String
messageText Text sent as answer String
receivedAt time message was received Long
receivedDate Date the message was received in UTC format String
campaignAlias Alias da campanha que originou a resposta String
mt MT that generated the message MT

MTs have the following fields

Field Details Type
id Id of the MT String
correlationId correlationID sent on the MT String
username Username of the user responsible of sending the MT String
email Email of the user responsible of sending the MT String

List MO request (list)

The listing request will return all MOs received since the last time this request was made according to the description above. Once this request is made, MOs will be consumed and will not be returned on following calls.

As a regular user, to recover all MOs of a sub account, use:

GET https://api-messaging.wavy.global/v1/sms/receive/list

As an administrator user, to recover all MOs from ALL sub accounts, use:

GET https://api-messaging.wavy.global/v1/sms/receive/list

As an administrator user, to recover the MOs of a specific sub account with reference “sub_account_reference”, use:

GET https://api-messaging.wavy.global/v1/sms/receive/list?subAccount=sub_account_reference

Send Message Status Codes (Callback and DLR)

There are two independently sent status levels.

1 - First status (sent_status - Sent Status = Callback)

Sent status to the carrier, this is the first status we return, supported by all carriers.

Code Message Meaning
2 SENT_SUCCESS Successfully sent to the carrier (This is the status considered for billing purposes.)
101 EXPIRED Expired before being sent to the handset
102 CARRIER_COMMUNICATION_ERROR Communication error with the carrier
103 REJECTED_BY_CARRIER Carrier rejected the message
201 NO_CREDIT The message limit set by the administrator of your business, for you account or sub account, was reached. If you business uses the prepaid charging model, it means you have used all messages you have paid for.
202 INVALID_DESTINATION_NUMBER The destination number is invalid (It is not a valid mobile phone number).
203 BLACKLISTED The destination number is blacklisted, it was manually put into the blacklist by your business.
204 DESTINATION_BLOCKED_BY_OPTOUT The destination number has opted-out of your messages. It no longer wants to receive messages from your sub account. (This status is specific for mobile marketing accounts)
205 DESTINATION_MESSAGE_LIMIT_REACHED The destination number has already received the maximum amount of messages that a single business may send in a given period of time. (This status is specific for Mobile Marketing and it is a rule set by the carriers)
207 INVALID_MESSAGE_TEXT The text of the message contains words that are not accepted by the carrier. It may contain foul language or, if you account is Mobile Marketing, you may be using names of large companies.
301 INTERNAL_ERROR There was an internal error on Wavy’s platform

2 - Second status (delivered_status - Delivery Report Callback)

Delivery status to a device, this is the second status we return, and it only exists when the first status cited above was successful, that is, if the message was successfully send to the carrier. In this status we inform whether the message was sent to the device or not. Carriers Oi and Sercomtel do not possess this second status level, for these carriers, we can only return the information of the first status, that is, if the message was delivered to the carrier or not.

Code Message Meaning
4 DELIVERED_SUCCESS Successfully delivered to the device.
104 NOT_DELIVERED The carrier accepted the message but was not able to deliver it to the device. Possible causes:
The device is turned off or out of the service area for a given period of time (normally 24h, but for some carriers, such as Vivo, the retry period is only 8 hours.)
Valid number, but inactive (some carriers return this kind of error only on this second level status).

API SMPP

All services provided by Wavy are required to be encrypted. The SMPP protocol does not possess native encryption. Because of that, we provide the two following alternatives for integration:

This is the recommended option. If your system does not possess this functionality, get help on the configuration of a TLS proxy HERE.

Beyond the TLS encryption, access will be authorized only for your server’s the public IP. (We accept multiple IPs and IP ranges) This information must be sent a request to our tech support in our Service Center.

If there is the need to allow outgoing traffic on your firewall, we recommend to allow any destination IP on port 2444. If this is not possible, you must include rules allowing the addresses below:
200.219.220.8:2444
200.219.220.193:2444
45.236.179.18:2444
45.236.179.19:2444

SMPP over VPN

The encryption and access granting will be made through VPN

If you choose this option, configure the VPNs using the peers and hosts below, already with the phase 1 and 2 proposals you wish. Send the filled in VPN form of your company to our tech support in our Service Center.

peer 200.155.0.250
hosts 200.219.220.8 and 200.219.220.193
port 2443

peer 45.236.178.12
hosts 45.236.179.18 and 45.236.179.19
port 2443

Obs: For high availability and load balancing, it is required to establish the 2 VPNs above, and to use the domain address smpp-messaging.wavy.global as destination in your SMPP client, instead of IPs.

Connection Details

Information Details
Hostname / IP Address smpp-messaging.wavy.global
When you configure your SMPP system, it is required to use the domain as destination, instead of IPs.
This domain has 4 entrance proxies with round robin DNS and health check and multiple servers backend. Based on the volume of messages your business will send, we can increase the number o binds(connections) allowed simultaneously.
Port 2444 (SMPP over TLS) or 2443 (VPN)
SMPP Version 3.4
Bind Count The establishment of at least four binds is mandatory for high availability and load balancing. Minimum of 4.
Character Encoding GSM7 - Default (data_coding = 0) (GSM3.38 extended table is not supported by carriers.)
LATIN1 (data_coding = 1)
UCS2 (data_coding=8).
Atention: Check HERE details of characters and billing.
Flash SMS Supported
data_coding=0x10 for GSM7 and data_coding 0x18 for UCS2
When we receive a flashSMS from our customer, it will be sent to the carrier as flashSMS, if the carrier doesn’t accept flashSMS, it will be delivered as a regular SMS.
Enquire-link Minimum: 30 seconds / Maximum: 59 seconds.
Concatenation UDH 8-bit and 16-bit are supported / UDH Headers
Default addr_ton 1
Default addr_npi 1
window size 10
2way Supported
SMPP bind type Transceiver(Recommended). Binding transmit/receiver separately is also accepted.
SMPP system_type MovileSMSC
SMPP source addr (senderID) When your service needs user’s responses (MO), the source address must be equal to the system_id, that is, the name of the user. When there is no need of MOs, you may use anything on this field.
Max MO throughput 80 per bind
Max MT throughput 80 per bind
Server Timezone UTC
ID Format UUID
Default validity_period 24 hours

Send Message Status Codes (Callback and DLR)

1 - First status (sent_status - Sent Status = Callback)

Sent status to the carrier, this is the first status we return, supported by all carriers.

stat err TLV (0x1403) TLV (0x1404) Meaning
ACCEPTD 000 2 SENT_SUCCESS Successfully sent to the carrier. (This is the status considered for billing purposes).
EXPIRED 101 101 EXPIRED Expired before being sent to the handset.
REJECTD 102 102 CARRIER_COMMUNICATION_ERROR Communication error with the carrier.
REJECTD 103 103 REJECTED_BY_CARRIER Carrier rejected the message.
REJECTD 201 201 NO_CREDIT The message limit set by the administrator of your business, for you account or sub account, was reached. If your business uses the prepaid charging model, it means you have used all messages you have paid for.
REJECTD 202 202 INVALID_DESTINATION_NUMBER The destination number is invalid (It is not a valid mobile phone number).
REJECTD 203 203 BLACKLISTED The destination number is blacklisted, it was manually put into the blacklist by your business.
REJECTD 204 204 DESTINATION_BLOCKED_BY_OPTOUT The destination number has opted-out of your messages. It no longer wants to receive messages from your sub account. (This status is specific for mobile marketing accounts).
REJECTD 205 205 DESTINATION_MESSAGE_LIMIT_REACHED The destination number has already received the maximum amount of messages that a single business may send in a given period of time. (This status is specific for Mobile Marketing and it is a rule set by the carriers).
REJECTD 207 207 INVALID_MESSAGE_TEXT The text of the message contains words that are not accepted by the carrier. It may contain foul language or, if your account is Mobile Marketing, you may be using names of large companies.
REJECTD 301 301 INTERNAL_ERROR There was an internal error on Wavy’s platform.
UNKNOWN 301 301 INTERNAL_ERROR There was an internal error on Wavy’s platform.

2 - Second status (delivered_status - Delivery Report Callback)

Delivery status to a device, this is the second status we return, and it only exists when the first status cited above was successful, that is, if the message was successfully send to the carrier. In this status we inform whether the message was sent to the device or not. Carriers Oi and Sercomtel do not possess this second status level, for these carriers, we can only return the information of the first status, that is, if the message was delivered to the carrier or not.

stat err TLV (0x1403) TLV (0x1404) TLV (0x1405) TLV (0x1406) Meaning
DELIVRD 000 2 SENT_SUCCESS 4 DELIVERED_SUCCESS Successfully delivered to the device.
UNDELIV 104 2 SENT_SUCCESS 104 NOT_DELIVERED The carrier accepted the message but was not able to deliver it to the device. Possible causes:
The device is turned off or out of the service area for a given period of time (normally 24h, but for some carriers, such as Vivo, the trial period if of 8 hours.)
Valid number, but inactive (some carriers return this kind of error only on this second level status).

TLS Proxy - Linux

The proxy is necessary if the connection is not made through a VPN. As previously stated, the SMPP proxy does not possess native TLS encryption, in this case we recommend the proxy below:

HAProxy

HAproxy Configuration

global
    #    local2.*                       /var/log/haproxy.log
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    ssl-server-verify       none
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

resolvers dns
    nameserver google 8.8.8.8:53
    hold valid 1s

defaults
    log                     global
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend movile
  bind *:2444
  mode tcp
  option tcplog
  use_backend movile

backend movile
    mode tcp
    server smpp-messaging.wavy.global smpp-messaging.wavy.global:2444 ssl resolvers dns check inter 15000

$ sudo yum install -y openssl-devel haproxy

$ sudo apt-get install -y openssl-devel haproxy

Important: Configure your system (SMPP client) to use 127.0.0.1:2444 as destination address

TLS Proxy - Windows

nginx configuration

worker_processes  2;

events {
    worker_connections  1024;
}

stream {
  resolver 8.8.8.8 valid=1s;
  map $remote_addr $backend {
    default smpp-messaging.wavy.global;
  }
  server {
    listen 2444;
    proxy_pass $backend:2444;
    proxy_ssl  on;
  }
}

It’s possible to use nginx as a proxy TLS on windows servers to encrypt SMPP data

Download the version below (its important to use this version because earlier versions resolve name on the first request only)

http://nginx.org/download/nginx-1.12.1.zip

Extract the .zip file on the desired place and replace the content on the file conf/nginx.conf with these example configuration.

API SFTP

Connection Details

Hostname ftp-messaging.wavy.global
Port 2222
Protocol SFTP (transfer over ssh, providing client-server encryption)
Authentication username + password (supplied by our tech support)
Portal messaging.wavy.global

Sending messages through SFTP

To send messages through SFTP, it is necessary to create a TXT file with formatting following the example below:

number;text;correlationId(optional);
5511900000000;message 1;;
5519900000000;message 2;;
5521900000000;message 3;;
EOF

The file name to be sent must have the following format:

<SUB_ACCOUNT_ID>.<DATE(YYYYMMDD)>.<SEQUENCE> or <SUB_ACCOUNT_REFERENCE_NAME>.<DATE(YYYYMMDD)>.<SEQUENCE>

The sub accounts(projects) can be created by the client himself in our portal. If naming above is not followed, the messages will be sent using the clients default sub account

Example:

3486.20170101.01.txt or PROJECT1.20170101.01.txt

After creating the file, it must be sent to our sftp server on the upload directory. The file will be moved to the success directory after its processing is done. If some error happens, the file will be moved to the error directory.

Accents and special characters

Messages that contain only the characters on the table below are charged every 160 characters. If a message contains one or more characters that are not in the table below, the charging is done every 70 characters, according to the specification of the protocol in the carrier network.

Space ( 0 8 @ H P X ` h p x
! ) 1 9 A I Q Y a i q y
* 2 : B J R Z b j r z
# + 3 ; C K S { c k s ~
$ , 4 < D L T \ d l t
% - 5 = E M U } e m u
& . 6 > F N V ^ f n v
/ 7 ? G O W _ g o w

Observations:

1 - Before using accents and special characters, you musk ask for permission with our tech support

2 - In cases where the destination carrier does not accept accents and special characters (Sercomtel), our platform does automatic character substitution for their closest not special counterparts, e.g.: á becomes a, and ç becomes c.

Large Texts (concatenation)

Even though the communication protocol used by the carriers has limits of 70 and 160 characters for messages with and without special characters respectively, it is possible to send large texts with the use of concatenation, where the messages are put together by the device when it receives them.

For clients integrated through HTTPS, SFTP or MQ, there is no additional parameter to be set in order to activate concatenation, just sending the whole large message at once is enough.

Clients integrated through SMPP must use the concatenation functionality with indicators on the header (UDH), LINK

It is important to note that even though the message will show up in the devices as a large, single message, the messages are still traveling on the carrier network individually, and in this case, we are still being charged on a per message basis, every 70 of 160 characters (depending on the caracteres used). Remember that when using concatenation some of the characters (70 or 160) are used by the header.

Observation: In cases then the carriers do not support the concatenation feature (Sercomtel), Wavy will send the messsage separately, with no concatenations and will automatically include numbering indicators on the message texts.

E.g.:

Beginning of text…. (½)

……end of text (2/2)

API Carrier Lookup

This API allows you to perform batch queries of numbers, returning the operator that these numbers belongs to and if it’s an invalid number (if a number does not belong to any operator so it is invalid). It uses the HTTP protocol with TLS, and the POST method with parameters in JSON. The query lets you know if a certain number belongs to the operator, but you can not verify if the number is active.

Authentication

To send messages and get status through the API, it is necessary to authenticate using a combination of either username or email and authentication token.

Field Details Data Type
UserName Your username or email String
AuthenticationToken Your authentication token. Get yours here String

Connection Details

Hostname api-messaging.wavy.global
APIs Batch request /v1/carrier/lookup
Port 443 (https)
Protocolo HTTPS (TLS encryption)
Authentication username + token
Portal messaging.wavy.global

HTTP POST request

curl --request POST \
  --url https://api-messaging.wavy.global/v1/carrier/lookup \
  --header 'authenticationtoken: <authenticationtoken>' \
  --header 'username: <username>' \
  --header 'Content-Type: application/json' \
  --data '{
    "destinations": ["+55(19)997712322", "5519997712322", "2312312"]
}'

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api-messaging.wavy.global/v1/carrier/lookup",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\n\t\"destinations\": [\"+55(19)997712322\", \"5519997712322\", \"2312312\"]\n}",
  CURLOPT_HTTPHEADER => array(
    "Content-Type: application/json",
    "authenticationtoken: <authenticationtoken>",
    "username: <username>"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

require 'uri'
require 'net/http'

url = URI("https://api-messaging.wavy.global/v1/carrier/lookup")

http = Net::HTTP.new(url.host, url.port)

request = Net::HTTP::Post.new(url)
request["authenticationtoken"] = '<authenticationtoken>'
request["username"] = '<username>'
request["Content-Type"] = 'application/json'
request.body = "{\n\t\"destinations\": [\"+55(19)997712322\", \"5519997712322\", \"2312312\"]\n}"

response = http.request(request)
puts response.read_body


import requests

url = "https://api-messaging.wavy.global/v1/carrier/lookup"

payload = "{\n\t\"destinations\": [\"+55(19)997712322\", \"5519997712322\", \"2312312\"]\n}"
headers = {
    'Content-Type': "application/json",
    'authenticationtoken': "<authenticationtoken>",
    'username': "<username>"
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)


POST https://api-messaging.wavy.global/v1/carrier/lookup Content-Type: application/json

To perform the query simply add in the body of the request a json with the array of numbers. The number format must contain the country code. Ex Brazil: 5519999999999

Request response

Resposta chamada em formato JSON

{
    "id": "aadb5130-7dd7-11e7-baac-a6aabe61edb5",
    "destinations": [
        {
            "destination": "5519997712322",
            "active": true,
            "carrier": {
                "name": "VIVO",
                "countryCode": "BR"
            }
        },
        {
            "destination": "5519997712322",
            "active": true,
            "carrier": {
                "name": "VIVO",
                "countryCode": "BR"
            }
        },
        {
            "destination": "2312312",
            "active": false,
            "carrier": {
                "name": "UNKNOWN"
            }
        }
    ]
}

The last number in the example is an invalid number to demonstrate how the query returns the JSON in these cases.

The batch query response will contain a JSON file with the individual information about each queried number:

Campo Detalhes Tipo
id UUID for messge reference String
destinations This field is an array with the responses of the individual batch queries, contains the id and correlationId of each query number IndividualResponse[]
destination Searched telephone number Long
active status of the operator’s number (currently only check if the number belongs to the operator, not active / in use) Boolean
carrier Operator and country to which the consulted number belongs array[]
name Carrier name String
countryCode countryCode String

WhatsApp API

This documentation provides you with information for the integration with the ChatClub platform for sending and receiving messages through Sinch’s WhatsApp Integration, as well as information for receiving status notifications (CallBack - WebHook). The ChatClub platform allows sending WhatsApp single and bulk messages. The API has REST integration, using the HTTP protocol with TLS, supporting the POST method with parameters sent in JSON format.

User authentication

In order to successfully use our API, you are required to present a valid user name - or email - and the associated authentication token. While creating the request, you have to provide the following parameters on the headers:

Field Details Data Type
UserName Name or email valid for user identification on ChatClub. String
AuthenticationToken Authentication token generated by our platform. Find it here or consult the support. here String

Connection Details

Hostname api-messaging.wavy.global
Port 443 (https)
Protocol HTTPS (TLS encryption)
Authentication username + token
Encoding UTF-8

Send Messages

Sending Text Messages

Text request example

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "messageText":"test message"
   }
}

Image request example (URL)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "image":{
         "type":"JPG",
         "url":"http://...jpg",
         "caption":"image description"
      }
   }
}

Image request example (Base64)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "image":{
         "type":"JPG",
         "data":"ZmlsZQ=="
      }
   }
}

Audio request example (URL)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "audio":{
         "type":"MP3",
         "url":"http://...mp3"
      }
   }
}

Audio request example (Base64)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "audio":{
         "type":"MP3",
         "data":"ZmlsZQ=="
      }
   }
}

Video request example (URL)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "video":{
         "type":"MP4",
         "url":"http://...mp4",
         "caption":"video description"
      }
   }
}

Video request example (Base64)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "video":{
         "type":"MP4",
         "data":"ZmlsZQ=="
      }
   }
}

Document request example (URL)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "document":{
         "type":"PDF",
         "url":"http://...pdf",
         "caption":"pdf description"
      }
   }
}

Document request example (Base64)

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "document":{
         "type":"PDF",
         "data":"ZmlsZQ=="
      }
   }
}

Location request example

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "location":{
         "geoPoint":"-22.894180,-47.047960",
         "name":"Wavy",
         "address":"Av. Cel. Silva Telles"
      }
   }
}

Contacts request example

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "contacts":[
         {
            "addresses":[
               {
                  "city":"Menlo Park",
                  "country":"United States",
                  "country_code":"us",
                  "state":"CA",
                  "street":"1 Hacker Way",
                  "type":"HOME",
                  "zip":"94025"
               },
               {
                  "city":"Menlo Park",
                  "country":"United States",
                  "country_code":"us",
                  "state":"CA",
                  "street":"200 Jefferson Dr",
                  "type":"WORK",
                  "zip":"94025"
               }
            ],
            "birthday":"2012-08-18",
            "emails":[
               {
                  "email":"test@fb.com",
                  "type":"WORK"
               },
               {
                  "email":"test@whatsapp.com",
                  "type":"WORK"
               }
            ],
            "name":{
               "first_name":"John",
               "formatted_name":"John Smith",
               "last_name":"Smith"
            },
            "org":{
               "company":"WhatsApp",
               "department":"Design",
               "title":"Manager"
            },
            "phones":[
               {
                  "phone":"+1 (940) 555-1234",
                  "type":"HOME"
               },
               {
                  "phone":"+1 (650) 555-1234",
                  "type":"WORK",
                  "wa_id":"16505551234"
               }
            ],
            "urls":[
               {
                  "url":"https://www.fb.com",
                  "type":"WORK"
               }
            ]
         }
      ]
   }
}

Allows messages to be sent through the WhatsApp platform to one or more recipients.

POST https://api-messaging.wavy.global/v1/whatsapp/send

The request body of any request must contain a JSON object with the following fields:

Base JSON:

Field Required Details Type
destinations Yes List of recipients Destination[]
message Yes Text message that will be sent to the recipient list Message
flowId No Bot flow identification String
defaultExtraInfo No Additional data that identifies the submission will be linked to all recipients who will receive the message String
campaignAlias No Campaign ID, is linked to all sending messages String

Destination:

Field Required Details Type
correlationId No Your defined id will be returned in a confirmation message (callback). This is useful in cases where you want to keep track of the sent message, since you can define different ids for different messages. String
destination Yes The phone number (country code — 55 for Brazil — and state must be present) to which the message will be sent. Examples:5519900001111, +5519900001111, +55(19) 900001111. String

Message:

Field Required Details Type
messageText Yes field used for in case you want to send a personalized message in response to a received message. text
image Yes Field used for in case you want to send an image content. Image
audio Yes Field used for in case you want to send an audio content. Audio
video Yes Field used for in case you want to send a video content. Video
document Yes Field used for in case you want to send a document file. Document
location Yes Field used for in case you want to send a location. Location
contacts Yes Field used for in case you want to send contact(s). Contact[]
previewFirstUrl No Control the app’s preview of first URL sent Boolean

Text:

Image:

Field Required Details Type
type Yes Type/extension of the image to be sent in the message. Available options: JPG, JPEG, PNG. String
caption No Text to be presented to the user under the image. String
url Yes URL where the content to be sent is hosted. String
data Yes Base64 encoded content String

Audio:

Field Required Details Type
type Yes Type/extension of the audio to be sent in the message. Available options: AAC, MP4, AMR, MP3, OGG. String
url Yes URL where the content to be sent is hosted. String
data Yes Base64 encoded content String

Video:

Field Required Details Type
type Yes Type/extension of the video to be sent in the message. Available options: MP4, 3gpp. String
caption No Text to be presented to the user under the video. String
url Yes URL where the content to be sent is hosted. String
data Yes Base64 encoded content String

Document:

Field Required Details Type
type Yes Type/extension of the document to be sent in the message. Available options: PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX String
caption No Text to be presented to the user under the document. String
url Yes URL where the content to be sent is hosted. String
data Yes Base64 encoded content String

Location:

Field Required Details Type
geopoint Yes The place’s geopoint. The format should be: “latitude,longitude” String
address No Address of the location. String
name No Name of the location. String

Contact:

Field Required Details Type
addresses No Full contact address(es). Address[]
birthday No Birthday date as YYYY-MM-DD formatted string. String
emails No Contact email address(es). Email[]
name No Full contact name. Name
org No Contact organization information. Org
phones No Contact phone number(s). Phone[]
urls No Contact URL(s). Url[]

Address:

Field Required Details Type
street No Street number and name. String
city No City name. String
state No State abbreviation. String
zip No ZIP code. String
country No Full country name. String
country_code No Two-letter country abbreviation. String
type No Standard Values: HOME, WORK. String

Email:

Field Required Details Type
email No Email address. String
type No Standard Values: HOME, WORK. String

Name:

Field Required Details Type
first_name No First name. String
last_name No Last name. String
middle_name No Middle name. String
name_suffix No Name suffix. String
name_prefix No Name prefix. String
formatted_name No Full name as it normally appears. String

Org:

Field Required Details Type
company No Name of the contact’s company. String
department No Name of the contact’s department. String
title No Contact’s business title. String

Phone:

Field Required Details Type
phone No Formatted phone number. String
type No Standard Values: CELL, MAIN, IPHONE, HOME, WORK. String
wa_id No WhatsApp ID. String

Url:

Field Required Details Type
phone No Contact URL. String
type No Standard Values: HOME, WORK. String

Sending template messages

Template Request Example

{
   "destinations":[
      {
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111"
      }
   ],
   "message":{
      "template":{
         "namespace":"aaaaaaaa_bbbb_cccc_dddd_eeeeeeeeeeee",
         "elementName":"some_approved_image_hsm",
         "header":{
            "parameters":[
               "header_parameter_1"
            ]
         },
         "bodyParameters":[
            "https://upload.wikimedia.org/wikipedia/commons/c/c3/Arquivo.jpg"
         ],
         "languagePolicy":"DETERMINISTIC",
         "languageCode":"pt_BR"
      }
   }
}

Template with Buttons Example

{
    "destinations": [
        {"destination": "5519900001111"} 
    ],
    "message": {
        "template": {
            "namespace": "whatsapp:hsm:ecommerce:movile",
            "elementName": "chatclub_test_buttons",
            "languageCode": "pt_BR",
            "languagePolicy": "DETERMINISTIC",
            "header": {
                "image": {
                    "type": "JPG",
                    "url": "https://url.to/some/file.jpg"
                }
            },
            "bodyParameters": [
                "Outter"
            ],
            "buttons": [
                {
                    "type": "QUICK_REPLY",
                    "replyPayload": "button-1-reply"
                },
                {
                    "type": "QUICK_REPLY",
                    "replyPayload": "button-2-reply"
                },
                {
                    "type": "QUICK_REPLY",
                    "replyPayload": "button-3-reply"
                }
            ]
        }
    }
}

It is also possible to send message base in previously defined templates (also called templates), with addition of placeholders (“parameters”). The request body must follow the BASE JSON format. Message object must have a single template field:

Message:

Field Required Details Type
template Yes Template message content. Template

Template:

Field Required Details Type
namespace Yes Value that identifies the template registration account in Facebook String
elementName Yes Value that identifies the template register in Facebook String
languageCode Yes One of the languages defined in the template registration String
languagePolicy Yes The languagePolicy must contain one of two values, “DETERMINISTIC”, “FALLBACK”. If not provided, the default is “DETERMINISTIC”. String
header Yes (if this template needs it) Header objects with its parameters Header
bodyParameters Yes (if this template uses variables) The sum of all body characters, considering fixed and dynamic fields is limited to 1024 characters if the registered template has only the body.
It is limited to 160 characters if you have a Header or Footer.
String[]
buttons Yes (if this template needs it) The approved buttons of the Template Button[]
Field Required Details Type
parameters Optional List of parameters which will be replaced in the header text. Note: In the case it is present, the header should not have a title nor any element. String[]
title Optional The title must be up to 60 chars String
image Yes Field used in case you want to send an image content. Image
video Yes Field used in case you want to send a video content. Video
document Yes Field used in case you want to send a document file. Document
location Yes Field used in case you want to send a location. Location

Button

Field Required Details Type
type yes The button type. Can be “URL”, “QUICK_REPLY” or “CALL”. String
url Required if the type is “URL” The url that will be called on click. String
replyPayload Required if type is “QUICK_REPLY” The payload which will be sent back when the user click in the button. String

Send Interactive Messages

ProductList Request Example

{
  "destinations": [
    {
      "correlationId": "MyCorrelationId",
      "destination": "5519900001111"
    }
  ],
  "message": {
    "interactive": {
      "messageInteractiveType": "PRODUCT_LIST",
      "header": {
        "text": "Sample text"
      },
      "body": {
        "text": "Main message text"
      },
      "footer": {
        "text": "Footer text"
      },
      "productListAction": {
        "catalogId": "catalog-id",
        "sections": [
          {
            "title": "Cakes",
            "productItems": [
              {
                "productRetailerId": "product-1-SKU"
              },
              {
                "productRetailerId": "product-2-SKU"
              }
            ]
          },
          {
            "title": "Juices",
            "productItems": [
              {
                "productRetailerId": "product-3-SKU"
              },
              {
                "productRetailerId": "product-4-SKU"
              }
            ]
          }
        ]
      },
      "alternativeText": "Simple message text"
    }
  }
}

List Request Example

{
  "destinations": [
    {
      "correlationId": "MyCorrelationId",
      "destination": "5519900001111"
    }
  ],
  "message": {
    "interactive": {
      "messageInteractiveType": "LIST",
      "header": {
        "text": "Sample text"
      },
      "body": {
        "text": "Main message text"
      },
      "footer": {
        "text": "Footer text"
      },
      "listAction": {
        "button": "button text",
        "sections": [
        {
          "rows": [
            {
              "identifier": "9ab8d65e-d389-4123-b97b-702e658cc9e4",
              "title": "August 7, 11:00",
              "description": "Saturday, August 7, 2021. 11:00AM"
            },
            {
              "identifier": "2051afef-e000-47d0-99a5-7d96c17968b2",
              "title": "August 7, 15:00",
              "description": "Saturday, August 7, 2021. 3:00PM"
            },
            {
              "identifier": "55baac93-a513-45d0-ad9e-2e2271861fc8",
              "title": "August 9, 11:00",
              "description": "Monday, August 9, 2021. 11:00AM"
            },
            {
              "identifier": "e2703f03-689c-4d1e-b0e9-4045d6687605",
              "title": "August 9, 15:00",
              "description": "Monday, August 9, 2021. 4:00PM"
            }
          ]
        }
      ]
      },
      "alternativeText": "Simple message text"
    }
  }
}

ReplyButton Request Example

{
  "destinations": [
    {
      "correlationId": "MyCorrelationId",
      "destination": "5519900001111"
    }
  ],
  "message": {
    "interactive": {
      "messageInteractiveType": "REPLY_BUTTON",
      "header": {
        "text": "Sample text",
        "image": {
          "type": "JPG",
          "url": "http://...jpg"
        },
        "video": {
          "type": "MP4",
          "url": "http://...mp4"
        },
        "document": {
          "type": "PDF",
          "url": "http://...pdf"
        },
        "location": {
          "geoPoint": "-22.894180,-47.047960",
          "name": "Wavy",
          "address": "Av. Cel. Silva Telles"
        }
      },
      "body": {
        "text": "Main message text"
      },
      "footer": {
        "text": "Footer text"
      },
      "replyButtonAction": {
        "buttons": [
        {
          "reply": {
            "title": "Display Text 1",
            "payload": "callback_payload_1"
          }
        },
        {
          "reply": {
            "title": "Display Text 2",
            "payload": "callback_payload_2"
          }
        }
       ]
      },
      "alternativeText": "Simple message text"
    }
  }
}

To send messages using interactive features, we will also follow BASE JSON format. Message object must have a single interactive field:

Message

Field Required Details Type
interactive Yes Field used to send an interactive message Interactive

Interactive

Field Required Details Type
messageInteractiveType Yes Type of the Interactive Message. Available options: PRODUCT_LIST, LIST and REPLY_BUTTON String
header Yes Header content Header
body Yes Main text Body
footer No Footer text Footer
productListAction When the interactive type is PRODUCT_LIST Contains the interactive type parameters ProductListAction
listAction When the interactive type is LIST Contains the interactive type parameters ListAction
replyButtonAction When the interactive type is REPLY_BUTTON Contains the interactive type parameters ReplyButtonAction
alternativeText No Text which will be sent in case the destination does not support Interactive Message String
Field Details Type
text Header text. Max 60 chars. Allows emojis, not markdown (always bold) String
image Complex property for image specification Image
video Complex property for video specification Video
document Complex property for document specification Document
location Complex property for location specification Location
Field Required Details Type
text Yes Cannot be an empty String. Allows Emojis & markdown.

Body: Max 1024 chars, whitespace is trimmed.
Footer: Max 60 chars.
String

ProductListAction

Field Required Details Type
catalogId Yes The catalogId configured in Business Manager String
sections Yes Array of at least one Section. Minimum of 1 and max of 10. Section[]

Section

Field Required Details Type
title Yes Displayed section text. String
productItems Yes Array of at least one Product Item. Maximum of 30 products across all sections. ProductItem[]

Product Item

Field Required Details Type
productRetailerId Yes The product id configured in Business Manager String

ListAction

Field Required Details Type
button Yes Button Content for message String
sections Yes Array of sections. There should be at least 1 section Section[]

Section

Field Required Details Type
rows Yes Array of rows. There should be at least 1 row and maximum of 10 rows across all sections Row[]

Row

Field Required Details Type
identifier Yes Unique identifier of the row String
title Yes Row title content String
description No Row description content String

ReplyButtonAction

Field Required Details Type
buttons Yes Array of one, two or three Buttons Button[]

Button

Field Required Details Type
reply Yes Button structure Reply

Reply

Field Required Details Type
title Yes Displayed button text. Max 20 chars String
payload Yes Extra information which is returned in the callback (as it already happens for Template buttons). Max 256 chars String

Common HTTP Status Code Response

Successful request response (200)

{
   "Id":"5efc3581-b8e8-11e7-9895-a6aabe61edb5",
   "destinations":[
      {
         "id":"5efc3581-b8e8-11e7-9895-a6aabe61edb5",
         "correlationId":"MyCorrelationId",
         "destination":"5519900001111."
      }
   ]
}

If successful, the response contains a list of recipients (“destinations”) with uuids generated from the application side.

Authentication error response (401)

{
  "errorCode": 401,
  "errorMessage": "Authentication Error: No user was found with this combination of username and authentication token."
}

If there is a problem in user authentication, the response shows the following error message.

Status Update Callback

Example

{
  "total": 1,
  "data": [
    {
      "id": "8995c40f-1c3a-48d0-98ee-bbc603622a91",
      "correlationId": "...",
      "destination": "5519900000000",
      "origin": "5519900000000",
      "campaignId": 100,
      "campaignAlias": "...",
      "flowId": "...",
      "extraInfo": "...",
      "sent": true,
      "sentStatusCode": 1,
      "sentStatus": "sent status",
      "sentDate": "2017-12-18T17:09:31.891Z",
      "sentAt": 1513616971891,
      "delivered": true,
      "deliveredStatusCode": 1,
      "deliveredStatus": "delivered status",
      "deliveredDate": "2017-12-18T17:09:31.891Z",
      "deliveredAt": 1513616971891,
      "read": true,
      "readDate": "2017-12-18T17:09:31.891Z",
      "readAt": 1513616971891,
      "updatedDate": "2017-12-18T17:09:31.891Z",
      "updatedAt": 1513616971891
    }
  ],
  "clientInfo": {
      "customerId": 42,
      "subAccountId": 1291,
      "userId": 1
  }
}

Each update on the status of sent messages (delivery confirmation to the end user, message reading, etc.), a callback/webhook is sent. Callbacks are sent in batch.

IMPORTANT: The endpoint in which the webhook will be sent must be previously configured with the support / operations team.

The format of this return will be according to the following description:

Field Details Type
total Number of callbacks in the call. String
data Callback list. Data[]
clientInfo Client Information ClientInfo

Data:

Field Details Type
id Last message id. String
correlationId A unique ID set by you to match with the message status (callback and DLR). This parameter is optional, and you can use the ID generated by ChatClub for this matching. String
destination Phone to which the message was sent (including country code). Example: 5511900000000. String
origin Phone that identifies the WhatsApp Account (including country code). Example: 5511900000000. String
campaignId Previously defined campaignID. String
campaignAlias Previously defined Campaign alias. String
extraInfo Extra information sent with the original message. String
sent Indicates whether the message was sent. Boolean
sentStatusCode Status code generated by the ChatClub for message indicating the sending status. Number
sentStatus Sent status description. Boolean
sentDate Date the message was sent. Format: yyyy-MM-dd’T'HH:mm:ssZ. String
sentAt Time when the message was sent, using Unix_time format Number
delivered Indicates whether the message was delivered to the destination. Boolean
deliveredStatusCode Status code generated by the ChatClub for message indicating the message was delivered. Number
deliveredStatus Delivery status description. String
deliveredDate Date the message was delivered. Format:: yyyy-MM-dd’T'HH:mm:ssZ String
deliveredAt Time when the message was delivered, using Unix_time format Number
read Indicates whether the message was read by the destination. Boolean
readDate Date the message was read. Format: yyyy-MM-dd’T'HH:mm:ssZ String
readAt Time when the message was read, using Unix_time format String
updatedDate Date the message status was updated. Format: yyyy-MM-dd’T'HH:mm:ssZ String
updatedAt Date when the message status was updated, using Unix_time format String

ClientInfo

Field Details Type
customerId Client identification. Number
subAccountId Subaccount identification. Number
userId User identification. Number

Status

Status that can be sent in the callback:

Status Sent code Delivered code Meaning
CARRIER_COMMUNICATION_ERROR 102 Error uploading media to WhatsApp.
REJECTED_BY_CARRIER 103 Database error occurred.
SENT_SUCCESS 2
EXPIRED 2 101 Message expired.
Failed to send message because it was too old.
NOT_DELIVERED 2 104 Rate limiting engaged - too many message sends attempted.
Failed to send message because this user’s phone number is part of an experiment.
Structure unavailable: Client could not display highly structured message. ‘
Failed to send message because you are outside the support window for freeform messages to this user. Please use a valid Template notification or reconsider.
Media upload error (Unknown Error).
Failed to send message because your account is ineligible. Please check your WhatsApp Business Account.
Temporary upload failure. Try again later.
DELIVERED_SUCCESS 2 4
READ_SUCCESS 2 5
INVALID_DESTINATION_NUMBER 202 Invalid WhatsApp Contact.
DESTINATION_BLOCKED_BY_OPTOUT 204 Destination Blocked by OptOut.
INVALID_MESSAGE_LENGTH 206 Message too long.
INVALID_MESSAGE_TEXT 207 Parameter value is not valid.
INVALID_CONTENT 209 Invalid message type UNKNOWN.
INVALID_SESSION 210 Session is not open and no fallback Template is set.
DESTINATION_BLOCKED_BY_OPTIN 211
DESTINATION_BLOCKED_BY_WHITELIST 212
INTERNAL_ERROR 311 Could not check contacts from WhatsApp API.

MO (messages sent by the end user to the Whatsapp Account)

Text Message example:

{
  "total": 1,
  "data": [
    {
      "id": "ce425ffe-bc62-421f-9261-e6819a5eab43",
      "source": "5519900000000",
      "origin": "5519900000000",
      "userProfile": {
        "name": "name of the user"
      },
      "campaignId": 100,
      "correlationId": "...",
      "campaignAlias": "...",
      "flowId": "....",
      "extraInfo": "...",
      "message": {
        "type": "TEXT",
        "messageText": "Hi, this is a message from the user"
      },
      "receivedAt": 1513616971473,
      "receivedDate": "2017-12-18T17:09:31.473Z"
    }
  ]
}

Extra Info example:

{  
   "segmentation_list":[  
      {  
         "id":26,
         "customerId":42,
         "subAccountId":0,
         "name":"Wavy WhatsApp Segmentation List",
         "active":true
      },
      {  
         "id":27,
         "customerId":43,
         "subAccountId":0,
         "name":"Wavy WhatsApp Segmentation List 2",
         "active":true
      }
   ]
}

Media Message example

{
  "total": 1,
  "data": [
    {
      "id": "ce425ffe-bc62-421f-9261-e6819a5eab43",
      "source": "5519900000000",
      "origin": "5519900000000",      
      "userProfile": {
        "name": "name of the user"
      },
      "campaignId": 100,
      "correlationId":"...",
      "campaignAlias":"...",
      "flowId": "....",
      "extraInfo": "...",
      "message": {
            "type": "IMAGE",
           "mediaUrl": "https://...",
           "mimeType": "image/jpg",
           "caption": "..."
      },
      "receivedAt": 1513616971473,
      "receivedDate": "2017-12-18T17:09:31.473Z"
    }
  ]
}

Location message example:

{
  "total": 1,
  "data": [
    {
      "id": "ce425ffe-bc62-421f-9261-e6819a5eab43",
      "source": "5519900000000",
      "origin": "5519900000000",      
      "userProfile": {
        "name": "name of the user"
      },
      "campaignId": 100,
      "correlationId": "...",
      "campaignAlias": "...",
      "flowId": "....",
      "extraInfo": "...",
      "message": {
           "location": {
               "geoPoint": "-22.894180,-47.047960",
               "name": "Wavy",
               "address": "Av. Cel. Silva Telles"
           }
      },
      "receivedAt": 1513616971473,
      "receivedDate": "2017-12-18T17:09:31.473Z"
    }
  ]
}

Contacts message example:

{
  "total": 1,
  "data": [
    {
      "id": "ce425ffe-bc62-421f-9261-e6819a5eab43",
      "source": "5519900000000",
      "origin": "5519900000000",      
      "userProfile": {
        "name": "name of the user"
      },
      "campaignId": 100,
      "correlationId": "...",
      "campaignAlias": "...",
      "flowId": "....",
      "extraInfo": "...",
      "message": {
           "contacts":[  
                 {  
                    "addresses":[  
                       {  
                          "city":"Menlo Park",
                          "country":"United States",
                          "country_code":"us",
                          "state":"CA",
                          "street":"1 Hacker Way",
                          "type":"HOME",
                          "zip":"94025"
                       },
                       {  
                          "city":"Menlo Park",
                          "country":"United States",
                          "country_code":"us",
                          "state":"CA",
                          "street":"200 Jefferson Dr",
                          "type":"WORK",
                          "zip":"94025"
                       }
                    ],
                    "birthday":"2012-08-18",
                    "emails":[  
                       {  
                          "email":"test@fb.com",
                          "type":"WORK"
                       },
                       {  
                          "email":"test@whatsapp.com",
                          "type":"WORK"
                       }
                    ],
                    "name":{  
                       "first_name":"John",
                       "formatted_name":"John Smith",
                       "last_name":"Smith"
                    },
                    "org":{  
                       "company":"WhatsApp",
                       "department":"Design",
                       "title":"Manager"
                    },
                    "phones":[  
                       {  
                          "phone":"+1 (940) 555-1234",
                          "type":"HOME"
                       },
                       {  
                          "phone":"+1 (650) 555-1234",
                          "type":"WORK",
                          "wa_id":"16505551234"
                       }
                    ],
                    "urls":[  
                       {  
                          "url":"https://www.fb.com",
                          "type":"WORK"
                       }
                    ]
                 }
              ]
      },
      "receivedAt": 1513616971473,
      "receivedDate": "2017-12-18T17:09:31.473Z"
    }
  ]
}

At each end-user response (MO or Mobile Originated) a callback/webhook is sent. These MOs are sent in batch.

IMPORTANT: The endpoint in which the webhook will be sent must be previously configured with the support / operations team.

The format of this return will be according to the following description:

Callback

Field Details Type
total Number of callbacks in the request Long
data List of Mobile Originated messages Data[]
clientInfo Information of who the message is for ClientInfo

Data

Field Details Type
id Last message identification String
source ID of the sender String
origin Phone that identifies the WhatsApp Account (including country code). Example: 5511900000000 String
userProfile Profile of the user who sent the message UserProfile
correlationId A unique ID set by you to match with the message status (callback and DLR). Optional as you can use the ID generated by Wavy String
campaignId Previously defined campaign ID String
campaignAlias Previously defined campaign alias String
message MO message Message
receivedDate Date when the message was received.
Format: yyyy-MM-dd’T'HH:mm:ssZ
String
receivedAt Date when the message was received, using Unix_time format Long
extraInfo Extra information related to the message. Format: Json String
session Session information Session

MO Flow Control - Segmentation Lists

The message will have a list of segmentation lists in the extraInfo field. Our partners use it to redirect the messages through certain flows. The key’s name is segmentation_lists, and it contains a list of SegmentationList.

Field Details Type
id Segmentation list identifier Integer
customerId Customer identifier Integer
subAccountId SubAccount identifier Integer
name Segmentation list name String
active Segmentation list status Boolean

UserProfile

Field Details Type
name User’s name specified in WhatsApp String
whatsAppId User’s phone number String

Session

Field Details Type
sessionId Session’s Id for this user String
createdAt Session’s creation timestamp Long

Message

Field Details Type
type Type of message sent by the end user: TEXT - IMAGE - AUDIO - VIDEO - DOCUMENT - STICKER - BUTTON - ORDER - LIST String
messageText The text message (MO) sent by the end user. For list replies, it is equal to the rowTitle. String
mediaUrl Url to download the media sent by the end user. String
mimeType Mime type of the file sent by the end user. String
caption Media label sent by end user. String
location Location sent by end user. Location
contacts Contact(s) sent by end user. Contact[]
receivedInteractive The received interactive fields. ReceivedInteractive

ReceivedInteractive

Field Details Type
order The order object with the products information (PRODUCT_LIST) Order
listReply Reply for list sent by the user. (LIST) ListReply
payload Text defined when sending buttons (REPLY_BUTTON) String

Order

Field Details Type
catalogId The catalogId configured in Business Manager String
productItems Array of ProductItem. ProductItem[]

Product Item

Field Details Type
productRetailerId Unique identifier (in the catalog) of the product String
quantity Number of items purchased String
itemPrice Unitary price of the items String
currency Currency of the price String

ListReply

Field Details Type
rowIdentifier Row identifier sending on original message to user String
rowTitle Row title sending on original message to user String

ClientInfo

Field Details Type
customerId CustomerId which the message is for Long
subAccountId SubAccountId which the message is for Long
userId UserId which the message is for Long

API SFTP WhatsApp

Detalhes de conexão

Hostname ftp-messaging.wavy.global
Port 2222
Protocol SFTP (transfer over ssh, providing client-server encryption)
Authentication username + password (supplied by our tech support)

Sending messages through SFTP

Template messages through SFTP

Media Template:

2020-01-21;16:00;16:00;TEMPLATE;chatclub_welcome;whatsapp:hsm:ecommerce:movile;pt_BR;DETERMINISTIC;name|company IMAGE;URL;https://upload.wikimedia.org/wikipedia/en/d/d2/Imagem_logo.png;PNG
phone;name;company
5519981560597;Name1;Wavy

1st Line
Send Date (for scheduling cases)
Initial sending time (for scheduling cases)
Final sending time (for scheduling cases)
Message type should be: TEMPLATE
Name (elementName) of Template
Namespace (namespace) of Template
Language (languageCode) of Template
Deterministic or Fallback of the language of Template (languagePolicy)
Name of Template parameters

Observations for the first line:

1 - The Template parameters name must be in the file columns or will be considered as constant values

2 - The information that won’t be used can be blank, but you must keep the semicolon as separation. For instance, a case that we don’t use the scheduling (initial fields are between semicolons and no information inside): ; ; ; TEMPLATE;chatclub_welcome;whatsapp:hsm:ecommerce:movile;pt_BR;DETERMINISTIC;name|company

3 - By default the languagePolicy will be Deterministic.

4 - The Template parameters name should be split by “ | ” and not by “ ; ”

2nd Line Examples
Header type supported by the Template IMAGE, AUDIO, VIDEO or DOCUMENT
Media source type URL or PATH (media directory from the FTP server)
Media Url or FTP server directory
Media type JPEG, PNG, JPG, PDF, DOC, MP4, MP3

Second line observation:

1 - The media type must be a type acceptable by WhatsApp.

Media Supported Content-Types
document Any valid MIME-type
image image/jpeg, image/png
audio audio/aac, audio/mp4, audio/amr, audio/mpeg, audio/ogg; codecs=opus
video video/mp4, video/3gpp. Note: Only H.264 video codec and AAC audio codec is supported.
3rd Lines
Column names
4th and further lines:
Recipient and parameter values of Template

Customized Templates for each recipient:

For customized send, as well as different medias for each recipient, contact our technical support team to configure and give more details about this feature.

Consulting open sessions via API

Request

To consult open sessions via our API, you need to do GET request to the following address:

GET http://api-messaging.wavy.global/v1/session?customerId={customerId}&subAccountId={subAccountId}

Passing the parameter customerId is mandatory, while subAccountId is optional.

Attention: Be careful to replace ’{‘ and ’}‘ too. For example, “={customerId}” becomes “=42”.

You will also need to use the following headers:

Header Value
Content-Type application/json
authenticationToken Messaging1 authentication token
userName Messaging1 username

Response

On success, if there are open sessions for the specified customerId and subAccountId, the request will return a JSON with the attribute:

Field Value
file_url Link to download a file of type csv containing the fields “source” and “session_created_at” of all the found destinations

If there is no data associated with customerId and subAccountId, the returned file is empty, with only the header.

Response example:

{
    "file_url": "https://chatclub-cdn.wavy.global/2019/02/13/633e33fc-3a3f-4ca5-a8b0-4b747fb67137/5bd46e2b-5990-4681-9b29-98ab6598960e"
}

Webhook

How does the webhook work?

When we do a dispatch from our platform, we will receive some information back. This information can be shared with our clients and redirected to other attendance channels to take further actions.

For example, we can do a Template dispatch from our platform and, in case our client responds with a MO, we can send the information to an attendance webhook, which will start a human conversation between the attendant and the user.

How to configure my webhook?

Currently, to configure your webhook, you need to just open a ticket through our portal to our Customer Service team: service.center.wavy.global, which will help with the configuration.

Technical Information

It is important this webhook have an HTTPS connection, because this connection is the most secure way of transferring data in the internet.

WhatsApp Lists via API

Technical Documentation: WhatsApp Lists via API

Consulting lists via API

OPT IN/OUT and BLACK/WHITE LIST


API - Possible list request types:



Request

It is required to make a GET request to the URL http://api-messaging.wavy.global/v1/list/{listType}?customerId={customerId}&subAccountId={subAccountId}.


List Type Value passed in List Type
Whatsapp Opt Out List OPTOUT
Whatsapp Opt In List OPTIN
Whatsapp Blacklist BLACKLIST
Whatsapp Whitelist (MT) WHITELIST

The parameter customerId is required, while subAccountId is optional. It is also required to pass the following headers:

Header Key Header Value
Content-Type application/json
authenticationToken Token do Messaging1
userName Nome de usuário do Messaging1

Response:

In case of success, if there is data related to the customerId and the subAccountId (if specified), a request will have as response a JSON with 3 attributes:

Attribute Name Attribute Value
success true
status 200
data Link to download the file of type csv containing the fields “source” and “createdAt” from all the found destinations

In case there are no related data, it will only be returned a similar JSON, but without the field data, which means that there were not problems with the request, but there was no data related with the request parameters passed.

WhatsApp Opt Out

Introduction

The Opt Out is a way of allowing ours users to inform that they want to leave the conversation. If they inform that, we prevent them from receiving messages from the business.

Opt Out Mechanism

Currently, our Opt Out respects the following rules:


Campaigns API

This document provides the information needed to integrate with the ChatClub platform to perform campaign management. The API has REST integration, using HTTP protocol with TLS, supporting the POST methods with the parameters sent in JSON format.

Authentication

To successfully use our API, you must provide a valid username (email) associated with an authentication token. You must add the following headers to the request:

Field Details Data Type
userName Valid e-mail subscribed in ChatClub Platform String
authenticationToken Authentication token generated by our platform. Find it here or check our support. String

Campaign Connection details

Hostname apigw.wavy.global
Port 443 (https)
Protocol HTTPS (TLS encryption)
Authorization username + token
Encoding UTF-8

Listing campaigns

Listing campaigns example

curl -X GET \
 'https://apigw.wavy.global/api/v1/campaigns?name=MyCampaign&page=1&page_size=10' \
 -H 'Content-Type: application/json' \
 -H 'authenticationToken: <authentication_token>' \
 -H 'userName: <e-mail>'

Response

HEADERS:
page-number: 1
per-page: 10
total: 2
total-pages: 1
{
    "status": {
        "error": false
    },
    "campaigns": [
        {
            "name": "My first campaign",
            "id": 1,
            "alias": "first"
        },
        {
            "name": "My second campaign",
            "id": 2,
            "alias": "second"
        }
    ]
}

List of campaigns already registered in the platform. You can page results or filter by campaign name. GET https://apigw.wavy.global/api/v1/campaigns

QueryString parameters

* Requeried fields

Field Details Data type
name Campaign’s name to be used as a filter String
page Requested page to be listed Integer
page_size Records per page Integer

Requesting for a specific campaign

Requesting specific campaign example

curl -X GET \
  https://apigw.wavy.global/api/v1/campaigns/1234 \
  -H 'Content-Type: application/json' \
  -H 'authenticationToken: <authentication_token>' \
  -H 'userName: <e-mail>'

Response

{
    "status": {
        "error": false
    },
    "campaign": {
        "name": "My Campaign",
        "id": 1234,
        "alias": "mycampaign"
    }
}

Requesting a specific campaign by id

GET https://apigw.wavy.global/api/v1/campaign/{id}

Creating campaigns

Creating campaign example:

curl -X POST \
  https://apigw.wavy.global/api/v1/campaigns \
  -H 'Content-Type: application/json' \
  -H 'authenticationToken: <authentication_token>' \
  -H 'userName: <e-mail>' \
  -d '{
        "campaign" : {
          "name": "My Campaign",
          "alias": "mycampaign"
        }
      }'

Response

{
    "status": {
        "error": false
    },
    "campaign": {
        "name": "My Campaign",
        "id": 1234,
        "alias": "mycampaign"
    }
}

Create a new campaign with name and alias. The campaign alias should be a simple name to make it easier to use with the API. It is recommended to be short and do not use special characters.

POST https://apigw.wavy.global/api/v1/campaigns

JSON Object

* Required fields

Field Details Data type
name* Campaign name String
alias Campaign identifier. To be used when send messages. String

Changing campaigns

Changing campaign example:

curl -X PUT \
  https://apigw.wavy.global/api/v1/campaigns/1234 \
  -H 'Content-Type: application/json' \
  -H 'authenticationToken: <authentication_token>' \
  -H 'userName: <e-mail>' \
  -d '{
        "campaign" : {
          "name": "My Campaign",
          "alias": "mycampaign"
        }
      }'

Response

{
    "status": {
        "error": false
    },
    "campaign": {
        "name": "My Campaign",
        "id": 1234,
        "alias": "mycampaign"
    }
}

Change a campaign by modifying the name and / or alias.

PUT https://apigw.wavy.global/api/v1/campaigns/{id}

JSON Object

* Required fields

Field Details Data type
name* Campaign name String
alias Campaign identifier. To be used when send messages. String

Deleting campaigns

Deleting campaign example:

curl -X DELETE \
  https://apigw.wavy.global/api/v1/campaigns/1234 \
  -H 'Content-Type: application/json' \
  -H 'authenticationToken: <authentication_token>' \
  -H 'userName: <e-mail>'

Response

{
    "status": {
        "error": false
    },
    "campaign": {
        "name": "My Campaign",
        "id": 1234,
        "alias": "mycampaign"
    }
}

Deleting a campaign by id

DELETE https://apigw.wavy.global/api/v1/campaigns/{id}

Support

Tickets You can open a support request through our Service Center