Technical Documentation: SMS API.
| | |
MT | Mobile Terminated | Term used for messages that have the user (device) as destination. I.e., messages originating from your company, destined for the user (device) |
MO | Mobile Originated | Term used for messages that have your company as destination. I.e., messages originating from the user (device). It is used, for instance, in question and answer flows via SMS, when confirmation is required from the user. |
Response | Synchronous response from Wavy | The immediate response to a request made in our API, where we inform whether the message has been accepted by our platform. |
Callback | Sent status | The first sent status we return, where we inform whether the message has been delivered to the carrier. |
LA | Short Code | A short 5- or 6-digit number, used for sending and receiving SMS messages. They are appointed by carriers to approved integrators (Wavy) and have antifraud and antispam rules |
DR or DLR | Delivery Receipt | The second sent status we return, where we inform whether the message was delivered to the device. The carriers send this information to Wavy, and we relay it to the customer. Delivery time varies: for example, if the device was turned off at the time the message was sent and the user turned it back on 2 hours later, this DLR status will be delivered to the customer with a 2-hour delay. • This receipt of delivery to the device will only exist in cases where the message has been successfully delivered to the carrier, i.e., the first status (callback) was successful. • It is very important to highlight that unfortunately carriers Oi and Sercomtel do not have this functionality, that is, they do not give us information on delivery to the device. Messages sent to numbers from those carriers will only have information on delivery to the carrier (callback) |
Simplified Flow: MT, Callback, DLR, MO
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.
To send messages and run queries in our API, you need to authenticate using a combination of either username or email and a token.
Field | Details | Data Type |
UserName | Your username or email | String |
AuthenticationToken | Your authentication token. Check here and read username descriptions below. | String |
Type | Details | |
Administrator | Admin user for your company; it is used for creating/editing/deactivating subaccounts and other users, and it can view reports of the entire company. This user does not send messages, whether through the portal or via API integration. | |
User | User used for sending messages via API and portal; it can view reports specific to its subaccount. A user is always related to a single subaccount. A subaccount can have multiple users. Each subaccount is a cost center in our platform; messages are broken down in reports and financially by subaccount, and not by user. | |
templateID | SMS template identifier. The text of the message will be retrieved and it should first be created through the Messaging Portal. | Long |
templateName | SMS template name. It may not be exclusive, resulting in an error if more than one template is found for the user’s access level. The text of the message will be retrieved and it should first be created through the Messaging Portal | String |
| |
Hostname | api-messaging.wavy.global |
APIs | Single messages /v1/send-sms Bulk messages /v1/send-bulk-sms |
Port | 443 (https) |
Protocol | HTTPS (TLS encryption) |
Authentication | username + token |
Portal | messaging.wavy.global |
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 :)”
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.
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.
POST https://api-messaging.wavy.global/v1/send-sms - Content-Type: application/json
* Required field
Field | Details | Type |
destination* | Phone number to which the message will be sent (including country code). E.g.: 5511900000000 | String |
messageText* | Text of the message to be sent (max 1280 chars). | String |
correlationId | A unique ID set by you to match the sent statuses (callback and DLR). This parameter is optional, and you can use the ID generated by Wavy for this purpose (max 64 chars). | String |
extraInfo | Any extra information you wish to add to your message (max 255 chars). | String |
timeWindow | Messages will only be sent during the specified time. For example, if you set a [11, 12, 18] window, messages will be sent between 11:00 and 11:59 A.M., 12:00 and 12:59 P.M., and 6:00 and 6:59 PM. This parameter must be set in the root of the JSON object | Integer[] |
expiresAt | Your message will not be sent after this date. The format used is Unix time . Note: The expiresAt, expiresInMinutes and expiresDate field are mutually exclusive (use one of them only) | Long |
expiresInMinutes | Your message will expire after the time set in this field. The time starts counting as soon as your message is received by Wavy. Note: The expiresAt, expiresInMinutes and expiresDate fields are mutually exclusive (use one of them only) | Long |
expiresDate | Your message will not be sent after this date. This field accepts the following format yyyy-MM-dd’T'HH:mm:ss. Note: The expiresAt, expiresInMinutes and expiresDate fields are mutually exclusive (use one of them only) | String |
scheduledAt | Your message will not be sent after this date. IMPORTANT! You can only schedule a period longer than 30 minutes, as it is processed by a differentiated flow from non-scheduled messages. The format used is Unix time. The expiresAt, expiresInMinutes and expiresDate fields are mutually exclusive (use one of them only) | Long |
delayedInMinutes | How many minutes after the request is made your message will be sent. The expiresAt, expiresInMinutes and expiresDate fields are mutually exclusive (use one of them only) | Long |
scheduledDate | Your message will not be sent before this date. This field supports the format yyyy-MM-dd’T'HH:mm:ss. Note: The expiresAt, expiresInMinutes and expiresDate fields are mutually exclusive (use one of them only) | String |
timeZone | Specifies the time zone into be used directly in the fields: expiresDate, scheduledDate and timeWindow (which will be modified in case dynamic time zones are used, such as daylight saving time). If the time zone is not included in your request, the system will check the user’s time zone - if included - or the time zone of the user’s country as a last resort. If neither of these options are present, the system will use UTC time | String |
campaignAlias | Identification for a previously created campaign. Click here to register a new campaign; this parameter must be set in the root of the JSON object | String |
flashSMS | Flash SMS; use this option to send a pop-up message to a user’s phone. To send a Flash message, set parameter to true. | Boolean |
flowId | Bot flow identifier. The text of your message will come from the selected flow | String |
subAccount | Subaccount reference. It can only be used by Admin users | String |
params | Map of placeholders that will be replaced in the text of your message. If one or more parameters are incorrect, your message will be flagged as invalid, but delivery will not be cancelled. You must send the flowId to use parameters | Map |
For every user, there is a unique authentication token
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
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'
}
Most common HTTP status codes:
Group | Description |
2xx | Success |
4xx | Client Error |
5xx | Server Error |
Code | Description |
200 | Success |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
429 | Too Many Requests |
500 | Internal Server Error |
503 | Service Unavailable |
504 | Gateway Timeout |
Maximum limit is 700 requests per second per IP.
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.
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:
Action | Return status sent |
After a message is delivered or not to the carrier | Sent status API (callback) |
When a message is delivered or not to the customer’s device | Delivery Report API (DRs) |
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":"",
}
Field | Description |
id | Message UUID generated |
correlationId | Your identification for this message |
carrierId | Carrier identifier |
carrierName | Carrier name |
destination | Phone number to which your message was sent |
sentStatusCode | Status code generated by Wavy for your message indicating its sent status. Refer to status codes for more information |
sentStatus | Sent status description. Refer to status codes for more information |
sentAt | Time the message was sent, the format used is Unix_time |
sentDate | Date the message was sent. Format: yyyy-MM-dd’T'HH:mm:ssZ |
campaignId | Campaign identifier, if any |
extraInfo | Any extra information added by the customer when sending the message |
Field | Description |
id | Message UUID generated |
correlationId | Your identification for this message |
carrierId | Carrier identifier |
carrierName | Carrier name |
destination | Phone number to which your message was sent |
sentStatusCode | Status code generated by Wavy for your message indicating its sent status. Refer to status codes for more information |
sentStatus | Sent status description. Refer to status codes for more information |
sentAt | Time the message was sent, the format used is Unix_time |
sentDate | Date the message was sent. Format: yyyy-MM-dd’T'HH:mm:ssZ |
deliveredStatusCode | Status code generated by Wavy for your message indicating its delivered status. Refer to status codes for more information |
deliveredStatus | Delivered status description. Refer to status codes for more information |
deliveredAt | Time of delivery, the format used is Unix_time |
deliveredDate | Date the message was sent. Format: yyyy-MM-dd’T'HH:mm:ssZ |
campaignId | Campaign identifier, if any |
extraInfo | Any extra information added by the customer when sending the message |
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.
JSON response fields:
Field | Details | Type |
id | UUID generated in the request for the message | String |
correlationId | Same correlationId as in the request | String |
carrierId | Carrier ID; for more information, refer to error codes | Long |
carrierName | Carrier name | String |
destination | Phone number to which your message was sent | String |
sentStatusCode | Sent status code. Refer to Sent Status Codes for more information | Long |
sentStatus | Sent status. Refer to Sent Status Codes for more information | String |
sentStatusAt | When the message was sent. It is an Epoch Date | Long |
sentStatusDate | When the message was sent. Format yyyy-MM-dd’T'HH:mm:ssZ. Date format with time and time zone (ISO 8601) | String |
deliveredStatusCode | Delivered status code. Refer to Delivered Status Codes for more information | Long |
deliveredStatus | Delivered status. Refer to Delivered Status Codes for more information | String |
deliveredAt | When the message was delivered. It is an Epoch Date | Long |
deliveredDate | When the message was delivered. Format yyyy-MM-dd’T'HH:mm:ssZ. Date format with time and time zone (ISO 8601) | String |
campaignId | Campaign Identifier | Long |
extraInfo | Any extra information set by the user when the message was sent | String |
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
}
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
Profile | Permission |
Regular | each request made in the MO API will only return MOs that correspond to the subaccount the user belongs to. A regular user is not able to retrieve MOs from other subaccounts. |
Administrator | the default behavior for the administrator user is to retrieve all MOs from all subaccounts. If an admin wishes to retrieve MOs from only one subaccount, they need to specify the subaccount in the subAccount parameter with the id of the desired subaccount. |
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:
Field | Details | Type |
total | Total number of MOs returned by the request | Integer |
start | Minimum query limit | String |
end | Maximum query limit | String |
messages | List of objects | List |
Field | Details | Type |
id | Message ID | String |
subAccount | subaccount responsible for sending the message that generated the response | String |
carrierId | Carrier ID | Integer |
carrierName | Carrier name | String |
source | Phone number that sent the response message | String |
shortCode | Shortcode of the message that originated the response and through which the response was sent | String |
messageText | Text of the response message | String |
receivedAt | Time of receipt | Long |
receivedDate | Date and time of receipt in UTC format | String |
campaignAlias | Alias of the campaign that originated the response | String |
mt | Original MT that generated the response | MT |
Field | Details | Type |
id | MT ID | String |
correlationId | CorrelationID sent in the MT | String |
username | Username of the user responsible for sending the MT | String |
Email of the user responsible for sending the MT | String |
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
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
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.
Code | Message | Meaning |
2 | SENT_SUCCESS | Successfully delivered to the carrier (This is the status to be considered for billing purposes.) |
101 | EXPIRED | Expired before being delivered to the device |
102 | CARRIER_COMMUNICATION_ERROR | Communication error with the carrier |
103 | REJECTED_BY_CARRIER | The carrier has rejected the message |
201 | NO_CREDIT | The message limit set by your company’s administrator, for your account or subaccount, has been exceeded. Or, if your company uses the pre-paid credit model, it has run out. |
202 | INVALID_DESTINATION_NUMBER | The destination number is invalid (Not a valid mobile number). |
203 | BLACKLISTED | The destination number is blacklisted and has been manually entered by your company. |
204 | DESTINATION_BLOCKED_BY_OPTOUT | The destination number has opted out and no longer wishes to receive messages from this subaccount. (This status is specifically for mobile marketing accounts). |
205 | DESTINATION_MESSAGE_LIMIT_REACHED | The destination number has already received the maximum number of messages that one company can send, within a period of time. (This status is specifically for Mobile Marketing accounts, and this is a rule set by carriers). |
207 | INVALID_MESSAGE_TEXT | The text of your message contains words that are not accepted by the carrier. These words can be profanity, or, if yours is a Mobile Marketing account, they can be major brands. |
301 | INTERNAL_ERROR | An error occurred in Wavy’s platform. |
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.
Code | Message | Meaning |
4 | DELIVERED_SUCCESS | Successfully delivered to the device. |
104 | NOT_DELIVERED | The carrier has accepted the message, but was unable to deliver it to the device. Potential causes: Device is off or has no signal for a given period of time (usually 24 hours, but for some carriers, such as Vivo, this retry period is 8 hours). Number is valid, but inactive (some carriers only return this kind of error in this second status level). |
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
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.
Information | Details |
Hostname | smpp-messaging.wavy.global When setting your SMPP system, you must use the domain as destination, instead of IPs. This domain has 4 entry proxies with round robin DNS and health check, and multiple backend servers. Based on the volume of messages your company will transmit, we will increase the number of binds (connections) allowed simultaneously. |
Port | 2444 (SMPP over TLS) or 2443 (VPN) |
SMPP Version | 3.4 |
Bind Count | Minimum of 4. Setting at least 4 binds is required to obtain high availability and load balancing. |
Character Encoding | GSM7 - Default (data_coding = 0) (GSM3.38 extended table is not supported by carriers.) LATIN1 (data_coding = 1) UCS2 (data_coding=8). Attention: Check character and billing details HERE. |
Flash SMS | Supported data_coding=0x10 for GSM7 and data_coding 0x18 for UCS2 When we receive flashSMS messages from our customers, they are sent to carriers as flashSMS; if the carrier does not support flashSMS, it is delivered as a normal SMS message. |
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). Separate transmit/receiver binds are also accepted. |
SMPP system_type | MovileSMSC |
SMPP source addr (senderID) | When your service requires user responses (MO), the source address must match the system_id, i.e., username. When your service does not require MOs, you can use anything in 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 |
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.
stat | err | TLV (0x1403) | TLV (0x1404) | Meaning |
ACCEPTD | 000 | 2 | SENT_SUCCESS | Successfully delivered to the carrier (This is the status to be considered for billing purposes.) |
EXPIRED | 101 | 101 | EXPIRED | Expired before being delivered to the device. |
REJECTD | 102 | 102 | CARRIER_COMMUNICATION_ERROR | Communication error with the carrier. |
REJECTD | 103 | 103 | REJECTED_BY_CARRIER | The carrier has rejected the message. |
REJECTD | 201 | 201 | NO_CREDIT | The message limit set by your company’s administrator, for your account or subaccount, has been exceeded. Or, if your company uses the pre-paid credit model, it has run out. |
REJECTD | 202 | 202 | INVALID_DESTINATION_NUMBER | The destination number is invalid (Not a valid mobile number). |
REJECTD | 203 | 203 | BLACKLISTED | The destination number is blacklisted and has been manually entered by your company. |
REJECTD | 204 | 204 | DESTINATION_BLOCKED_BY_OPTOUT | The destination number has opted out and no longer wishes to receive messages from this subaccount. (This status is specifically for mobile marketing accounts). |
REJECTD | 205 | 205 | DESTINATION_MESSAGE_LIMIT_REACHED | The destination number has already received the maximum number of messages that one company can send, within a period of time. (This status is specifically for Mobile Marketing accounts, and this is a rule set by carriers). |
REJECTD | 207 | 207 | INVALID_MESSAGE_TEXT | The text of your message contains words that are not accepted by the carrier. These words can be profanity, or, if yours is a Mobile Marketing account, they can be major brands. |
REJECTD | 301 | 301 | INTERNAL_ERROR | An error occurred in Wavy’s platform. |
UNKNOWN | 301 | 301 | INTERNAL_ERROR | An error occurred in Wavy’s platform. |
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.
stat | err | TLV (0x1403) | TLV (0x1404) | TLV (0x1405) | TLV (0x1406) | Meaning |
DELIVRD | 000 | 2 | SENT_SUCCESS | 4 | DELIVERED_SUCCESS | Successfully delivered to the device. |
UNDELIV | 104 | 2 | SENT_SUCCESS | 104 | NOT_DELIVERED | The carrier has accepted the message, but was unable to deliver it to the device. Potential causes: Device is off or has no signal for a given period of time (usually 24 hours, but for some carriers, such as Vivo, this retry period is 8 hours). Number is valid, but inactive (some carriers only return this kind of error in this second status level). |
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.
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:
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
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
| |
Hostname | ftp-messaging.wavy.global |
Port | 2222 |
Protocol | SFTP (transfer over ssh, providing client-server encryption) |
Authentication | username + password (provided by support) |
Portal | messaging.wavy.global |
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
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.
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
To send messages and run queries in our API, you need to authenticate using a combination of username or email and a token.
Field | Details | Data Type |
UserName | Your username or email | String |
AuthenticationToken | Your authentication token. Check here and read username descriptions below. | String |
| |
Hostname | api-messaging.wavy.global |
APIs | /v1/carrier/lookup |
Port | 443 (https) |
Protocol | HTTPS (TLS encryption) |
Authentication | username + token |
Portal | messaging.wavy.global |
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
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:
Field | Details | Type |
id | UUID generated for this batch | String |
destinations | This field is an array with the responses of the individual batch queries, it contains the id and correlationId of each queried number | IndividualResponse[] |
destination | Queried phone number | Long |
active | number's status with the carrier (currently only checks whether the number belongs to the carrier, not active / in use) | Boolean |
carrier | Carrier and country to which the queried number belongs | array[] |
name | Carrier name | String |
countryCode | Country Code | String |
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.
| | | | | | | | | | | |
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 | |
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.
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.: