Navbar
Java PHP C# Python NodeJS
  • Get Started
  • Get Started

    Learn the basics. Connect your application using Apifon’s API and optimize the communication with your customers.

    Sign Up

    Before you start, please take a moment to register to the platform.

    Introduction

    These guidelines assist the connection of your application to the ADMS (Apifon Distributed Messaging System), allowing you to seamlessly communicate with customers anywhere in the world.

    There are two ways of using Apifon’s services: The first one is via the SMPP protocol, which effectively links your application to the SMSC servers. To set up an SMPP bind, please contact here. The second one is via the HTTP interface, which enables your application to send out SMS and IM messages.

    The following two images explain how the Apifon REST API messaging and callback services function: alt text

    alt text

    HTTP Methods

    4 HTTP Methods are supported:

    Versioning

    Apifon's REST API supports API versioning. It uses URI versioning and deprecation of resources.

    Versioning in the URI is placed before the resource in format vX - where X is the number of the version.

    See the example below:

    https://ars.apifon.com/services/api/v1

    In case of a breaking change in the API, a new URI versioning will be established and documented.

    Older versions may end up being deprecated and marked for removal.
    It is strongly recommended not using deprecated resources as they may get removed in the future.

    Parameters

    There are four main categories of parameters for each endpoint in the REST API:

    The API reference includes all available parameters for each possible request. See below an overview of the categories:

    Path Parameters

    In the API URL, resource names and unique identifiers help you figure out the structure of the requests. Resource names are immutable. However, resource identifiers are required. Thus, they are needed to be replaced with real values.

    See the example below:

    https://ars.apifon.com/services/api/v1/list/{list_id}/field/{field}

    In this URL there is one resource (lists) and one subresource (field). There are also two path parameters that are needed to be replaced with real values (list_id and field).

    NOTE: Path parameters are enclosed in { } in the API reference.

    When these values are replaced, the final URL should look like this:

    https://ars.apifon.com/services/api/v1/list/5ce4fcef7ed5cc3898208e67/field/date_BIRTHDAY

    Query Parameters

    Apifon REST API allows query parameters to be used for partial responses, result filtering, pagination and result sorting.

    Partial Responses

    Use the field parameter to reduce the amount of data transferred, by limiting the fields the API returns. For example, if not all details of the resource are needed, it is recommended to pass a comma-separated list. In this way, only the desired fields are to be included in the field parameter.

    For example, the following API returns list resources which include only the id, title and the description fields:

    https://ars.apifon.com/services/api/v1/list?fields=id,title,description

    NOTE: The parameter fields will throw an error response if a field in the request is not valid.

    Pagination

    Paginate requests to limit response results and facilitate the process.

    Page and size parameters can be used as query parameters in the URL query string to paginate GET requests or POST requests.

    size refers to the maximum amount of results which will be included in the results. page refers to the current page of the results viewed.

    For example, if you want the second page to feature 20 results, the following query parameter must be included in your request:

    https://ars.apifon.com/services/api/v1/list?page=2&size=20

    NOTE: Pagination parameters can be omitted from your request and will be set back to default values by the API. For the default values refer to the specific endpoint implementations in the API reference.

    Sort

    Apifon's API supports results sorting when multiple resources are returned from an endpoint.

    Sort and sort_dir parameters can be used in the URL query string to paginate on GET requests or in the JSON request body of POST requests.

    sort contains a property name on which the sort is applied. sort_dir is an enumeration (DESC/ASC) which indicates the sort direction.

    For example, in case you want to retrieve lists resources sorted by their creation date in ascending order, the link should look like this:

    https://ars.apifon.com/services/api/v1/list?sort=date_created&sort_dir=ASC

    NOTE: Sort parameters can be omitted from your request, and will be set to default values by the API. For the default values refer to the specific endpoint implementations in the API reference.

    Result Filtering

    Apifon's API supports filtering of returned results. The API reference explains which resources can be filtered and what should be included in the URL query string.

    NOTE: If multiple filters are provided, the API returns resources which match all filters.

    Request body

    For PUT and POST requests, a request body in JSON format needs to be included.

    Content-Type : application/json

    The API Reference shows all available request parameters for each endpoint, including required fields and default values.

    Response body

    The API Reference includes all possible response body parameters.

    NOTE: Some endpoints may return an empty response body.

    For endpoints that provide paginated results, links object will contain URIs that access the first, last, previous and next page of results.

    Meta

    Meta object contain additional information about the response, such as the total number of resources on paginated results, entity tags (if applicable) etc. API Reference contains a list of all available meta information of a resource.

    HTTP ETag

    Entity Tags (Commonly called ETags) are identifiers for a resource.

    Apifon's REST API generates ETags for resources which are transmitted back to the client in the meta field.

    "meta": { "Etag": "9b914344475f6b31beec7a4decb5d93d" }

    ETags can be used for cache management and for preventing simultaneous updates of a resource from overwriting each other.

    For further information on how to use entity tags refer to the MDN Entity Tag documentation or to the API examples

    Authentication

    To make use of the REST API, you must supply with each request an authorization token in the HTTP header. The token (ApifonWS) at this point will be generated automatically through Apifon’s Service Control Panel (Mookee) and will be given to you via email.

    The Authentication Header

    Authorization: ApifonWS [Token]:[Signature]
    

    Setting Authorization Header Code Example

    import org.apache.http.client.methods.HttpPost;
    
    HttpPost request = new HttpPost();
    
    request.setHeader("Authorization", "ApifonWS " + token + ":" + signature);
    
    $curl = curl_init($url);
    
    $header[] = "Authorization: ApifonWS " . $token . ":" . $signature;
    
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    
    WebRequest webRequest = WebRequest.Create(uri);
    
    webRequest.Headers["Authorization"] = "ApifonWS " + token + ":" + signature;
    
    headers = {
        "Authorization": "ApifonWS %s: %s" % (token, signature),
    }
    
    connection = http.client.HTTPConnection(base_url)
    connection.request(method, endpoint, body, headers)
    
    var request = require('sync-request');
    
    var res = request(method, url, {
        headers: {
            'Authorization': 'ApifonWS ' + token + ":" + signature,
        },
        body: body
    });
    

    The ApifonWS REST API uses the standard HTTP Authorization header to pass authentication information. (The name of the standard header is unfortunate because it carries authentication information, not authorization.) Under the ApifonWS authentication scheme, the Authorization header has the following form:

    When developers register they are issued an ApifonWS token and ApifonWS secret access key. For request authentication, the ApifonWS token element is used to indirectly retrieve the secret key to compute the signature and, thus, identify the developer making the request.

    Authorization Instructions:

    Authorization = "ApifonWS" + " " + Token + ":" + Signature
    
    Signature = Base64( HMAC-SHA256( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) );
    
    StringToSign = HTTP-Verb + "\n"
    + HTTP-Request-Uri + "\n"
    + Content(Body) + "\n"
    + Date
    

    Building Signature Code Example

    import java.io.UnsupportedEncodingException;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.binary.Base64;
    
    public class SignatureGenerator {
    
        public static String getSignature(String secretKey, String method, String uri, String body, String strDate){
            String toSign = method + "\n"
                    + uri + "\n"
                    + body + "\n"
                    + strDate;
            Mac mac = null;
            try {
                byte[] secretyKeyBytes = secretKey.getBytes("UTF-8");
                SecretKeySpec secretKeySpec = new SecretKeySpec(secretyKeyBytes, "HmacSHA256");
                mac = Mac.getInstance("HmacSHA256");
                mac.init(secretKeySpec);
            } catch (Exception ex) {
                System.out.println(ex);
            }
    
            String signature = null;
            byte[] data;
            byte[] rawHmac;
            try {
                    data = toSign.getBytes("UTF-8");
                    rawHmac = mac.doFinal(data);
                    Base64 encoder = new Base64();
                    signature = new String(encoder.encode(rawHmac));
            } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException("UTF-8 is unsupported!", e);
            }
            return signature;
        }
    
    }
    
    $message = $method."\n"
                    . $endpoint . "\n"
                    . $body . "\n"
                    . $requestDate;
    
    
    $signature = base64_encode(hash_hmac('SHA256', $message, $secretKey, true));
    
    
    using System;
    using System.Security.Cryptography;
    
    namespace Apifon
    {
        class SignatureGenerator
        {
            public static string hmac(string secretKey, string method, string uri, string body, string strDate)
            {
                string toSign = method + "\n"
                        + uri + "\n"
                        + body + "\n"
                        + strDate;
    
                var encoding = new System.Text.UTF8Encoding();
                byte[] keyByte = encoding.GetBytes(secretKey);
                byte[] messageBytes = encoding.GetBytes(toSign);
                using (var hmacsha256 = new HMACSHA256(keyByte))
                {
                    byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                    return Convert.ToBase64String(hashmessage);
                }
            }
        }
    }
    
    import base64
    import hashlib
    import hmac
    
    
    def sign(method, endpoint, body, request_date, secretKey):
        try:
            signed_message = method + "\n" + endpoint + "\n" + body + "\n" + request_date
            encode = hmac.new(bytes(secretKey.encode("utf-8")), bytes(signed_message.encode("utf-8")), hashlib.sha256).digest()
            signature = base64.b64encode(encode).decode()
            return signature
        except Exception as e:
            print(str(e))
    
    var message = method + "\n"
                 + endpoint + "\n"
                 + body + "\n"
                 + requestDate;
    
    var signature = crypto.createHmac('sha256', secretKey).update(message).digest('base64');
    

    The Signature element is the RFC 2104 HMAC-SHA256 of selected elements from the request, meaning that the Signature part of the Authorization header will vary from request to request. If the request signature calculated by the system matches the Signature included with the request, the requester will have demonstrated possession of the ApifonWS secret access key. The request will then be processed under the identity, and with the authority of the developer to whom the key was issued.

    Following is a pseudogrammar that illustrates the construction of the Authorization request header. (In the example, \n means the Unicode code point U+000A, commonly called newline).

    HMAC-SHA256 is an algorithm defined by RFC 2104 – Keyed-Hashing for Message Authentication . The algorithm takes as input two byte-strings, a key and a message. For ApifonWS request authentication, use your ApifonWS secret access key (YourSecretAccessKeyID) as the key, and the UTF-8 encoding of the StringToSign as the message. The output of HMAC-SHA256 is also a byte string, called the digest. The Signature request parameter is constructed by Base64 encoding this digest.

    Request Canonicalization for Signing

    Recall that when the system receives an authenticated request, it compares the computed request signature to the signature provided by the StringToSign of the request. For that reason, you must compute the signature by using the same method used by ApifonWS. We call the process of putting a request in an agreed-upon form for signing canonicalization.

    String to sign empty Elements

    If a StringToSign element called for in the definition of StringToSign is not present in your request (for example, Content are optional for PUT requests and meaningless for GET requests), substitute the empty string (“”) for that position.

    Time Stamp Requirement

    Building Timestamp Header Code Example

    HttpPost request = new HttpPost();
    
    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    String strDate = dateFormat.format(new Date());
    
    request.setHeader("X-ApifonWS-Date", strDate);
    
    $dateTime = new \DateTime();
    $dateTime->setTimezone(new \DateTimeZone('GMT'));
    $requestDate = $dateTime->format('D, d M Y H:i:s T');
    
    $header[] = "X-ApifonWS-Date: " . $requestDate;
    
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    
    String strDate = DateTime.Now.ToUniversalTime().ToString("r");
    
    WebRequest webRequest = WebRequest.Create(uri);
    
    webRequest.Headers["X-ApifonWS-Date"] = strDate;
    
    request_date = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
    
    headers = {
        "X-ApifonWS-Date": request_date
    }
    
    connection = http.client.HTTPConnection(base_url)
    connection.request(method, endpoint, body, headers)
    
    var d = new Date();
    var dateTime = d.toUTCString();
    var requestDate = dateTime;
    
    var request = require('sync-request');
    
    var res = request(method, url, {
        headers: {
            'X-ApifonWS-Date': requestDate
        },
        body: body
    });
    

    A valid time stamp (use only an X-ApifonWS-Date header) is mandatory for authenticated requests. Furthermore, the client timestamp included with an authenticated request must be within 15 minutes of the ApifonWS system time when the request is received. If not, the request will fail with the Unauthorized (or 401 Unauthorized Access) error code. The intention of these restrictions is to limit the possibility that intercepted requests could be replayed by an adversary. For stronger protection against eavesdropping, use the HTTPS transport for authenticated requests.

    You can set the timestamp for the request by using an ‘X-ApifonWS-Date’ header. The value of the X-ApifonWS-Date header must be in one of the RFC 2616 formats (http://www.ietf.org/rfc/rfc2616.txt). See the next section for an example.

    Authentication Examples

    Setting Authorization Header Code Example

    import org.apache.http.client.methods.HttpPost;
    
    HttpPost request = new HttpPost();
    
    request.setHeader("Authorization", "ApifonWS " + token + ":" + signature);
    
    $curl = curl_init($url);
    
    $header[] = "Authorization: ApifonWS " . $token . ":" . $signature;
    
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    
    WebRequest webRequest = WebRequest.Create(uri);
    
    webRequest.Headers["Authorization"] = "ApifonWS " + token + ":" + signature;
    
    headers = {
        "Authorization": "ApifonWS %s: %s" % (token, signature),
    }
    
    connection = http.client.HTTPConnection(base_url)
    connection.request(method, endpoint, body, headers)
    
    var request = require('sync-request');
    
    var res = request(method, url, {
        headers: {
            'Authorization': 'ApifonWS ' + token + ":" + signature,
        },
        body: body
    });
    

    The examples in this section use the (non-working) credentials in the following table.

    Parameter Value Description
    Token 5b5a6ca0deb4bdba5bab An alphanumeric sequence that is used to reference to the user Account a is making the Request.
    Secret Key YourSecretKey A character sequence used to validate the identity of the Requester.

    In the example StringToSign, formatting is not significant, and \n means the Unicode code point U+000A, commonly called newline. Also, the examples use “+0000” to designate the time zone. You can use “GMT” to designate timezone instead, but the signatures shown in the examples will be different.

    Example Object POST

    Request

    Method: POST
    
    Endpoint: /services/sms/send
    
    Content-Type: application/json
    
    Content-Length: 12
    
    Host: ars.apifon.com
    
    X-ApifonWS-Date: Sun, 22 Feb 2016 21:29:42 +0000
    
    Authorization: ApifonWS 5b5a6ca0deb4bdba5bab:YourSecretKey 
    

    StrToSign

    POST \n
    
    /services/sms/send \n
    
    {subscribers:{...}, message:{...}, ...} \n
    
    Sun, 22 Feb 2016 21:29:42 +0000
    

    Complete Request Example

    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    import java.util.TimeZone;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.HttpClientBuilder;
    
    public class HttpRequest {
    
        public static void main(String[] args) throws URISyntaxException, IOException {
            String token = "5b5a6ca0deb4bdba5bab";
            String secretKey = "YourSecretKey";
            String endpoint = "/services/balance";
            String body = "";
    
            StringEntity input = new StringEntity(body, "UTF-8");
            input.setContentType("application/json");
    
            HttpPost request = new HttpPost();
            request.setEntity(input);
            request.setURI(new URI("https://ars.apifon.com" + endpoint));
    
            SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
            dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
            String strDate = dateFormat.format(new Date());
    
            HttpClient httpClient = HttpClientBuilder.create().build();
            URI tmUri = new URI(endpoint);
    
            String signature = SignatureGenerator.getSignature(secretKey, "POST", tmUri.getPath(), body, strDate);
            request.setHeader("Content-Type", "application/json");
            request.setHeader("Authorization", "ApifonWS " + token + ":" + signature);
            request.setHeader("X-ApifonWS-Date", strDate);
    
            HttpResponse response = httpClient.execute(request);
        }
    }
    
    <?php
    
    $token = "5b5a6ca0deb4bdba5bab";
    $secretKey = "YourSecretKey";
    $endpoint = "/services/balance";
    $body = "";
    $url = "https://ars.apifon.com" . $endpoint;
    
    $dateTime = new \DateTime();
    $dateTime->setTimezone(new \DateTimeZone('GMT'));
    $requestDate = $dateTime->format('D, d M Y H:i:s T');
    
    $message = "POST"."\n"
    . $endpoint . "\n"
    . $body . "\n"
    . $requestDate;
    
    $signature = base64_encode(hash_hmac('SHA256', $message, $secretKey, true));
    
    $header = array();
    $header[] = "Content-type: application/json";
    $header[] = "Authorization: ApifonWS " . $token . ":" . $signature;
    $header[] = "X-ApifonWS-Date: " . $requestDate;
    
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
    
    $response = curl_exec($curl);
    
    using System;
    using System.Security.Cryptography;
    using System.IO;
    using System.Net;
    using System.Text;
    
    namespace Apifon
    {
        class HttpRequest
        {
            static void Main(string[] args)
            {
                String token = "5b5a6ca0deb4bdba5bab";
                String secretKey = "YourSecretKey";
                String body = "";
                String uri = "https://ars.apifon.com/services/balance";
                String strDate = DateTime.Now.ToUniversalTime().ToString("r");
    
                byte[] data = Encoding.UTF8.GetBytes(body);
                WebRequest webRequest = WebRequest.Create(uri);
    
                Uri tmpUri = new Uri(uri);
                webRequest.Method = "POST";
                webRequest.ContentType = "application/json";
                webRequest.ContentLength = data.Length;
                string toSign = "POST" + "\n"
                    + tmpUri.AbsolutePath + "\n"
                    + body + "\n"
                    + strDate;
                string signature;
                var encoding = new UTF8Encoding();
                byte[] messageBytes = encoding.GetBytes(toSign);
                using (var hmacsha256 = new HMACSHA256(encoding.GetBytes(secretKey)))
                {
                    signature = Convert.ToBase64String(hmacsha256.ComputeHash(messageBytes));
                }
                webRequest.Headers["X-ApifonWS-Date"] = strDate;
                webRequest.Headers["Authorization"] = "ApifonWS " + token + ":" + signature;
                using (Stream stream = webRequest.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
    
                string responseContent = null;
                using (WebResponse response = webRequest.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader sr99 = new StreamReader(stream))
                        {
                            responseContent = sr99.ReadToEnd();
                        }
                    }
                }
                Console.WriteLine(responseContent);
            }
        }
    }
    
    import json
    import base64
    import hashlib
    import hmac
    import http.client
    from datetime import datetime, timezone
    
    request_date = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
    
    token = "5b5a6ca0deb4bdba5bab"
    secretKey = "YourSecretKey"
    uri = "ars.apifon.com"
    endpoint = "/services/balance"
    body = ""
    
    signed_message = "POST" + "\n" + endpoint + "\n" + body + "\n" + request_date
    
    encode = hmac.new(bytes(secretKey.encode("utf-8")), bytes(signed_message.encode("utf-8")), hashlib.sha256).digest()
    signature = base64.b64encode(encode).decode()
    
    headers = {
        "Content-type": "application/json",
        "Authorization": "ApifonWS %s: %s" % (token, signature),
        "X-ApifonWS-Date": request_date
    }
    
    try:
        connection = http.client.HTTPConnection(uri)
        connection.request("POST", endpoint, body, headers)
    except Exception as e:
        print(str(e))
    t = json.loads(connection.getresponse().read().decode('utf8'))
    print(t)
    
    
    var token = "5b5a6ca0deb4bdba5bab";
    var secretKey = "YourSecretKey";
    var endpoint = "/services/balance";
    var body = "";
    var url = "https://ars.apifon.com" + endpoint;
    
    var requestDate = new Date().toUTCString();
    
    var message = "POST" + "\n"
            + endpoint + "\n"
            + body + "\n"
            + requestDate;
    
    const crypto = require('crypto');
    var signature = hmac = crypto.createHmac('sha256', secretKey).update(message).digest('base64');
    
    var request = require('sync-request');
    var res = request("POST", url, {
        headers: {
            'Content-type': 'application/json',
            'Authorization': 'ApifonWS ' + token + ":" + signature,
            'X-ApifonWS-Date': requestDate,
        },
        body: body
    });
    return JSON.parse(res.getBody('utf8'));
    

    This example sends an SMS request with the POST method.

    REST Request Signing Problems

    When REST request authentication fails, the system responds to the request with an 401 Unauthorized Error.

    Some toolkits silently insert headers that you do not know about beforehand, such as adding the header Content-Type during a POST. In most of these cases, the value of the inserted header remains constant, allowing you to discover the missing headers by using tools such as Ethereal or tcpmon.

    Using Base64 Encoding

    HMAC request signatures must be Base64 encoded. Base64 encoding converts the signature into a simple ASCII string that can be attached to the request.