NAV
PHP Python C# NodeJS Java Ruby Go

Introduction

The purpose of this document is to describe LINK Mobility Messaging API.

The API can be used to send SMS and Viber messages.

The API uses REST technology with POST methods to HTTPS Endpoints.

LINK Mobility provides 3rd parties with api_key, api_secret, service_id and list of allowed senders.

Base URL's

Type URL
Production https://api.msghub.cloud/
Testing https://api-test.msghub.cloud/

API methods

Method Description Example
/send Send message to end-user https://api.msghub.cloud/send
/dlr Check status of previously send message https://api.msghub.cloud/dlr

Request Body

SMS Message

Example JSON (SMS)

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "registered_delivery": true,
    "callback_url": "http:\/\/example.com\/index.php",
    "context": {
        "foo": "bar"
    },
    "priority": "1024",
    "delay": "+11 hours",
    "parent_msg_id": "goGkSsMG2bpMtZDBoX8v",
    "unique": true,
    "max_sms_size": 1
}
Parameter Description Type Mandatory
msisdn Valid end-user mobile number string Yes
sc Sender / Display name string Yes
text Message to send string Yes
service_id LINK Mobility Service ID integer Yes
registered_delivery Request DLR for the message boolean No
priority Priority of the message integer/string No
delay Message delay in seconds integer/string No
context User defined context array No
max_sms_size Maximum sms’s to send integer No
unique Do not duplicate message boolean No

SMS length calculation

The maximum length of an SMS depends on the characters set used in its content. Typically, SMS containing only GSM-7 characters are limited to 160 characters while using any Unicode characters will limit the length to 70 symbols. Sending longer messages will be sent and billed as more than one SMS as per the table below:

Number of SMS Maximum GSM-7 characters Maximum Unicode characters
1 160 70
2 306 134
3 459 201
4 612 268
5 765 335
6 918 402
7 1071 469
8 1224 536
9 1377 603

SMS DLR Statuses

Code Description
201 The message is sent to carrier
202 The message is delivered to handset
203 The message is undelivered (invalid number, queue full, etc.)
204 Sending message failed
205 The message is rejected from carrier
206 Unknown error occurred. Please report this to LINK Mobility.

Viber specific parameters

Example JSON (Viber)

  {
      "msisdn": "359XXXXXXXXX",
      "sc": "ViberTest",
      "text": "Test Viber Message",
      "service_id": "1",
      "platform": 1,
      "registered_delivery": true,
      "callback_url": "http:\/\/example.com\/index.php",
      "context": {
          "foo": "bar"
      },
      "fallback": {
          "sms": "Test Message SMS"
      },
      "priority": "1024",
      "delay": "+11 hours",
      "ButtonName": "Cool Button",
      "ButtonUrl": "https:\/\/www.linkmobility.bg\/bg",
      "ImageUrl": "https:\/\/example.com\/example.jpg",
      "parent_msg_id": "goGkSsMG2bpMtZDBoX8v",
      "ttl": 120
  }
Parameter Description Type Mandatory
ButtonName Viber Button Text. Maximum allowed size is 30 characters. string No
ButtonUrl LINK Mobility Service ID string No
ImageUrl Viber Image URL string No
fallback Array of fallback texts array No
platform Enduser platform. Default: 2 integer No
ttl Time to live for the message. integer No

Viber File Message specific parameters

Example File Message JSON (Viber)

  {
      "msisdn": "359XXXXXXXXX",
      "sc": "ViberTest",
      "service_id": "1",
      "platform": 1,
      "registered_delivery": true,
      "callback_url": "http:\/\/example.com\/index.php",
      "fallback": {
          "sms": "Test Message SMS"
      },
      "FileUrl": "https://cdn.storage/files/example.pdf",
      "FileName": "Example Filename.pdf",
      "parent_msg_id": "goGkSsMG2bpMtZDBoX8v",
      "ttl": 120
  }
