SMS API

Technical Documentation: SMS API.

Important Terms

Important Terms

Message Flow

Simplified Flow: MT, Callback, DLR, MO

HTTPS API

This API allows you to automatize both single and bulk message requests and the retrieval of sent statuses through queries. It uses HTTP protocol with TLS and accepts the GET method with query string parameters and the POST method with JSON parameters.

Authentication

To send messages and run queries in our API, you need to authenticate using a combination of either username or email and a token.

Connection Details

Encoding

The encoding standard used is UTF-8, all message contents must follow this standard.

You can escape characters if you wish or encode using HTTP format.

You can see some encoding examples to the side

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

Or you can escape characters if you so wish:

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

Sending Messages (MT)

Sending with GET Method - Individual

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"}'

After sending a message, you will receive a JSON informing the id that was generated for that message (Synchronous response from Wavy):

[

{

"id":"9cb87d36-79af-11e5-89f3-1b0591cdf807",

"correlationId":"myId"

}

]

Via GET method, you can send a message by relaying all parameters as a query string.

URL for Single Messages with GET Method

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

Via POST method, you can send a message by relaying all parameters in the body.

URL for Single Messages with POST Method

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

Request Parameters

* Required field

For every user, there is a unique authentication token

Messaging via POST Method - Single or Bulk

curl --request POST \

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

--header 'authenticationtoken: <Authentication Token>' \

--header 'username:<Movile Messaging User>' \

--header 'content-type: application/json' \

--data "{ "messages":[{ "destination":"5519999999999", "messageText":"First message" }, { "destination":"5519999999999" }, { "destination":"5519999999999" }], "defaultValues":{"messageText":"Default message" }}"

There is a 1000-message limit per request

After sending a message, a JSON object will be returned with the UUID for the batch and individual messages:

{

"id": "ce528d70-013b-11e7-98f2-e27c463c8809",

"messages": [

{

"id": "ce528d71-013b-11e7-98f2-e27c463c8809"

},

{

"id": "ce528d72-013b-11e7-98f2-e27c463c8809"

}

]

}

Allows you to send bulk or individual messages by relaying parameters in a JSON object. There is a 1000-message limit per request

HTTP Request via POST Method

Example of JSON for Bulk messaging:

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"

}

Example 5, with templateId/templateName (possible with either or both) and parameters:

{

"messages":[

{

"destination":"5519900001111",

"params": {

"param1": "other_value1",

"param2": "other_value2"

}

},

{

"destination":"5519900002222"

}

],

"defaultValues":{

"params": {

"param1": "value1",

"param2": "value2"

}

},

"templateId": 0,

"templateName": 'name'

}

HTTP Status Code Response

Most common HTTP status codes:

Maximum limit is 700 requests per second per IP.

Sent Status (Callback and DLR)

There are two ways of obtaining message sent statuses, namely:

  • Webhook - Receive statuses in a webserver of your company (recommended)

As soon as we deliver your message to the carrier, or as soon as the carrier informs us whether it has delivered your message to the device, this information is relayed to you instantaneously.

  • Query API - Make query requests in our sms-status API.

Statuses are available for 3 days and can be retrieved using the UUID that Wavy returned upon receiving the message from your company or the ID that your company received after delivering your message to Wavy.

The downside to this option Note in the examples above, some “destination” fields do not have a “messageText” directly attributed to them; in these cases, the text of your message will be the “messageText” within “defaultValues.” This function is useful when you need to send the same message to several different numbers of running queries instead of webhooks is that you will make query requests for an ID that might not have been delivered to the carrier or the device yet; in this case, a series of unnecessary requests will be made. For example, if a user had their device turned off when you sent them a message and they turned it back on 2 hours later, you will be requesting this ID countless times during two hours. And if you use a webhook, this information would be sent to you as soon as it was delivered to the device, without any empty requests.

Status queries have a rate-limit of 1 request per second per IP address. Requests beyond this limit are responded to with HTTP status code 429.

Statuses via Webhook (Delivery to Your Webservice)

