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:
- URL:
{
"service_id": 123,
"service_params": {
"mobile_number": "01234567890"
}
}
-
Signature Creation
- Generate timestamp in the format (YYYYMMDDTHHmm) (i.e: 10:08 pm, 21st of May 2022 will be
20220521T2208
). Timestamp must be in UTC timezone. - Concatenate each of the following in one string:
- Request HTTP Method (GET/POST/..etc)
- Endpoint url (without the domain) (i.e:
/api/v1/endpoint
) - Your
Public key
- Timestamp generated in step #1
- Service ID (add this in case of
/inquiry/
,/fees_inquiry/
and/payment/
only, otherwise skip this step) - Unique UUID that will act as Nonce
- Generate HMAC signature using your
Secret key
withSHA256
hashing - Join the below with
.
in one string:- Your
Public key
- Timestamp
- Generated hex signature
- Nonce (The generated UUID in step #6)
- Your
- Base64 encode the string generated in step #4
- Send the full string in
Authorization
header with every request
- Generate timestamp in the format (YYYYMMDDTHHmm) (i.e: 10:08 pm, 21st of May 2022 will be
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);
}