Parameter Description Type Mandatory
FileUrl File URL. Maximum size: 200mb. Supported formats: doc, docx, rtf, dot, dotx, odt, odf, fodt, txt, info, pdf, xps, pdax, eps, xls, xlsx, ods, fods, csv, xlsm, xltx string Yes
FileName Custom filename string No
fallback Array of fallback texts array No
platform Enduser platform. Default: 2 integer No
ttl Time to live for the message. integer No

Viber Video Message specific parameters

Example Video Message JSON (Viber)

  {
      "msisdn": "359XXXXXXXXX",
      "sc": "ViberTest",
      "text": "Test Viber Video Message",
      "service_id": "1",
      "platform": 1,
      "registered_delivery": true,
      "callback_url": "http:\/\/example.com\/index.php",
      "fallback": {
          "sms": "Test Message SMS"
      },
      "ButtonName": "Cool Button",
      "ThumbnailUrl": "https:\/\/example.com\/example.jpg",
      "VideoUrl": "https://storage.googleapis.com/viber-images/1016444621613da75f04.mp4",
      "VideoSize": 10,
      "Duration": 30,
      "parent_msg_id": "goGkSsMG2bpMtZDBoX8v",
      "ttl": 120
  }
Parameter Description Type Mandatory
ButtonName Viber Button Text. Maximum allowed size is 30 characters. string No
VideoUrl Video Message URL. Supported formats: 3gp, m4v, mov, mp4 string Yes
ThumbnailUrl Viber Video Thumbnail URL string Yes
VideoSize Video Size in MB. Maximum size: 200mb integer Yes
Duration Video Duration in seconds integer Yes
text Text for Video Message string No* (if button is not present, text is optional)
fallback Array of fallback texts array No
platform Enduser platform. Default: 2 integer No
ttl Time to live for the message. integer No

There are 3 different use cases for Viber Video Message.
1. Only video in the message.
2. Video + text message.
3. Video + text message + button (the button will redirect to the video url in browser).

Viber Delivery Report

Viber DLR Examples JSON

{
  "status": 202,
  "status_msg": "seen, done date:2022-07-25 12:55:34",
  "sent_timestamp": "2022-07-25 12:55:16",
  "dlr_timestamp": "2022-07-25 12:55:35",
  "sms_id": "BGP3-62de687e06f8c7.23349902",
  "service_id": "5",
  "type": "DLR",
  "channel": "VIBER"
}

{
  "status": 202,
  "status_msg": "delivered, done date:2022-07-25 12:55:23",
  "sent_timestamp": "2022-07-25 12:55:16",
  "dlr_timestamp": "2022-07-25 12:55:23",
  "sms_id": "BGP3-62de687e06f8c7.23349902",
  "service_id": "5",
  "type": "DLR",
  "channel": "VIBER"
}

{
  "status": 203,
  "status_msg": "bad data, done date:2022-07-25 12:58:14",
  "sent_timestamp": "2022-07-25 12:58:13",
  "dlr_timestamp": "2022-07-25 12:58:14",
  "sms_id": "BGP1-62de69304938a8.88127029",
  "service_id": "5",
  "type": "DLR",
  "channel": "VIBER"
}
Parameter Description Type Mandatory
sms_id Message ID to check string Yes
service_id GW3 service integer Yes
status_msg Message for the DLR event (comma separated) integer Yes
sent_timestamp When message was sent datetime Yes
dlr_timestamp When this DLR event was received datetime Yes
type Event type (DLR/MO) string Yes
channel The channel of the DLR (in this case viber) string Yes

Push Notification specific parameters

Example Message JSON (Push Notification)

  {
      "sc": "PushTest",
      "service_id": "1",
      "fallback": {
          "sms": "Test Message SMS"
      },
      "push": {
        "title": "Example title!",
        "body": "Example body description!",
        "uid": "cloud.msghub.example_df123e3ihuhfdaXXXXX",
        "redirect_url": "https://example.com",
        "image": "https://cdn.com/examples/image.jpg"
      },
      "priority": 1024
  }