In order to set the delivery of Callbacks and DRs (if you have questions about these terms, check the Important Terms tab), first you need to log in to Wavy Messaging in API settings; in the settings form, you can provide the URLs to which sent statuses (Callbacks) and device confirmation statuses (DRs) will be sent

After including your webhook in the portal above, your settings will be replicated to our platform within 10 minutes, and we will call your URL when the following actions occur:

Example of JSON sent status (callback - delivery 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 in Callbacks (sent status)

JSON response fields in Delivery Reports (DRs)

Status Query via HTTP Request

To check the status of the your last sent messages, you need to make a POST request to the URL below by sending the UUID(s) and/or correlationId(s) obtained in the sent response:

POST https://api-messaging.wavy.global/v1/sms/status/search

{ "ids": ["918F3591-9AD6-11E7-9C9B-E255B01A8B1A","234F3591-6AD6-11E7-9C9B-E255B01A8B1A"], "correlationIds": ["2468"] }

You can also obtain only the statuses that have not yet been requested:

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

Note that this endpoint only returns statuses that haven’t yet been returned by this endpoint.

Response

JSON response fields:

Example of JSON Delivery Report (DR or DLR - Delivery to the user’s 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 allows you to automatize the process of retrieving messages sent by customers in response to the messages you have sent them. All requests use the GET method, and responses are sent in JSON format. IMPORTANT! MO receipt is enabled by default only for LAs 27182 and 28149; if you need to receive messages through other Las, you need to contact support for evaluation.

You can also set it so that MOs are forwarded as they arrive to an API of the customer; this is the most efficient manner, as you don’t have to make any calls, just handle messages as they arrive. For this setting to be made, you need to open a ticket with our support team at customer.service@wavy.global relaying the url that will receive MOs. We are able to send MOs via both GET method (query string) and POST method (JSON)

Example of JSON 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": "I want 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 MOs received during the last 3 days, up to a limit of 1,000 MOs. For previous dates or larger amounts, please contact our support team at customer.service@wavy.global

The behavior of the MO query list will be different for each authenticated user due to each user’s permission level.

We recommend the method of sending MOs to an API; every MO sent will automatically be sent to an API, thus all responses can be handled immediately after receipt

Default MO Response Format

Example of JSON response to a Wavy API call:

{

"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": "I want 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": "Is my burger arriving?",

"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 list and search requests return a JSON object with the following fields:

Each message in the messages field has the following structure:

MTs have the following structure:

List MO Request

The List will return all MOs received since the last call according to the default response described above. Once this call is made, it will be consumed and will not return following calls.

As a regular user, to retrieve all MOs from a subaccount, use:

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

As an administrator user, to retrieve ALL MOs from ALL subaccounts, use:

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

As an administrator user, to retrieve MOs from a subaccount with the reference “referencia_subconta”, use:

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

Search MO Request

The search request will return each MO received within a given period of time. You must set the start and end parameters to specify a time period, using the ISO-8601 format. START by default is set for 5 days prior to the current date, and END by default is set for the current date. You cannot retrieve MOs prior to 5 days.

As a regular user, to retrieve all MOs from a subaccount, use:

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

As an administrator user, to retrieve ALL MOs from ALL subaccounts, use:

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

As an administrator user, to retrieve MOs from a subaccount with the reference “referencia_subconta”, use:

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

Search with set START and END parameters:

GET https://api-messaging.wavy.global/v1/sms/receive/search?start=2016-09-12T00:00:00&end=2016-09-15T00:00:00

Only with START specified (using default END, current date)

GET https://api-messaging.wavy.globalv1/sms/receive/search?start=2016-09-12T00:00:00

Only with END specified (using default START, 5 days prior to the current date)

GET https://api-messaging.wavy.global/v1/sms/receive/search?end=2016-09-15T00:00:00

Using default values for START and END and specifying the subaccount

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

Sent Status Codes

There are two status levels that are sent independently.

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

Status of delivery to the carrier, this is the first status we return, and all carriers have it.

2 - Second Status (delivered_status - Delivery Report Callback)

Status of delivery to the device, this is the second status we return and it only exists for cases where the first status above was successful, i.e., the message was successfully delivered to the carrier. In this status, we inform whether the message has been delivered to the device. Carriers Oi and Sercomtel do not have this second status level; for those carriers, the first status, i.e., whether the carrier has accepted your message, is the maximum information there is.

SMPP API

All services provided by Wavy must necessarily be encrypted, and the SMPP protocol does not have native encryption. In this case, we provide two options for integration:

This is the option we recommend. If your system does not have this functionality, click HERE to get help in setting up a TLS proxy.

In addition to the encryption to be done by TLS, access will only be authorized for the public IP of your server. (We accept multiple IPs and ranges) This information must be sent to the email address customer.service@wavy.global

If you need to allow outgoing traffic in your firewall, we recommend allowing any destination IP on port 2444; if not possible, you must include rules with the following allowances: 200.219.220.8:2444 200.219.220.193:2444 200.189.169.8:2444 189.36.59.86:2444 45.236.179.18:2444 45.236.179.19:2444

Option 2 - SMPP over VPN

Encryption and access granting will be done through VPN.

If you choose this option, set up VPNs using the peers and hosts below, already including the phase 1 and 2 proposals you wish. Please send the completed VPN form for your company to customer.service@wavy.global

peer 200.155.0.250 hosts 200.219.220.8 and 200.219.220.193 port 2443

peer 200.143.57.150 hosts 200.189.169.8 and 189.36.59.86 port 2443

peer 45.236.178.12 hosts 45.236.179.18 and 45.236.179.19 port 2443

For high availability and load balancing reasons, you are required to set the 2 VPNs, as well as use the smpp-messaging.wavy.global.com domain as your SMPP client’s destination, instead of IPs.

Connection Details

Sent Status (Callback and DLR)

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

Status of delivery to the carrier, this is the first status we return, and all carriers have it.

2 - Second Status (delivered_status - Delivery Report Callback)

Status of delivery to the device, this is the second status we return and it only exists for cases where the first status above was successful, i.e., the message was successfully delivered to the carrier. In this status, we inform whether the message has been delivered to the device. Carriers Oi and Sercomtel do not have this second status level; for those carriers, the first status, i.e., whether the carrier has accepted your message, is the maximum information there is.

Statuses of delivery to the device, carrier, and MOs are queued if a connectivity problem occurs, but the time period is 8h; after this, you will no longer be able to obtain statuses through SMPP.

TLS Proxy - Linux

The proxy is required if your connection is not made via VPN. As previously explained, the SMPP protocol does not have native TLS encryption; in this case we suggest the proxy below:

HAProxy

Installing the HAProxy

Debian-Like

In Debian-like distributions through the repository: sudo apt-get install haproxy

RedHat-Like

As there is currently no HAProxy package with TLS support already in the repository, you can download it from the official website: http://www.haproxy.org/

To the side, you will find a script for installation

sudo yum install wget gcc pcre-static pcre-devel -y

wget http://www.haproxy.org/download/1.6/src/haproxy-1.6.3.tar.gz -O ~/haproxy.tar.gz

tar xzvf ~/haproxy.tar.gz -C ~/

cd ~/haproxy-1.6.3

make TARGET=linux2628 USE_LINUX_TPROXY=1 USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_PCRE=1

sudo make install

sudo cp /usr/local/sbin/haproxy /usr/sbin/

sudo cp ~/haproxy-1.6.3/examples/haproxy.init /etc/init.d/haproxy

sudo chmod 755 /etc/init.d/haproxy

sudo mkdir -p /etc/haproxy

sudo mkdir -p /run/haproxy

sudo mkdir -p /var/lib/haproxy

sudo touch /var/lib/haproxy/stats

sudo useradd -r haproxy

sudo haproxy -vv

Setting up haproxy

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.movile.com smpp-messaging.wavy.global.com:2444 ssl resolvers dns check inter 15000

  • Installing haproxy servers (red-hat / centos):

$sudo yum install -y openssl-devel haproxy

  • Installing haproxy servers (debian / ubuntu)

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

  • After installing, replace the entire content of the /etc/haproxy/haproxy.cfg file with the content to the side ->

IMPORTANT: Set your system (SMPP client) to use 127.0.0.1:2444 as destination address

TLS Proxy - Windows

Setting up nginx

worker_processes 2;

events {

worker_connections 1024;

}

stream {

resolver 8.8.8.8 valid=1s;

map $remote_addr $backend {

default smpp-messaging.wavy.global.com;

}

server {

listen 2444;

proxy_pass $backend:2444;

proxy_ssl on;

}

}

You can use nginx as a TLS proxy in Windows servers to encrypt the data

Download the version below (it is important to use this version, as older versions only resolve the name in the first request)

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

Extract the .zip file to the desired location and replace the content of the conf/nginx.conf file with the data to the side

SFTP API

Connection Details

Your IPs must be allowed in Wavy’s firewalls. If you need to allow outgoing traffic in the firewall for port 2222, you must allow the DNS, or IPs 200.219.220.54, 200.189.169.53 and 45.236.179.22

Sending Messages via SFTP

To trigger messages via SFTP, you need to generate a TXT file, with formatting following the example below:

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

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

<SUBACCOUNT_ID>.<DATE(YYYYMMDD)>.<SEQUENCE> or <SUBACCOUNT_REFERENCE_NAME>.<DATE(YYYYMMDD)>.<SEQUENCE>

Subaccounts (projects) can be created by the customer themself in the portal. If the nomenclature above is not followed, the messages will be sent by the customer’s default subaccount.

Example:

3486.20170101.01.txt or PROJECT1.20170101.01.txt

It is important to follow the set nomenclature so the messages can be discounted from the correct subaccount.

Afterwards, the file must be sent to the sftp server in the upload directory. The file will be moved to the success directory after it is done; if any error occurs, the file will be moved to the error directory.

Number Validation API

API for validating phone numbers, where we return the current carrier of queried numbers (including ported numbers), or whether the number is invalid, i.e., it is not a mobile number.

IMPORTANT: Number lookup queries have a differentiated fee from SMS deliveries; before running a query, check with the head of the commercial team

Authentication

To send messages and run queries in our API, you need to authenticate using a combination of username or email and a token.

Connection Details

HTTP Request via POST Method

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"]

}'

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

To run a query, just add a json to the request body with the number array. You can run a query using the +55(19)999999999 and 5519999999999 formats

Query Response

Call response in JSON format

{

"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 shown now the query returns the JSON in such cases.

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

Accents & Special Characters

Messages containing only characters in the table below are charged for every 160 characters. If your message has one or more characters that are not in the table below, you will be charged for every 70 characters, as specified in the protocol of the carriers’ network.

Notes:

• Please request our support team to enable the use of accents and special characters.

• If the destination carrier does not accept accents and characters (Sercomtel), our platform automatically replaces them for our customers, such as: á to a, é to e, etc.

Long Texts (Concatenation)

The protocol used in the carriers’ network has 70- or 160-character limits for messages with or without special characters, respectively. But you can send longer messages using concatenation, where the device regroups messages upon receipt.

For customers integrated via HTTPS, SFTP, or MQ, there are no additional indicators in order to activate concatenation, just send the long message text in a single request.

For customers integrated via SMPP, you must use the concatenation feature with indicators in the header (UDH), LINK.

It is worth noting that, despite appearing on the device as a single long message, messages still travel through carriers’ networks individually, and, in this case, we continue being charged and charging individually for every 63 or 160 characters (depending on the characters used). Reminding that, when you use concatenation, part of the characters (70 or 160) are used by the header header.

Note: In cases of carriers that do not support the concatenation feature (e.g.: Sercomtel), Wavy sends the messages separately, without concatenating, and includes order indicators automatically for our customers. E.g.: