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 generate a signature that you send with your data. On receipt, the incoming webhook contains the signature and all the fields you need to create the signature in your application in order to check that the two signatures match and that the webhook is therefore correct.

This signature can be used to 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 must contain certain data such as the timestamp, the target URL, a nonce and the data sent.


Structure of the signature

The following data is required to create a signature:

valuedescription
NonceA random string consisting of 32 alphanumeric characters. This must be unique for each request.
TimestampThe time of the request as a Unix timestamp, must not be more than 30 seconds in the past
HTTP methodThe HTTP request method, e.g. POST or GET
Target URLThe complete URL to which the request is sent
Content of the requestMD5 hash of the content of the request

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 character string to be signed

The string to be signed must be structured as follows:

STRING_TO_SIGN =
  Timestamp + \n +
  Nonce + \n +
  HTTP method + \n +
  TargetURL + \n + 
  ContentBodyMD5

For example, if you send this request:

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

{"to": "49170123456789", "text": "Hello World! :-)", "from": "seven"}

The string to be signed would be structured as follows:

STRING_TO_SIGN =
  1634641200
  fpPRhAd1s8GXacfR39mWqKPynmmXfJnc
  POST
  https://gateway.seven.io/api/sms
  62dd06ffb3101dc2456517b177b744ae
valueexplanation
1634641200The current timestamp at the time the request was sent, here 19.10.2021 at 13:00:00
fpPRhAd1s8GXacfR39mWqKPynmmXfJncA randomly generated string with 32 characters
POSTThe HTTP method used
https://gateway.seven.io/api/smsThe destination URL
62dd06ffb3101dc2456517b177b744aeMD5( {"to": "49170123456789", "text": "Hello World! :-)", "from": "seven"} )

Creation of the signature

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

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

Similar implementations are available in most common programming languages, such as PHP:

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

Sending the signature

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

  • Name
    X-Signature
    Type
    string
    Description

    The signature generated by you

  • Name
    X-Timestamp
    Type
    integer
    Description

    The timestamp at which the signature was created

  • Name
    X-Nonce
    Type
    string
    Description

    The nonce you created


Examples

Bash Script with curl and openssl

#!/bin/bash

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

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

# Timestamp
TIMESTAMP=$(date +%s)

# Data of the request
HTTP_VERB="POST"
URL="https://gateway.seven.io/api/sms"
CONTENT_BODY="{ \"to\": \"0170123456789\", \"text\": \"Hello World! :-)\", \"from\": \"seven.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 a 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' => 'seven.io',
]);

$url = 'https://gateway.seven.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 header
$headers = [
  'X-Signature: ' . $hash,
  'X-Api-Key: ' . $key,
  'X-Timestamp:' . $timestamp,
  'X-Nonce:' . $nonce,
  'Content-type: application/json',
  'Accept: application/json'
];

# Send 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;