1. Home
  2. Gateway
  3. HTTP API
  4. Signing of requests

Signing of requests

For additional security, you can use signatures for all requests to and from our API. The use of signatures is optional. However, if a signature is sent, it must be valid. When sending requests to our API, you create a signature to send with your data. When you receive it, the incoming webhook contains the signature and all the fields you need to create the signature in your application to verify that the two signatures match and that the webhook is correct. By means of this signature you can ensure that

  • the request actually comes from the correct source,
  • the request has not been falsified en route,
  • requests are not intercepted and repeated later.

The signature contains mandatory data such as the timestamp, the destination URL, a so-called nonce and the sent data.

Structure of the signature

The following data is required to create a signature:

Value Description
Nonce A random string consisting of 32 alphanumeric characters. This must be unique for each request.
Timestamp The time of the request as a Unix timestamp, must not be older than 30 seconds
HTTP Method The HTTP request method, e.g. POST or GET
Destination URL The full URL to which the request is sent
Content of the request MD5 hash of the request content

To generate the signature, the SHA256 HMAC algorithm is used with the signing key of your account. You can find the key in your login in the developer area in the API settings.

Structure of the string to be signed

The string to be signed must be structured as follows:

STRING_TO_SIGN =
 Timestamp + \n +
 Nonce + \n +
 HTTPMethod + \n +
 DestinationURL + \n + 
 ContentBodyMD5

Example request

POST https://gateway.sms77.io/api/sms

{ "to": "49170123456789", "text": "Hello World! :-)", "from": "sms77.io" }

The string to be signed would be structured as follows:

STRING_TO_SIGN =
  1634641200
  fpPRhAd1s8GXacfR39mWqKPynmmXfJnc
  POST
  https://gateway.sms77.io/api/sms
  62dd06ffb3101dc2456517b177b744ae
Value Explanation
1634641200 the current timestamp at the time the request was sent, in this case 10/19/2021 at 13:00:00
fpPRhAd1s8GXacfR39mWqKPynmmXfJnc a randomly generated string with 32 characters
POST the HTTP method used
https://gateway.sms77.io/api/sms the destination URL
62dd06ffb3101dc2456517b177b744ae MD5( { “to”: “49170123456789”, “text”: “Hello World! :-)”, “from”: “sms77.io” } )

Creating the signature

Now to create the signature, use SHA256 HMAC algorithm in conjunction with signing key of your account.

printf "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "${SIGNING_SECRET}"

Similar implementations are given in most common programming languages, for example in PHP:

$signature = hash_hmac('sha256', $STRING_TO_SIGN, $SIGNING_SECRET);

Sending the signature

The signature, nonce and timestamp must be sent in the HTTP headers of the request.

Header Explanation
X-Signature The signature you generated
X-Timestamp The timestamp at which the signature was generated
X-Nonce The nonce you created

In case of an error, if we cannot match the signature, the timestamp is too old or the nonce/signature has already been sent, you will receive the HTTP code 401 and a more detailed description of the error in the response to your request.

Examples

Bash script with curl and openssl:

#!/bin/bash

# Your API data
API_KEY="YOUR_API_KEY"
SIGNING_SECRET="YOUR_SIGN_KEY"

# Create random nonce
NONCE=$(openssl rand -hex 32)

# timestamp
TIMESTAMP=$(date +%s)

# data of the request
HTTP_VERB="POST
URL="https://gateway.sms77.io/api/sms"
CONTENT_BODY="{ \"to\": \"0170123456789\", \"text\": \"Hello World! :-)\", \"from\": \"sms77.io\" }"

# create signature
CONTENT_BODY_MD5=$(printf "${CONTENT_BODY}" | md5sum | awk '{print $1}')
STRING_TO_SIGN=$(printf "${TIMESTAMP}\n${NONCE}\n${HTTP_VERB}\n${URL}\n${CONTENT_BODY_MD5}")
SIGNATURE=$(printf "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "${SIGNING_SECRET}" | sed 's/^.*= //')

# send request
curl -X $HTTP_VERB $URL \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Nonce: $NONCE" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE" \
  -H "Content-type: application/json" \
  -H "Accept: application/json" \
  -d "${CONTENT_BODY}"

PHP Script:

# Your API data
$key = 'YOUR_API_KEY';
$secret = 'YOUR_SIGN_KEY';

# Create random nonce 
$nonce = bin2hex(random_bytes(16)) 

# timestamp
$timestamp = time();

# data of the request
$http_verb = 'POST';

$content_body = json_encode([
  'to' => '49170123456789',
  'text' => 'Hello World! :-)',
  'from' => 'sms77.io',
]);

$url = 'https://gateway.sms77.io/api/sms';

# create signature
$StringToSign = $timestamp . "\n" .
  $nonce . "\n" .
  $http_verb . "\n" .
  $url . "\n" .
  md5($content_body);

$hash = hash_hmac('sha256', $StringToSign, $secret);

# set headers
$headers = [
  'X-Signature: ' . $hash,
  'X-Api-Key: ' . $key,
  'X-Timestamp: ' . $timestamp,
  'X-nonce:' . $nonce,
  'Content-type: application/json' ,
  'Accept: application/json'
];

# Submit request
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $content_body);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);

echo $result;

Webhooks

Analogous to the way described above, we send webhooks to your server appropriately signed with your account’s signing key. We send you the following headers in each webhook:

Header Explanation
X-Signature The signature we generate
X-Timestamp Timestamp at which the signature was generated by us
X-Nonce Randomly generated string of 32 characters

Based on this data, you can validate the authenticity of the requests from us in each received webhook.