Parameter Description Type Mandatory
push Push Notification's payload. Fields:
title: string,
body: string,
uid: string,
package: string,
redirect_url: string,
image: string
array Yes* (title & body & uid/package are mandatory parameters, the rest are optional. Note: you can either send to a uid or send to a package which will send to all devices subscribed to this package.)
msisdn Msisdn can be used for fallback if sending push 1 by 1 string No
fallback Array of fallback texts array No

Push Notification Delivery Report Statuses

Value Description
delivered The PN is received by the device
opened The PN is tapped (seen) by the user
swiped The PN is cleared/discarded by the user

Push Notifications Delivery Report

Push Notifications DLR Examples JSON

{
  "status": 202,
  "status_msg": "delivered, done date: 2022-08-11 16:31:41",
  "sent_timestamp": "2022-08-11 16:31:41",
  "dlr_timestamp": "2022-08-11 16:31:43",
  "sms_id": "BGP3-62f504b4a24e79.57913864",
  "service_id": "1395",
  "type": "DLR",
  "channel": "PUSH"
}

{
  "status": 202,
  "status_msg": "swiped, done date: 2022-08-11 16:31:54",
  "sent_timestamp": "2022-08-11 16:31:41",
  "dlr_timestamp": "2022-08-11 16:31:56",
  "sms_id": "BGP3-62f504b4a24e79.57913864",
  "service_id": "1395",
  "type": "DLR",
  "channel": "PUSH"
}
Parameter Description Type Mandatory
sms_id Message ID to check string Yes
service_id GW3 service integer Yes
status_msg Message for the DLR event (comma separated) integer Yes
sent_timestamp When message was sent datetime Yes
dlr_timestamp When this DLR event was received datetime Yes
type Event type (DLR only for Push) string Yes
channel The channel of the DLR (in this case Push) string Yes

Response

Example Response

{
  "meta": {
      "code": 200,
      "text": "OK"
  },
  "data": {
      "sms_id": "light-5b83e6df35fe41.14520017",
      "request_id": "605aff94c0fde9.89437771"
  }
}

Response from the API is JSON encoded string. It contains meta and data field.

The meta field contains status code and text description.

The data field contains additional information about the request, for example the sms_id.

Headers

POST /send HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 75
Content-Type: application/json
Host: api-test.msghub.cloud
x-api-key: $vY$aQLmRIRHI0eZR6vDay5KYm3iTwCYPOkJfjqmjomtnBztDRZqfpV8oirf
x-api-sign: PlBIoNRG5PFdnfb6AoJgT78LlkIYhqPxS4zvjM0Ell3BtCC9Sebtpq2bPYPR3wowtxvPe1Zn6QBT6

Parameter Value Type Mandatory
Content-type application/json string Yes
x-api-key YOUR_API_KEY string Yes
x-api-sign HASH HMAC signature string Yes
Expect string Yes

Authentication

Creating a signature

<?php

$signature = hash_hmac('sha512', $postData, $api_secret);
private static string HashHmacSha512(string message, string secret)
{
  Encoding encoding = Encoding.UTF8;

  using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
  {
      var msg = encoding.GetBytes(message);
      var hash = hmac.ComputeHash(msg);

      return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
  }
}
import hmac
import hashlib

signature = hmac.new(bytes(API_SECRET, 'utf8'), bytes(data, 'utf8'), hashlib.sha512).hexdigest()
const crypto = require('crypto');
let signature = crypto.createHmac("sha512", secret).update(data).digest('hex');
private static String buildHmacSignature(String value, String secret) {
      String result;
      try {
          Mac hmacSHA512 = Mac.getInstance("HmacSHA512");
          SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(),
                  "HmacSHA512");
          hmacSHA512.init(secretKeySpec);

          byte[] digest = hmacSHA512.doFinal(value.getBytes());
          BigInteger hash = new BigInteger(1, digest);
          result = hash.toString(16);
          if ((result.length() % 2) != 0) {
              result = "0" + result;
          }
      } catch (IllegalStateException | InvalidKeyException | NoSuchAlgorithmException ex) {
          throw new RuntimeException("Problem calculating HMAC", ex);
      }
      return result;
  }
