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 |
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.
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:
- Webhook - Receive the statuses in a webservice of your company (recommended)
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.
- API status requests - Make api requests using our sms-status endpoints
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 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)
Code | Name | Short Description | Detailed Description |
---|---|---|---|
1 | ROUTED_SUCCESS | Routed | Intermediate internal routing status. Messages are not persisted with this status, so we have no messages in reports with this status |
2 | SENT_SUCCESS | Sent | Message successfully sent to carrier or WhatsApp container. |
3 | CARRIER_ACCEPTED_SUCCESS | Carrier Accepted | Intermediate routing status on carrier. Messages are not persisted with this status, so we have no messages in reports with this status |
4 | DELIVERED_SUCCESS | Delivered | Message successfully delivered from carrier or WhatsApp container to recipient’s device. |
101 | EXPIRED | Expired | For SMS is the status for messages that expired before being sent to the carrier. For WhatsApp it is the TTL, it is the time that the message is waiting in the container/whatsapp to be delivered to the device. |
102 | CARRIER_COMMUNICATION_ERROR | Carrier communication error | Status indicating that we were having problems establishing communication with the operator or with the WhatsApp container and the message could not be sent. |
103 | REJECTED_BY_CARRIER | Rejected by carrier | Status indicating that the carrier or WhatsApp container rejected the message. It can be due to several reasons, such as a full queue at the operator, an invalid number for the operator, a WhatsApp template without the language or missing parameters. Or any other internal carrier or container error |
104 | NOT_DELIVERED | Message not delivered | Message successfully sent to carrier or WhatsApp container, but not delivered to user’s device. It could be because the user’s device is out of range; the number has been deactivated or blocked; for whatsapp it could be because the content (media) cannot be sent to the user or because the recipient cannot receive the message due to limits or spam. |
201 | NO_CREDIT | No credit | Credit check is done at time of shipping request. So we don’t have this status on persisted messages. I believe this status is only used in B2C for shortcodes that are billed, so the message can be declined if the user doesn’t have credit. |
202 | INVALID_DESTINATION_NUMBER | Invalid destination number | Recipient number is invalid and the message will not be sent to carrier or WhatsApp container |
203 | BLACKLISTED | Destination in blocklist | The customer has added the number to the blocklist and the message will not be sent to the carrier or WhatsApp container |
204 | DESTINATION_BLOCKED_BY_OPTOUT | Destination in optOut | The user sent the “exit” command and was added to the opt-out list. The message will not be sent. |
206 | INVALID_MESSAGE_LENGTH | Exceeded text size limit | It is no longer used. Limit that existed for SMS from Mobile Marketing. |
207 | INVALID_MESSAGE_TEXT | Message text is invalid | Message text contains forbidden words. |
209 | INVALID_CONTENT | Invalid message content | Indicates that some message parameter is invalid or missing. |
213 | COUNTRY_NOT_ALLOWED_FOR_CUSTOMER | Destination country not allowed for the customer | Status indicating that the customer is not allowed to ship to the recipient’s country. In practice, we don’t have any customers with this restriction, so we don’t have this status in the messages. We don’t have this status for WhatsApp. |
214 | INVALID_CUSTOMER_CONFIGURATION | Invalid client configuration | Status indicating that the customer settings could not be found, probably because the customer/sub_account has been disabled. |
215 | CUSTOMER_QUOTA_BLOCKED | Client blocked by quota limit | Status that indicates that the client has reached his quota (monthly/daily) for sending messages and therefore the message will not be sent. |
216 | MESSAGE_BLOCKED_BY_WARM_UP | Message blocked by WarmUp feature | Status for WhatsApp clients that are performing container warm-up. The message stays in this status when the container has already reached the allowed limit of messages for the current tier. |
301 | INTERNAL_ERROR | Internal error | Status indicating that there was some internal error on our platforms and the message could not be processed and sent. |
401 | MESSAGE_SPLIT | Message split | In our databases, we store the customer’s original message and the parts in case the SMS exceeds the size of 160 characters without accents or 70 characters with accents. The original message has the message_split status and the parts have the actual status of being sent to the carrier. But at the time of generating the reports, only the parts are computed and the original is discarded, so we don’t have this status in the reports. |
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:
SMPP over TLS + IP whitelist (Recommended)
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)
Code | Name | Short Description | Detailed Description |
---|---|---|---|
1 | ROUTED_SUCCESS | Routed | Intermediate internal routing status. Messages are not persisted with this status, so we have no messages in reports with this status |
2 | SENT_SUCCESS | Sent | Message successfully sent to carrier or WhatsApp container. |
3 | CARRIER_ACCEPTED_SUCCESS | Carrier Accepted | Intermediate routing status on carrier. Messages are not persisted with this status, so we have no messages in reports with this status |
4 | DELIVERED_SUCCESS | Delivered | Message successfully delivered from carrier or WhatsApp container to recipient’s device. |
101 | EXPIRED | Expired | For SMS is the status for messages that expired before being sent to the carrier. For WhatsApp it is the TTL, it is the time that the message is waiting in the container/whatsapp to be delivered to the device. |
102 | CARRIER_COMMUNICATION_ERROR | Carrier communication error | Status indicating that we were having problems establishing communication with the operator or with the WhatsApp container and the message could not be sent. |
103 | REJECTED_BY_CARRIER | Rejected by carrier | Status indicating that the carrier or WhatsApp container rejected the message. It can be due to several reasons, such as a full queue at the operator, an invalid number for the operator, a WhatsApp template without the language or missing parameters. Or any other internal carrier or container error |
104 | NOT_DELIVERED | Message not delivered | Message successfully sent to carrier or WhatsApp container, but not delivered to user’s device. It could be because the user’s device is out of range; the number has been deactivated or blocked; for whatsapp it could be because the content (media) cannot be sent to the user or because the recipient cannot receive the message due to limits or spam. |
201 | NO_CREDIT | No credit | Credit check is done at time of shipping request. So we don’t have this status on persisted messages. I believe this status is only used in B2C for shortcodes that are billed, so the message can be declined if the user doesn’t have credit. |
202 | INVALID_DESTINATION_NUMBER | Invalid destination number | Recipient number is invalid and the message will not be sent to carrier or WhatsApp container |
203 | BLACKLISTED | Destination in blocklist | The customer has added the number to the blocklist and the message will not be sent to the carrier or WhatsApp container |
204 | DESTINATION_BLOCKED_BY_OPTOUT | Destination in optOut | The user sent the “exit” command and was added to the opt-out list. The message will not be sent. |
206 | INVALID_MESSAGE_LENGTH | Exceeded text size limit | It is no longer used. Limit that existed for SMS from Mobile Marketing. |
207 | INVALID_MESSAGE_TEXT | Message text is invalid | Message text contains forbidden words. |
209 | INVALID_CONTENT | Invalid message content | Indicates that some message parameter is invalid or missing. |
213 | COUNTRY_NOT_ALLOWED_FOR_CUSTOMER | Destination country not allowed for the customer | Status indicating that the customer is not allowed to ship to the recipient’s country. In practice, we don’t have any customers with this restriction, so we don’t have this status in the messages. We don’t have this status for WhatsApp. |
214 | INVALID_CUSTOMER_CONFIGURATION | Invalid client configuration | Status indicating that the customer settings could not be found, probably because the customer/sub_account has been disabled. |
215 | CUSTOMER_QUOTA_BLOCKED | Client blocked by quota limit | Status that indicates that the client has reached his quota (monthly/daily) for sending messages and therefore the message will not be sent. |
216 | MESSAGE_BLOCKED_BY_WARM_UP | Message blocked by WarmUp feature | Status for WhatsApp clients that are performing container warm-up. The message stays in this status when the container has already reached the allowed limit of messages for the current tier. |
301 | INTERNAL_ERROR | Internal error | Status indicating that there was some internal error on our platforms and the message could not be processed and sent. |
401 | MESSAGE_SPLIT | Message split | In our databases, we store the customer’s original message and the parts in case the SMS exceeds the size of 160 characters without accents or 70 characters with accents. The original message has the message_split status and the parts have the actual status of being sent to the carrier. But at the time of generating the reports, only the parts are computed and the original is discarded, so we don’t have this status in the reports. |
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
- haproxy server installation (red-hat / centos):
$ sudo yum install -y openssl-devel haproxy
- haproxy server installation (debian / ubuntu)
$ sudo apt-get install -y openssl-devel haproxy
- After the installation, exchange all content of the file /etc/haproxy/haproxy.cfg for the content besides.
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":"https://...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":"https://...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":"https://...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":"https://...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 |
---|---|---|---|
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[] |
Header:
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
Multi Product List Message 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"
}
}
}
Single Product Message Request Example
{
"destinations": [
{
"correlationId": "MyCorrelationId",
"destination": "5519900001111"
}
],
"message": {
"interactive": {
"messageInteractiveType": "PRODUCT_LIST",
"body": {
"text": "Main message text"
},
"footer": {
"text": "Footer text"
},
"productListAction": {
"catalogId": "catalog-id",
"productRetailerId": "product-sku"
},
"alternativeText": "Simple message text"
}
}
}
List Message 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": [
{
"title": "Section One",
"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 Message Request Example
{
"destinations": [
{
"correlationId": "MyCorrelationId",
"destination": "5519900001111"
}
],
"message": {
"interactive": {
"messageInteractiveType": "REPLY_BUTTON",
"header": {
"text": "Sample text",
"image": {
"type": "JPG",
"url": "https://...jpg"
},
"video": {
"type": "MP4",
"url": "https://...mp4"
},
"document": {
"type": "PDF",
"url": "https://...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 | Required for Multi Product Messages. Denied for Single Product Messages. Optional for other types. | Header content | Header |
body | Yes, except for Single Product Messages | 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 |
Header
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 |
Body/Footer
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 (For Single Product Messages)
Field | Required | Details | Type |
---|---|---|---|
catalogId | Yes | The catalogId configured in Business Manager | String |
productRetailerId | Yes | The product id configured in Business Manager | String |
ProductListAction (For Multi Product Messages)
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 |
---|---|---|---|
title | Yes | Section title that will be displayed for the user. Max 24 chars. It’s only required if you have more than one section | String |
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,
"type": "MESSAGE",
"conversation": {
"id": "conversationId123",
"origin": {
"type": "REFERRAL_CONVERSION"
},
"expiration": "2017-12-19T17:09:31.891Z"
}
}
],
"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 |
type | The type of entity this status object is about. Currently, the only available option is “message”. | String |
conversation | The conversation object, that contains in itself id, origin.type and expiration. This object related to the new billable model of whatsapp messages. See Whatsapp Conversation. | Conversation |
ClientInfo Op
Field | Details | Type |
---|---|---|
customerId | Client identification. | Number |
subAccountId | Subaccount identification. | Number |
userId | User identification. | Number |
Status
Status that can be sent in the callback:
Code | Name | Short Description | Detailed Description |
---|---|---|---|
1 | ROUTED_SUCCESS | Routed | Intermediate internal routing status. Messages are not persisted with this status, so we have no messages in reports with this status |
2 | SENT_SUCCESS | Sent | Message successfully sent to carrier or WhatsApp container. |
3 | CARRIER_ACCEPTED_SUCCESS | Carrier Accepted | Intermediate routing status on carrier. Messages are not persisted with this status, so we have no messages in reports with this status |
4 | DELIVERED_SUCCESS | Delivered | Message successfully delivered from carrier or WhatsApp container to recipient’s device. |
5 | READ_SUCCESS | Message read | Message opened and displayed to the user in the WhatsApp App. We don’t have this status in SMS. |
101 | EXPIRED | Expired | Message TTL expired. |
102 | CARRIER_COMMUNICATION_ERROR | Carrier communication error | Status indicating that we were having problems establishing communication with the operator or with the WhatsApp container and the message could not be sent. |
103 | REJECTED_BY_CARRIER | Rejected by carrier | Status indicating that the carrier or WhatsApp container rejected the message. It can be due to several reasons, such as a full queue at the operator, an invalid number for the operator, a WhatsApp template without the language or missing parameters. Or any other internal carrier or container error |
104 | NOT_DELIVERED | Message not delivered | Message successfully sent to carrier or WhatsApp container, but not delivered to user’s device. It could be because the user’s device is out of range; the number has been deactivated or blocked; for whatsapp it could be because the content (media) cannot be sent to the user or because the recipient cannot receive the message due to limits or spam. |
105 | WA_MO_MEDIA_UNRETRYABLE_EXCEPTION | Retryable media error | Status for WhatsApp MO that contains media. This status indicates that a media cannot be downloaded from the container and there is no need to retry. |
106 | WA_MO_MEDIA_RETRYABLE_EXCEPTION | Not retryable media error | Status for WhatsApp MO that contains media. This status indicates that a media cannot be downloaded from the container, but it is possible to retry. |
107 | WA_MO_MEDIA_UNKNOWN_EXCEPTION | Media message unknown error | Status for WhatsApp MO that contains media. This status indicates that a media cannot be downloaded from the container and the error is unknown. |
108 | WA_MO_MEDIA_MESSAGE_WITHOUT_FILE_ID_EXCEPTION | Media message without content | Media cannot be properly processed when sent to Felix, due to its empty content. |
109 | WA_MT_UNKNOWN_EXCEPTION | Unknown error (MT) | MT Error Status, indicates that an error occurred not related to the message content itself, such as connection timeout, connection interrupted, internal error or error with ssl authentication. |
110 | WA_DATABASE_ERROR | Error with WhatsApp container’s database | Indicates that an error occurred with the container database (WhatsApp) |
111 | WA_MT_BLOCKED_BY_SPAM_RATE_LIMIT | Blocked for exceeding the amount of shipments (MT) | Blocking when many identical messages are sent more than once to a certain user, then the container is blocked and the messages are not sent. |
112 | WA_MT_DESTINATION_INCAPABLE | Recipient unable to receive messages (MT) | Recipient of the message does not have a more up-to-date version of WhatsApp or, for some other reason, cannot receive the sent message |
201 | NO_CREDIT | No credit | Credit check is done at time of shipping request. So we don’t have this status on persisted messages. I believe this status is only used in B2C for shortcodes that are billed, so the message can be declined if the user doesn’t have credit. |
202 | INVALID_DESTINATION_NUMBER | Invalid destination number | Recipient number is invalid and the message will not be sent to carrier or WhatsApp container |
203 | BLACKLISTED | Destination in blocklist | The customer has added the number to the blocklist and the message will not be sent to the carrier or WhatsApp container |
204 | DESTINATION_BLOCKED_BY_OPTOUT | Destination in optOut | The user sent the “exit” command and was added to the opt-out list. The message will not be sent. |
205 | DESTINATION_MESSAGE_LIMIT_REACHED | Message limit reached | Indicates that the container is overloaded and cannot receive any more messages. |
207 | INVALID_MESSAGE_TEXT | Message text is invalid | Template submissions that are not enabled in the customer’s account. Or even invalid parameters for the message. We have no forbidden words for WhatsApp. |
209 | INVALID_CONTENT | Invalid message content | Indicates that some message parameter is invalid or missing. |
210 | INVALID_SESSION | Invalid session | Indicates that an attempt was made to send a text or media without the session having been opened by an MO. Only Templates are allowed with the session closed. |
211 | DESTINATION_BLOCKED_BY_OPT_IN | Destination blocked by optIn | The number is not on the opt-in list and therefore the message will not be sent. |
212 | DESTINATION_BLOCKED_BY_WHITELIST | Destination blocked by allowlist | The number is not on the list of allowed numbers and therefore the message will not be sent. |
215 | CUSTOMER_QUOTA_BLOCKED | Client blocked by quota limit | Status that indicates that the client has reached his quota (monthly/daily) for sending messages and therefore the message will not be sent. |
216 | MESSAGE_BLOCKED_BY_WARM_UP | Message blocked by WarmUp feature | Status for WhatsApp clients that are performing container warm-up. The message stays in this status when the container has already reached the allowed limit of messages for the current tier. |
217 | WA_MT_MEDIA_EXCEPTION | Error in media content (MT) | MT status for media messages, where due to an error in the template, the size of the media or the template exceeded the supported limit, the media format was not supported or the media could not be found and was considered invalid. |
218 | WA_NO_PRODUCTS_FOUND | Product not found | The request tried to search for a product that is not registered in the system. If it’s a Product List Message, it means that the catalog or the product does not exist in the Business Manager. |
219 | INVALID_PARAMETER_OR_CONTACT | Invalid parameter or contact/destination | Indicates that some message parameter is invalid or missing, or that the contact/recipient is invalid/does not have WhatsApp. |
301 | INTERNAL_ERROR | Internal error | Status indicating that there was some internal error on our platforms and the message could not be processed and sent. |
302 | WA_MO_UNKWNOWN_EXCEPTION | Unknown error (MO) | Status for WhatsApp MO. This status indicates that an unknown error occurred while processing the MO. |
303 | WA_BUSINESS_PAYMENT_ISSUE | Business payment issue | Status indicates that a problem occurred during the payment of the transaction, which can be caused by both internal and external errors. The message will not be sent to the user. |
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"
}
]
}
Text message with referral exemple:
{
"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": "...",
"referral": {
"headLine": "...",
"body": "...",
"sourceType": "...",
"sourceId": "...",
"sourceUrl": "...",
"mediaType": "...",
"mediaUrl": "..."
},
"mtSentAt": 1513616971473,
"message": {
"type": "TEXT",
"messageText": "Hi, this is a message from the user"
},
"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 |
referral | Present if the message was initiated by the user clicking in a post or ad. Contains information related to the ad. This field is optional (can be null). | Referral |
mtSentAt | The timestamp when the last MT was sent to this recipient. | Long |
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 |
Referral
All fields in this object are optional (can be null).
Field | Details | Type |
---|---|---|
headLine | Headline in the ad that generated the message. | String |
body | Body of the ad. | String |
sourceType | Type of the ad. Can either be “ad”, “post” or “unknown”. | String |
sourceId | Ad id in Facebook. | String |
sourceUrl | Ad url. | String |
mediaType | Ad media type. Can either be “image” or “post”. | String |
mediaUrl | Ad media url. | String |
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:
OPT IN
OPT OUT
BLACK LIST
WHITE LIST
Opened Sessions
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:
All customers have opt-out mechanics enabled by default and cannot disable it.
Our platform adds the user to the opt-out list when they send one of these words:
- Opt Out Words in English:
- stop
- exit
- Opt Out Words in Spanish:
- detener
- salir
- Opt Out Words in Portuguese:
- parar
- sair
- Opt Out Words in English:
We have an automatic message that will be sent to the user when they are added to the opt-out list, this is enabled by default for all customers but can be disabled. If you want to disable this automatic message for a specific customer just open a ticket to our customer support team. We send the automatic messages according to the optOut word language:
- Reply Message in English:
- Your request to leave the conversation was accomplished. Please send #start to come back!
- Reply Message in Spanish:
- Tu solicitud de abandonar la conversación se cumplió. ¡Envíe #volver para regresar!
- Reply Message in Portuguese:
- Seu pedido para sair da conversa foi atendido. Favor enviar #voltar para retornar!
- Reply Message in English:
When a user is in opt-out we will block every template sent to them unless the template is in one of the following categories: CUST_SERVICE or OTP
Our AI team classifies the templates in categories automatically using, guess what, AI!
All messages that are not templates will be sent normally if the session is open.
Our platform will remove the user from the opt-out list when they send one of these words:
- Opt Out Words in English:
- #start
- Opt Out Words in Spanish:
- #volver
- #recibir
- Opt Out Words in Portuguese:
- #voltar
- #receber
- Opt Out Words in English:
We also send an automatic message to the user when they are removed from the opt-out list. It is enabled by default for all customers and can be disabled by our customer support team. We send the automatic messages according to the optOut word language:
- Reply Message in English:
- Your request to return to the conversation has been granted! Welcome back!
- Reply Message in Spanish:
- Se ha concedido su solicitud para volver a la conversación! Bienvenido de nuevo!
- Reply Message in Portuguese:
- Seu pedido de retornar à conversa foi atendido! Bem vindo de volta!
- Reply Message in English:
WhatsApp Opt Out Event Notification
Each opt out will trigger a notification webhook with the event information.
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:
Example
{
"total": 1,
"data": [
{
"id": "8995c40f-1c3a-48d0-98ee-bbc603622a91",
"correlationId": "...",
"destination": "5519900000000",
"origin": "5519900000000",
"campaignId": 100,
"campaignAlias": "...",
"extraInfo": "...",
"conversation": {
"id": "conversationId123",
"origin": {
"type": "REFERRAL_CONVERSION"
},
"expiration": "2017-12-19T17:09:31.891Z"
},
"eventType": "OPT_OUT",
"eventDate": "2023-03-22T17:21:38.000Z"
}
],
"clientInfo": {
"customerId": 42,
"subAccountId": 1291,
"userId": 1
}
}
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 callbacks. Same id sent in the MT that matched the MO which generated the opt out event. | 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 |
conversation | The conversation object, that contains in itself id, origin.type and expiration. This object related to the new billable model of whatsapp messages. See Whatsapp Conversation. | Conversation |
eventType | Indicates the opt out event type. Can assume either ‘OPT_OUT’ or ‘EXIT_OPT_OUT’. If the value is ‘OPT_OUT’ then the user entered opt out else if value is ‘EXIT_OPT_OUT’ user exited optout. | String |
eventDate | Date when the opt out event occurred. Format: yyyy-MM-dd’T'HH:mm:ssZ | String |
ClientInfo
Field | Details | Type |
---|---|---|
customerId | Client identification. | Number |
subAccountId | SubAccount identification. | Number |
userId | User identification. | Number |
WhatsApp Conversation
Introduction
The Conversation Object is related to the Whatsapp’s messages new way of billing. A conversation can be started whenever a message by a business account is delivered, and it will last for a period of 24 hours. The Conversation Object has 3 attributes, which can be visualized by reports, metrics and callbacks. In our platform we use the following object structure:
Conversation
Field Name | Type | Details |
---|---|---|
conversation.id | String | An id it’s created whenever a conversation starts. |
conversation.origin | ConversationOrigin | The conversation origin object refers to where the conversation has originated from. |
conversation.expiration | Timestamp | Indicates when the ongoing conversation expires, which will follow the rule of 24 hours after the conversation it’s started. |
ConversationOrigin
Field Name | Type | Details |
---|---|---|
conversationOrigin.type | ConversationOriginType | The origin type enum, refers exactly to the types of origins a conversation can have. |
ConversationOriginType
Field Name | Details |
---|---|
BUSINESS_INITIATED | When a business account sends the first message to the user. |
USER_INITIATED | Indicates that the conversation started by a business account replying to an user message |
REFERRAL_CONVERSION | Conversation originated from a free entry point, which is when a user messages the business using call-to-actions buttons. |
See Whatsapp’s conversation object and conversation-based pricing official documentation.
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 |