Localization

For all requests, the client should provide the header Accept-Language describing the language requested in the response, the allowed values for now are ar for Arabic and en for English. Arabic is the default language if not specified.

Authentication

Signature

For all requests, a signature must be created and added to Authorization header

Procedure

  • First, request API public key and secret key for your account
  • For a given request having the following details (examples are for explanation, replace with your actual payload and endpoint):
    • URL: https://example.com/api/v1/endpoint/
    • Payload:
{
  "service_id": 123,
  "service_params": {
    "mobile_number": "01234567890"
  }
}
  • Signature Creation

    1. Generate timestamp in the format (YYYYMMDDTHHmm) (i.e: 10:08 pm, 21st of May 2022 will be 20220521T2208). Timestamp must be in UTC timezone.
    2. Concatenate each of the following in one string:
      1. Request HTTP Method (GET/POST/..etc)
      2. Endpoint url (without the domain) (i.e: /api/v1/endpoint)
      3. Your Public key
      4. Timestamp generated in step #1
      5. Service ID (add this in case of /inquiry/, /fees_inquiry/ and /payment/ only, otherwise skip this step)
      6. Unique UUID that will act as Nonce
    3. Generate HMAC signature using your Secret key with SHA256 hashing
    4. Join the below with . in one string:
      1. Your Public key
      2. Timestamp
      3. Generated hex signature
      4. Nonce (The generated UUID in step #6)
    5. Base64 encode the string generated in step #4
    6. Send the full string in Authorization header with every request

Code Snippets

Below are code snippets with some commonly used languages

Python

import base64
import hashlib
import hmac
import uuid
from datetime import datetime

TIMESTAMP_FMT = "%Y%m%dT%H%M"


def create_header(request_method, url, secret_key, public_key, payload):
    """
    Generate authorization header using HMAC signature

    :param request_method: HTTP Method (i.e: GET/POST)
    :param url: endpoint without domain (i.e: /api/v1/inquiry/)
    :param secret_key: User secret key
    :param public_key: User Public Key
    :param payload: dict: request payload
    :return: header to be used as value for request Authorization
    """
    timestamp = datetime.utcnow().strftime(TIMESTAMP_FMT)
    nonce = str(uuid.uuid4())
    signature_string = (
            request_method + url + public_key + timestamp + payload.get("service_id", "") + nonce
    )
    h = hmac.new(
        secret_key.encode(),
        signature_string.encode(),
        digestmod=hashlib.sha256,
    )
    signature = h.hexdigest()
    header = ".".join([public_key, timestamp, signature, nonce])
    header = base64.b64encode(header.encode()).decode()
    return header

Kotlin

fun createAuthorizationToken(method: String, apiLink: String): String {
    val publicKey = BuildConfig.BILLS_PUBLIC_KEY
    val privateKey = BuildConfig.BILLS_PRIVATE_KEY
    val dateFormat = SimpleDateFormat("yyyyMMdd'T'HHmm", Locale.ENGLISH)
    dateFormat.timeZone = TimeZone.getTimeZone("GMT")
    val currentDate = Date()
    val nonce = UUID.randomUUID()
    val signatureString = method + apiLink + publicKey + dateFormat.format(currentDate) + nonce
    val hMacSHA256 = Mac.getInstance("HmacSHA256")
    val secretKey = SecretKeySpec(privateKey.toByteArray(), "HmacSHA256")
    hMacSHA256.init(secretKey)
    val signature: String =
        Hex.bytesToHexString(hMacSHA256.doFinal(signatureString.toByteArray())).lowercase()
    val header: String =
        publicKey + "." + dateFormat.format(currentDate) + "." + signature + "." + nonce
    return Base64.encodeToString(header.toByteArray(), Base64.NO_WRAP)
}

C#

using System;
using System.Security.Cryptography;
using System.Text;

public class AuthorizationHandler
{
    public static string CreateHeader(string requestMethod, string url, string secretKey, string publicKey, string serviceId)
    {
        string timestamp = DateTime.UtcNow.ToString("yyyyMMddTHHmm");
        string nonce = Guid.NewGuid().ToString("N");
        string signatureString = requestMethod + url + publicKey + timestamp + (serviceId ?? "") + nonce;

        byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
        byte[] signatureStringBytes = Encoding.UTF8.GetBytes(signatureString);

        using (var hmac = new HMACSHA256(secretKeyBytes))
        {
            byte[] hmacSignatureBytes = hmac.ComputeHash(signatureStringBytes);
            string hmacSignature = BitConverter.ToString(hmacSignatureBytes).Replace("-", "").ToLower();

            string header = $"{publicKey}.{timestamp}.{hmacSignature}.{nonce}";
            byte[] headerBytes = Encoding.UTF8.GetBytes(header);

            return Convert.ToBase64String(headerBytes);
        }
    }
}

Node.js

const crypto = require('crypto');

const TIMESTAMP_FMT = "yyyyMMddTHHmm";

function createHeader(requestMethod, url, secretKey, publicKey, payload) {
    const timestamp = new Date().toISOString().slice(0, -5).replace(/[-:]/g, "");
    const nonce = crypto.randomBytes(16).toString("hex");
    const signatureString = requestMethod + url + publicKey + timestamp + (payload["service_id"] || "") + nonce;
    const hmacSignature = crypto.createHmac('sha256', secretKey).update(signatureString).digest('hex');
    const header = `${publicKey}.${timestamp}.${hmacSignature}.${nonce}`;
    return Buffer.from(header).toString("base64");
}

PHP


date_default_timezone_set("UTC");
define('TIMESTAMP_FMT', 'Ymd\THis');

function createHeader($requestMethod, $url, $secretKey, $publicKey, $payload) {
    $timestamp = date(TIMESTAMP_FMT);
    $nonce = bin2hex(random_bytes(16));
    $signatureString = $requestMethod . $url . $publicKey . $timestamp . ($payload["service_id"] ?? "") . $nonce;
    $hmacSignature = hash_hmac('sha256', $signatureString, $secretKey, true);
    $signature = strtolower(bin2hex($hmacSignature));
    $header = "$publicKey.$timestamp.$signature.$nonce";
    return base64_encode($header);
}