require 'openssl'

signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), API_SECRET, data)
package main

import (
  "crypto/hmac"
  "crypto/sha512"
  "encoding/hex"
)

h := hmac.New(sha512.New, []byte(Api_secret))
h.Write(dataJson)
signature := hex.EncodeToString(h.Sum(nil))

To authenticate to the API you have to sign the data you post.

  1. Construct the Request Body in JSON format

  2. Create a hash using the shared api_secret

  3. Include the signature in the request headers as x-api-sign

  4. Using the shared api_secret, LINK Mobility creates signature of the received JSON POST data

  5. If LINK Mobility’s signature matches the one included in the request, the request is serviced

Examples

<?php

/**
 * Single Message
 */

$api_endpoint = "https://<LINK_MOBILITY_ENDPOINT>/send";
$api_key = '<YOUR_API_KEY>';
$api_secret = '<YOUR_API_SECRET>';

$data = [
    'msisdn'      => '35988XXXXXXX',
    'sc'          => '1909',
    'text'        => 'Test Message!',
    'service_id'  => '<YOUR_SERVICE_ID>',
];

$data = json_encode($data);

$signature = hash_hmac('sha512', $data, $api_secret);

$headers = [
  "Content-Type: application/json",
  "x-api-key: {$api_key}",
  "x-api-sign: {$signature}",
  "Expect: ",
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_endpoint);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$result = curl_exec($ch);

curl_close($ch);

$result = json_decode($result);

var_dump($result);

/**
 * Multiple Messages
 */

$api_endpoint = "https://<LINK_MOBILITY_ENDPOINT>/send";
$api_key = '<YOUR_API_KEY>';
$api_secret = '<YOUR_API_SECRET>';

$data = [
  [
    'msisdn'      => '35988XXXXXXX',
    'sc'          => '1909',
    'text'        => 'Test Message!',
    'service_id'  => '<YOUR_SERVICE_ID>',
  ],
  [
    'msisdn'      => '35988XXXXXXX',
    'sc'          => '1909',
    'text'        => 'Test Message!',
    'service_id'  => '<YOUR_SERVICE_ID>',
  ],
  [
    'msisdn'      => '35988XXXXXXX',
    'sc'          => '1909',
    'text'        => 'Test Message!',
    'service_id'  => '<YOUR_SERVICE_ID>',
  ],
];


$data = json_encode($data);

$signature = hash_hmac('sha512', $data, $api_secret);

$headers = [
  "Content-Type: application/json",
  "x-api-key: {$api_key}",
  "x-api-sign: {$signature}",
  "Expect: ",
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_endpoint);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$result = curl_exec($ch);

curl_close($ch);

$result = json_decode($result);

var_dump($result);
using System;
using System.Text;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Security.Cryptography;

/**
* Single message
*/

namespace SMS
{
    class Program
    {
        private const string apiEndPoint = "https://<LINK_MOBILITY_ENDPOINT>/send";
        private const string apiKey = "<YOUR_API_KEY>";
        private const string apiSecret = "<YOUR_API_SECRET>";

        private class SMSRequestData
        {
            public string msisdn { get; set; }
            public string sc { get; set; }
            public string text { get; set; }
            public string service_id { get; set; }
        }

        static async Task Main(string[] args)
        {

            SMSRequestData data = new SMSRequestData
            {
                msisdn         = "35988XXXXXXX",
                sc             = "1909",
                text           = "Test Message!",
                service_id     = "<YOUR_SERVICE_ID>",
            };

            string jsonData = JsonSerializer.Serialize(data);

            string signature = HashHmacSha512(jsonData, apiSecret);

            var postData = new StringContent(jsonData, Encoding.UTF8, "application/json");

            using var client = new HttpClient();

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("x-api-key", apiKey);
            client.DefaultRequestHeaders.Add("x-api-sign", signature);
            client.DefaultRequestHeaders.Add("Expect", string.Empty);

            var response = await client.PostAsync(apiEndPoint, postData);

            string result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }

        private static string HashHmacSha512(string message, string secret)
        {
            Encoding encoding = Encoding.UTF8;
            using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
            {
                var msg = encoding.GetBytes(message);
                var hash = hmac.ComputeHash(msg);
                return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
            }
        }
    }
}

/**
* Multiple messages
*/

namespace SMS
{
    class Program
    {
        private const string apiEndPoint = https://<LINK_MOBILITY_ENDPOINT>/send;
        private const string apiKey = "<YOUR_API_KEY>";
        private const string apiSecret = "<YOUR_API_SECRET>";

        private class SMSRequestData
        {
            public string msisdn { get; set; }
            public string sc { get; set; }
            public string text { get; set; }
            public string service_id { get; set; }
        }

        static async Task Main(string[] args)
        {
            List<SMSRequestData> smsRequests = new List<SMSRequestData>()
            {
                new SMSRequestData
                {
                    msisdn = "35988XXXXXXX",
                    sc = "1909",
                    text = "Test Message!",
                    service_id = "<YOUR_SERVICE_ID>",
                },
                new SMSRequestData
                {
                    msisdn = "35988XXXXXXX",
                    sc = "1909",
                    text = "Test Message!",
                    service_id = "<YOUR_SERVICE_ID>",
                }
                new SMSRequestData
                {
                    msisdn = "35988XXXXXXX",
                    sc = "1909",
                    text = "Test Message!",
                    service_id = "<YOUR_SERVICE_ID>",
                }
            };

            string jsonData = JsonSerializer.Serialize(smsRequests);

            string signature = HashHmacSha512(jsonData, apiSecret);

            var postData = new StringContent(jsonData, Encoding.UTF8, "application/json");

            using var client = new HttpClient();

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("x-api-key", apiKey);
            client.DefaultRequestHeaders.Add("x-api-sign", signature);
            client.DefaultRequestHeaders.Add("Expect", string.Empty);

            var response = await client.PostAsync(apiEndPoint, postData);

            string result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }

        private static string HashHmacSha512(string message, string secret)
        {
            Encoding encoding = Encoding.UTF8;
            using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
            {
                var msg = encoding.GetBytes(message);
                var hash = hmac.ComputeHash(msg);
                return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
            }
        }
    }
}
import hmac
import hashlib
import json
import requests

#
# Single message
#

ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send"
API_KEY = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRET>"

data = {
  "msisdn":     "35988XXXXXXX",
  "sc":         "1909",
  "text":       "Test Message!",
  "service_id": "1"
};

data = json.dumps(data)

signature = hmac.new(bytes(API_SECRET, 'utf8'), bytes(data, 'utf8'), hashlib.sha512).hexdigest()

headers = {
  "Content-Type": "application/json",
  "x-api-key":    API_KEY,
  "x-api-sign":   signature,
  "Expect":       ""
};

request = requests.post(ENDPOINT, data=data, headers=headers)

print(request.text)

#
# Multiple messages
#

ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send"
API_KEY = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRET>"

data = [
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "1"
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "1"
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "1"
  }
]

data = json.dumps(data)

signature = hmac.new(bytes(API_SECRET, 'utf8'), bytes(data, 'utf8'), hashlib.sha512).hexdigest()

headers = {
  "Content-Type": "application/json",
  "x-api-key":    API_KEY,
  "x-api-sign":   signature,
  "Expect":       ""
};

request = requests.post(ENDPOINT, data=data, headers=headers)

print(request.text)

const crypto = require('crypto');
const request = require('request');

const endpoint = "https://<LINK_MOBILITY_ENDPOINT>/send";
const api_key = "<YOUR_API_KEY>";
const secret = "<YOUR_API_SECRET>";

/**
* Single message
*/

let data = {
  "msisdn":     "35988XXXXXXX",
  "sc":         "1909",
  "text":       "Test Message!",
  "service_id": "<YOUR_SERVICE_ID>",
};

data = JSON.stringify(data);

let signature = crypto.createHmac("sha512", secret).update(data).digest('hex');

let headers = {
    "Content-Type": "application/json",
    "x-api-key":    `${api_key}`,
    "x-api-sign":   `${signature}`,
    "Expect":       "",
};

const callback = (error, response, body) => {
  console.log(body);
};

request.post(endpoint, {
    headers: headers,
    body: data,
    callback
});

/**
* Multiple messages
*/

let data = [
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "<YOUR_SERVICE_ID>",
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "<YOUR_SERVICE_ID>",
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test Message!",
    "service_id": "<YOUR_SERVICE_ID>",
  }
];

data = JSON.stringify(data);

let signature = crypto.createHmac("sha512", secret).update(data).digest('hex');

let headers = {
    "Content-Type": "application/json",
    "x-api-key":    `${api_key}`,
    "x-api-sign":   `${signature}`,
    "Expect":       "",
};

const callback = (error, response, body) => {
  console.log(body);
};

request.post(endpoint, {
    headers: headers,
    body: data,
    callback
});


/**
* Single message
*/

public class Main {
    private static String buildHmacSignature(String value, String secret) {
        String result;
        try {
            Mac hmacSHA512 = Mac.getInstance("HmacSHA512");
            SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(),"HmacSHA512");
            hmacSHA512.init(secretKeySpec);
            byte[] digest = hmacSHA512.doFinal(value.getBytes());
            BigInteger hash = new BigInteger(1, digest);
            result = hash.toString(16);
            if ((result.length() % 2) != 0) {
                result = "0" + result;
            }
        } catch (IllegalStateException | InvalidKeyException | NoSuchAlgorithmException ex) {
            throw new RuntimeException("Problem calculating HMAC", ex);
        }
        return result;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        final String ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send";
        final String API_KEY = "<YOUR_API_KEY>";
        final String API_SECRET = "<YOUR_API_SECRET>";

        String data = "{" +
                "\"msisdn\":\"35988XXXXXXX\"," +
                "\"sc\":\"1909\"," +
                "\"text\":\"Test message!\"," +
                "\"service_id\":\"<YOUR_SERVICE_ID>\"" +
                "}";

        String signature = buildHmacSignature(data, API_SECRET);
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(ENDPOINT))
                .POST(HttpRequest.BodyPublishers.ofString(data))
                .header("Content-Type", "application/json")
                .header("x-api-key", API_KEY)
                .header("x-api-sign", signature)
                /*.header("Expect", "")*/ // must be run with java -Djdk.httpclient.allowRestrictedHeaders=expect
                .build();

        HttpResponse<String> response = client.send(request,HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}

/**
* Multiplce messages
*/

public class Main {
    private static String buildHmacSignature(String value, String secret) {
        String result;
        try {
            Mac hmacSHA512 = Mac.getInstance("HmacSHA512");
            SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(),"HmacSHA512");
            hmacSHA512.init(secretKeySpec);
            byte[] digest = hmacSHA512.doFinal(value.getBytes());
            BigInteger hash = new BigInteger(1, digest);
            result = hash.toString(16);
            if ((result.length() % 2) != 0) {
                result = "0" + result;
            }
        } catch (IllegalStateException | InvalidKeyException | NoSuchAlgorithmException ex) {
            throw new RuntimeException("Problem calculating HMAC", ex);
        }
        return result;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        final String ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send";
        final String API_KEY = "<YOUR_API_KEY>";
        final String API_SECRET = "<YOUR_API_SECRET>";

        JSONArray data = new JSONArray(
          "[{\"msisdn\":\"35988XXXXXXX\",\"sc\":\"1909\",\"text\":\"Test message!\",\"service_id\":\"<YOUR_SERVICE_ID>\"},{\"msisdn\":\"35988XXXXXXX\",\"sc\":\"1909\",\"text\":\"Test message!\",\"service_id\":\"<YOUR_SERVICE_ID>\"},{\"msisdn\":\"35988XXXXXXX\",\"sc\":\"1909\",\"text\":\"Test message!\",\"service_id\":\"<YOUR_SERVICE_ID>\"}]"
        );

        String signature = buildHmacSignature(data, API_SECRET);
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(ENDPOINT))
                .POST(HttpRequest.BodyPublishers.ofString(data))
                .header("Content-Type", "application/json")
                .header("x-api-key", API_KEY)
                .header("x-api-sign", signature)
                /*.header("Expect", "")*/ // must be run with java -Djdk.httpclient.allowRestrictedHeaders=expect
                .build();

        HttpResponse<String> response = client.send(request,HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}
require 'json'
require 'openssl'
require 'net/https'

#
# Single message
#

ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send"
API_KEY = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRET>"

data = {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test message!",
    "service_id": "<YOUR_SERVICE_ID>"
};

data = data.to_json

signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), API_SECRET, data)

headers = {
    "Content-Type": "application/json",
    "x-api-key": API_KEY,
    "x-api-sign": signature,
    "Expect": ""
};

uri = URI.parse(ENDPOINT)

http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, headers)
request.body = data
http.use_ssl = true
response = http.request(request)

puts response.body

#
# Multiple messages
#

ENDPOINT = "https://<LINK_MOBILITY_ENDPOINT>/send"
API_KEY = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRET>"

data = [
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test message!",
    "service_id": "<YOUR_SERVICE_ID>"
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test message!",
    "service_id": "<YOUR_SERVICE_ID>"
  },
  {
    "msisdn":     "35988XXXXXXX",
    "sc":         "1909",
    "text":       "Test message!",
    "service_id": "<YOUR_SERVICE_ID>"
  }
];

data = data.to_json

signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), API_SECRET, data)

headers = {
    "Content-Type": "application/json",
    "x-api-key": API_KEY,
    "x-api-sign": signature,
    "Expect": ""
};

uri = URI.parse(ENDPOINT)

http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, headers)
request.body = data
http.use_ssl = true
response = http.request(request)

puts response.body
package main

/**
* Single message
*/

import (
  "bytes"
  "crypto/hmac"
  "crypto/sha512"
  "encoding/hex"
  "encoding/json"
  "fmt"
  "io"
  "net/http"
)

func main() {
  const (
    Endpoint   = "https://<LINK_MOBILITY_ENDPOINT>/send"
    Api_key    = "<YOUR_API_KEY>"
    Api_secret = "<YOUR_API_SECRET>"
  )
  dataMap := map[string]string{
    "msisdn":     "35988XXXXXXX",
    "sc":         "1990",
    "text":       "Test message!",
    "service_id": "<YOUR_SERVICE_ID>",
  }

  dataJson, _ := json.Marshal(dataMap)

  h := hmac.New(sha512.New, []byte(Api_secret))
  h.Write(dataJson)
  signature := hex.EncodeToString(h.Sum(nil))

  client := &http.Client{}
  req, _ := http.NewRequest("POST", Endpoint, bytes.NewBuffer(dataJson))
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-api-key", Api_key)
  req.Header.Add("x-api-sign", signature)
  req.Header.Add("Expect", "")
  resp, _ := client.Do(req)

  defer resp.Body.Close()

  body, _ := io.ReadAll(resp.Body)

  fmt.Println(string(body))
}

/**
* Multiple messages
*/
import (
  "bytes"
  "crypto/hmac"
  "crypto/sha512"
  "encoding/hex"
  "encoding/json"
  "fmt"
  "io"
  "net/http"
)

type message struct {
    MSISDN    string `json:"msisdn"`
    ShortCode string `json:"sc"`
    Text      string `json:"text"`
    ServiceId string `json:"service_id"`
}

func main() {
    dataMap := []message{{
    "3598888888888", 
    "1990", 
    "test 1", 
    "12345",
  }, 
  {
    "3598888811111", 
    "1900", 
    "test 2", 
    "4567",
  }}

  payload, _ := json.Marshal(dataMap)

  h := hmac.New(sha512.New, []byte(Api_secret))
  h.Write(payload)
  signature := hex.EncodeToString(h.Sum(nil))

  client := &http.Client{}
  req, _ := http.NewRequest("POST", Endpoint, bytes.NewBuffer(payload))
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("x-api-key", Api_key)
  req.Header.Add("x-api-sign", signature)
  req.Header.Add("Expect", "")
  resp, _ := client.Do(req)

  defer resp.Body.Close()

  body, _ := io.ReadAll(resp.Body)

  fmt.Println(string(body))
}

Response Codes

Code Description
200 OK
400 Bad Request
401 Unauthorized
402 Empty required parameters
403 Invalid input parameters
404 Invalid or empty msisdn
405 Invalid or empty service_id
406 Invalid or empty text
407 Invalid or empty shortcode
408 Throttle limit reached
410 Empty or invalid ButtonUrl (Viber only)
411 Empty or invalid ImageUrl! (Viber only)
412 Invalid callback url
413 Invalid context data
414 Invalid max_sms_size
415 SMS with duplicate ID
500 Error processing request
501 Send text failed

Using Postman

Signature generation in Postman (Pre-request script)

API_KEY = 'YOUR_API_KEY';
SECRET_KEY = 'YOUR_API_SECRET';

function getAuthHeaderxkey(requestBody) {
    var hmacDigest = CryptoJS.HmacSHA512(requestBody, SECRET_KEY).toString(CryptoJS.digest);
    return hmacDigest;
}

var Header = require('postman-collection').Header
pm.request.headers.add(new Header("x-api-key: " + API_KEY))
pm.request.headers.add(new Header("x-api-sign: " + getAuthHeaderxkey(request['data'])))

You can download Postman collection from this url: download

The collection includes examples for:

Message Priority

Example using custom high priority

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "priority": "101"
}

Example using predefined priority constant

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "priority": "high"
}

Priority can be added to each message.

The priority range is from 0 to 2048.

Priority can also be set with the predefined constants: low, high, normal;

Predefined constant Value
low 2048
normal 1024
high 512

Message Delay

Example delay with 5 minutes

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "delay": "300"
}

Example using mnemonic

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "delay": "+10 minutes"
}

The message delay defines when the message should be send.

The delay value is in seconds, but you can also use mnemonics.

Example mnemonics:

1 November 2018 10:00:00

+30 minutes

+10 seconds

2019-10-02 09:00:00

Unique Parameter

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "unique": true
}

When unique parameter is set to true the API will check if currently send message has already been sent and reply with error if so.

The API uses parent_msg_id as unique identifier for the message.

If not provided it will create one using combination of msisdn, sc, text.

Message Size

The maximum SMS size depends on message encoding.

The default encoding for SMS messages is GSM 7 bit.

This encoding is limited to 140 bytes or total of 160 characters.

For characters supported by GSM 7 bit please refer to this link.

UCS-2 encoding supports up to 70 16 bit characters.

If the message is over 70 characters it will be sent as concatenated message.

Concatenated Message

Example of limiting maximum messages to send to 1

{
    "msisdn": "359XXXXXXXXX",
    "sc": "1909",
    "text": "Test SMS Message",
    "service_id": "1",
    "max_sms_size": 1
}

Concatenated message is a long message (more than 160 characters in 7 bit encoding or more than 70 in UCS-2 encoding).

These messages are split and send individually to the Mobile Operator. (additional charges may occur)

Once received on the end user handset they are recombined again into 1 message.

SMS Fallback

Example Fallback

  {
      "msisdn": "359XXXXXXXXX",
      "sc": "ViberTest",
      "text": "Test Viber Message",
      "service_id": "1",
      "fallback": {
          "sms": "Test Message SMS"
      }
  }

Fallback is functionality that will resend failed Viber messages as SMS.