API Authentication and Signature Generation

API Authentication and Signature Generation

Authentication Parameters

When accessing Mettl Examine platform using a REST API request, you must always provide 3 mandatory query parameters, i.e.,  ak   ts  and  asgn , so that the request can be authenticated.

In REST APIs, all Query Parameters have to be URL encoded. The same logic follows for our REST APIs where all the query parameters have to be URL encoded in your code before the request is sent as the data is being transmitted in the request URL.

This is especially important for the  asgn  parameter and any parameters with JSON as they always contain characters that need to be URL encoded. Since  ak  and  ts  parameters don't contain any characters that need to be URL encoded, URL encoding of these parameters can be skipped.

Mandatory Parameters


Query Parameter


Description

ak

This is your Public-API-Key, which Mettl uses to identify your account.

Unsuccessful authentication results in rejection of the request with Error: Access denied. The API key is not authorized for requested resource/action (E403)

ts

This is the current UNIX or Epoch Timestamp (the number of seconds between 1970-01-01 00:00:00 and current UTC Time). Any current geneTimestamp generated will be valid for 24 hours only.

Unsuccessful validation results in rejection of the request with Error: Invalid Timestamp (E504)

asgn

This is a unique Signature which has to be generated for each API request.

The Signature is generated by creating a String-to-Sign and hashing it with your Private-API-Key using the HMAC-SHA256 (for version v2 and v3) or HMAC-SHA1 (for v1) hashing algorithm with Base-64 and URL encoding.

Read more about the Signature Generation Process in the following sections.

Unsuccessful authentication results in rejection of the request with Error: Authentication failed/Signature Mismatch (E401)


Authentication Process

Following is the series of tasks required to authenticate requests to Mettl using an HMAC-SHA request signature.
You perform the first 4 tasks
1.
Construct a request
2.
Generate signature
3.
Include signature in the request
4.
Send request to Mettl

Mettl does the remaining
5.
Checks if Timestamp is in valid format and and within past 24 hours of the current Epoch or UNIX Time
6.
Checks Public API Key and retrieves the corresponding private API key in Mettl
7.
Recalculates the signature using your request and private API key
8.
Compares the 2 signatures

Signature Generation

You can calculate the signature to be sent with the  asgn  parameter in an API Request using these 2 steps: 

1.  Creating a String-to-Sign

Create a String-to-Sign according to the following pseudo-code sample format:
String-to-Sign = Http-Method + API-Endpoint + "\n" + QueryValue1 + "\n" + QueryValue2 + "\n" + QueryValue3 + ....... + "\n" + QueryValueN
where,
  1. Http-Method is the request method of your call such as "GET" or "POST".
  2. API-Endpoint is the API Endpoint URL such as "https://api.mettl.com/v2/account" or "https://api.mettl.com/v2/assessments/{Assessment_Id}/schedules".
  3. "\n" is the New Line Feed character. Alternatively, you can also use the ASCII character 10 in the string.
  4. QueryValue1 to QueryValueN is the value of each query parameter in your API call (including  ak   ts ) sorted in ascending order according to the name of the query parameters.

For example, lets check out the String-to-Sign for a sample  GET  request (Get All Assessments API).

Request without Signature
a. GET request URL, with queries  ak   ts  and  limit  (optional) but without  asgn  (Signature)
https://api.mettl.com/v2/assessments?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&limit=40

Signature Generation Process
b. Creating a String-to-Sign, calculated with Method + Endpoint + Values of query parametersin new lines and in ascending order of the parameter name (i.e., the new line characters "\n" followed by values of  ak  ,  limit  and  ts  in order, for this example)
String-to-Sign = "GET" +  "https://api.mettl.com/v2/assessments"  + "\n" + "ab12c345-6789-0123-456d-78e9f0123456 + "\n" + "40 + "\n" + "1635976200"
c. Output of the Sting-to-Sign created above
ab12c345-6789-0123-456d-78e9f0123456
40
1635976200

2.  Generating Signature

Encode the message string obtained above using your private API key, with HMAC-SHA256 (for API version v2 and v2) or HMAC-SHA1 (for API v1) algorithm in the below pseudo-code sample format  to obtain the signature :
Signature = URL-Encode ( Base64-Encode ( HMAC-SHA ( String-to-Sign , Private-API-Key ) ) )
where,
  1. String-To-Sign is the output message string calculated in Step 1
  2. Private-API-Key is your private API key
  3. HMAC-SHA is the keyed hashing algorithm to be used for signature generation. Depending on API version you are calling, you have to use either HMAC-SHA256 (for API version v2 and v3) or HMAC-SHA1 (for v1).
  4. Base64-Encode is the method for encoding the output of the key hash in base 64 instead of hex or any other format.
  5. URL-Encode is the method for encoding the string 
Note: The above format could vary a lot between different programming languages and is just a frame of reference as to how the signature is generally generated. Check out this amazing article to find sample code snippets in 17 different languages for generating base 64 encoded hashes using HMAC SHA256.

Continuing on the previous example, lets check out the Signature for same sample request as above.

Request without Signature
a.  GET  request URL, with queries  ak   ts  and  limit  (optional) but without  asgn  (Signature)
https://api.mettl.com/v2/assessments?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&limit=40

Signature Generation Process
b. Creating a String-to-Sign, calculated with Method + Endpoint + Values of query parametersin new lines and in ascending order of the parameter name (i.e., the new line characters "\n" followed by values of  ak  ,  limit  and  ts  in order, for this example)
String-to-Sign = "GET" +  "https://api.mettl.com/v2/assessments + "\n" + "ab12c345-6789-0123-456d-78e9f0123456"  + "\n" + "40"  + "\n" + "1635976200"
c. Output of the Sting-to-Sign created above
ab12c345-6789-0123-456d-78e9f0123456
40
1635976200
d.  Private-API-Key to sign/hash the above Sting-to-Sign using HMAC-SHA256 (since API version is v2)
zy98x765-4321-0987-654w-32v1u0987654
e. Output of the generated Signature for  asgn  using the Sting-to-Sign and your Private-API-Key, hashed with HMAC-SHA256 (Base-64 and URL Encoded)
PTra8Gp5FQU807mKkfwHKKsdiwtELXYscV3gp4nByxI%3D

Request with Signature
f. Final  GET  request URL with queries   ak   ts  ,  limit  and  asgn  (URL Encoded)
https://api.mettl.com/v2/assessments?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&limit=40&asgn=PTra8Gp5FQU807mKkfwHKKsdiwtELXYscV3gp4nByxI%3D

Using the given examples, you can test and troubleshoot the HMAC-SHA function in your own code in case of error "Authentication failed/Signature mismatch." This can be done by calculating the signature of the examples strings (String-to-Sign and Private-API-Key) in your code and checking if the resultant signature matches with the one in our examples.
You can also use freely available tools online for Base64 HMAC-SHA generation and URL encoding to also compare and check the expected signature generation from your code.

Examples

For the purposes of consistency across signatures generated in all examples, the values used for authentication will remain the same. Thus, Public API Key ( ak ) will be "ab12c345-6789-0123-456d-78e9f0123456", Private API Key (used for generating  asgn ) will be "zy98x765-4321-0987-654w-32v1u0987654" and Timestamp ( ts ) will be "1635976200". Note, The API keys here are dummy and Timestamp has expired.


1) Sample Signature Generation for Create Schedule API  
Request without Signature
a.  POST  request URL, with queries  ak  ts  and  sc  (mandatory for this API and URL encoded below) but without  asgn  (Signature)
https://api.mettl.com/v2/assessments/999999/schedules?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&sc=%7B%22name%22%3A%22schedule%20name%22%2C%22sourceApp%22%3A%22app%20name%22%2C%22scheduleType%22%3A%22AlwaysOn%22%2C%22access%22%3A%7B%22type%22%3A%22OpenForAll%22%7D%7D

Signature Generation Process
b. Output of String-to-Sign
ab12c345-6789-0123-456d-78e9f0123456
{"name":"schedule name","sourceApp":"app name","scheduleType":"AlwaysOn","access":{"type":"OpenForAll"}}
1635976200
 c. Private API Key 
zy98x765-4321-0987-654w-32v1u0987654
d. Output of Signature for  asgn  (URL encoded) calculated using HMAC-SHA256 as the API version in URI is v2
mOaySHfwgvSW%2FIjStl5b1UCz0ugsgfNL%2B3vw2QjmbM4%3D

Request with Signature
e. Final  POST  request URL with queries   ak  ts  rd (URL encoded) and  asgn (URL encoded)
https://api.mettl.com/v2/assessments/999999/schedules?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&sc=%7B%22name%22%3A%22schedule%20name%22%2C%22sourceApp%22%3A%22app%20name%22%2C%22scheduleType%22%3A%22AlwaysOn%22%2C%22access%22%3A%7B%22type%22%3A%22OpenForAll%22%7D%7D&asgn=mOaySHfwgvSW%2FIjStl5b1UCz0ugsgfNL%2B3vw2QjmbM4%3D


2) Sample Signature Generation for Register Candidates in Schedule API
Request without Signature
a.  POST  request URL, with queries  ak  ts  and  rd  (mandatory for this API and URL encoded below) but without  asgn  (Signature)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&rd=%7B%22registrationDetails%22%3A%5B%7B%22First%20Name%22%3A%22Sample%22%2C%22Email%20Address%22%3A%22Sample%40Email%22%7D%5D%7D

Signature Generation Process
b. Output of String-to-Sign
ab12c345-6789-0123-456d-78e9f0123456
{"registrationDetails":[{"First Name":"Sample","Email Address":"Sample@Email"}]}
1635976200
 c. Private API Key 
zy98x765-4321-0987-654w-32v1u0987654
d. Output of Signature for  asgn  (URL encoded) calculated using HMAC-SHA256 as the API version in URI is v3
6bkiFYc6WoNHiDQYXd%2FGhH6mLVQhbT4Xfr8XbtpWY68%3D

Request with Signature
e. Final  POST  request URL with queries   ak  ts  rd (URL encoded) and  asgn (URL encoded)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&rd=%7B%22registrationDetails%22%3A%5B%7B%22First%20Name%22%3A%22Sample%22%2C%22Email%20Address%22%3A%22Sample%40Email%22%7D%5D%7D&asgn=6bkiFYc6WoNHiDQYXd%2FGhH6mLVQhbT4Xfr8XbtpWY68%3D


3) Sample Signature Generation for Get Status/Results of All Candidates in Schedule API
Request without Signature
a.  GET  request URL, with queries  ak  ,  ts  ,  limit  ,  offset  ,  sort  ,  sort_order  (Optional) but without  asgn  (Signature)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&limit=10&offset=20&sort=name&sort_order=desc

Signature Generation Process
b. Output of String-to-Sign
ab12c345-6789-0123-456d-78e9f0123456
10
20
name
desc
1635976200
 c. Private API Key 
zy98x765-4321-0987-654w-32v1u0987654
d. Output of Signature for  asgn  (URL encoded) calculated using HMAC-SHA256 as the API version in URI is v3
cTFR3Yyh36vgLyBeO59PnSLEScHBbMR1zR8FAJDytMo%3D

Request with Signature
e. Final  GET  request URL with queries  ak  ,  ts  ,  limit  offset  ,  sort  ,  sort_order  (Optional) and  asgn (URL encoded)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&limit=10&offset=20&sort=name&sort_order=desc&asgn=cTFR3Yyh36vgLyBeO59PnSLEScHBbMR1zR8FAJDytMo%3D


Code Snippets

Node.js - Get All Assessments API
  1. const crypto = require("crypto");
  2. const axios = require("axios");

  3. // Request Variables for - Get All Assessments API
  4. let publicKey = ""; // Enter your Public API Key
  5. let privateKey = ""; // Enter your Private API Key
  6. let httpMethod = "GET";
  7. let apiEndpoint = "https://api.mettl.com/v2/assessments";
  8. let timestamp = Math.floor(new Date().getTime() / 1000);

  9. // Signature Generation Process
  10. // For more details refer https://support.mettl.com/portal/en/kb/articles/api-authentication-and-signature-generation

  11. // Step 1 - Creating a Sting-to-Sign
  12. let stringToSign = httpMethod + apiEndpoint + "\n" + publicKey + "\n" + timestamp;
  13. console.log("String-To-Sign: " + stringToSign);

  14. // Step 2 - Calculating Signature, using HMAC-SHA-256 as the API version is v2, with Base 64 and URL encoding
  15. let signature = encodeURIComponent(crypto.createHmac("SHA256", privateKey).update(stringToSign).digest("base64"));
  16. console.log("Signature: " + signature);

  17. // Full Request URL with Signature
  18. let urlToHit = apiEndpoint + "?ak=" + publicKey + "&ts=" + timestamp + "&asgn=" + signature;
  19. console.log("URL: " + urlToHit);

  20. // Sending the Request
  21. axios.get(urlToHit).then((response) => console.log("Response: " + JSON.stringify(response.data)));

C# - Create Schedule API
  1. using System;
  2. using System.Text;
  3. using System.Web;
  4. using System.Security.Cryptography;
  5. using System.Net.Http;


  6. public class Program {
  7. public static void Main() {
  8. // Request Variables for - Get All Assessments API
  9. string publicKey = "";  // Enter your Public API Key
  10. string privateKey = "";  // Enter your Private API Key
  11. string assessmentId = ""; // Enter the Assessment Id for which a new Schedule or Test Link has to be created
  12. string httpMethod = "POST";
  13. string apiEndpoint = "https://api.mettl.com/v2/assessments/" + assessmentId + "/schedules";
  14. string schedule = "{\"name\":\"Schedule Name\",\"scheduleType\":\"AlwaysOn\",\"access\":{\"type\":\"OpenForAll\"},\"sourceApp\":\"Sample App\"}";
  15. string timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString();

  16. // Signature Generation Process
  17. // For more details refer https://support.mettl.com/portal/en/kb/articles/api-authentication-and-signature-generation

  18. // Step 1 - Creating a Sting-to-Sign
  19. string stringToSign = httpMethod + apiEndpoint + "\n" + publicKey + "\n" + schedule + "\n" + timestamp;
  20. Console.WriteLine("String-To-Sign: " + stringToSign);

  21. // Step 2 - Calculating Signature
  22. string signature = generateSignature(stringToSign, privateKey);
  23. Console.WriteLine("Signature: " + signature);

  24. // Full Request URL with Signature
  25. string urlToHit = apiEndpoint + "?ak=" + publicKey + "&ts=" + timestamp + "&asgn=" + signature + "&sc=" + HttpUtility.UrlEncode(schedule);
  26. Console.WriteLine("URL: " + urlToHit);

  27. // Sending the Request
  28. var httpClient = new HttpClient();
  29. var request = httpClient.PostAsync(urlToHit, null).Result;
  30. string response = request.Content.ReadAsStringAsync().Result;
  31. Console.WriteLine("Response: " + response);    
  32. }
  33. // Signature Calculation Function in C# for Step 2 of the Signature Generation Process above
  34. private static string generateSignature(string message, string secret) {
  35. // Generating signature using HMAC-SHA-256 as the API version is v2, with Base 64 and URL encoding
  36. byte[] hmacSHA256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)).ComputeHash(Encoding.UTF8.GetBytes(message));
  37. string base64Encoded = Convert.ToBase64String(hmacSHA256);
  38. string urlEncoded = HttpUtility.UrlEncode(base64Encoded);
  39. return urlEncoded;
  40. }
  41. }

Python 3 - Register Candidate API
  1. import hashlib
  2. import hmac
  3. import base64
  4. import urllib.parse
  5. import requests
  6. import json
  7. import time

  8. def main():
  9.     # Request Variables for - Register Candidate API
  10.     publicKey = ""  # Enter your Public API Key
  11.     privateKey = ""  # Enter your Private API Key
  12.     accessKey = ""  # Enter the Access Key for the Schedule/ Test Link to which the candidate has to be registered
  13.     httpMethod = "POST"
  14.     apiEndpoint = "https://api.mettl.com/v2/schedules/" + accessKey + "/candidates"
  15.     registrationDetails = '{"registrationDetails":[{"First Name":"Sample","Email Address":"sample@email.com"}]}'
  16.     timestamp = str(int(time.time()))

  17.     # Signature Generation Process
  18.     # For more details refer https://support.mettl.com/portal/en/kb/articles/api-authentication-and-signature-generation

  19.     # Step 1 - Creating a Sting-to-Sign
  20.     stringToSign = httpMethod + apiEndpoint + '\n' + publicKey + '\n' + registrationDetails + '\n' + timestamp
  21.     print("String-To-Sign: " + stringToSign)

  22.     # Step 2 - Calculating Signature
  23.     signature = generateSignature(stringToSign, privateKey)
  24.     print("Signature: " + signature)

  25.     # Full Request URL with Signature
  26.     urlToHit = apiEndpoint + "?ak=" + publicKey + "&ts=" + timestamp + "&asgn=" + signature + "&rd=" + urllib.parse.quote(registrationDetails)
  27.     print("URL: " + urlToHit)

  28.     # Sending the Request
  29.     response=requests.post(urlToHit).json()
  30.     print("Response: " + str(response))


  31. # Signature Calculation Function in python for Step 2 of the Signature Generation Process above
  32. def generateSignature(message, secret):
  33.     # Generating signature using HMAC-SHA-256 as the API version is v2, with Base 64 and URL encoding
  34.     hmcaSHA256 = hmac.new(bytes(secret, 'UTF-8') ,bytes(message, 'UTF-8') , digestmod=hashlib.sha256).digest()
  35.     base64Encoded = str(base64.b64encode(hmcaSHA256),'UTF-8')
  36.     urlEncoded = urllib.parse.quote(base64Encoded)
  37.     return urlEncoded
  38.     
  39. main()

Using the above sample code snippets you can adapt and design the code in your preferred language. For more code snippets in C#, Java, Node.js, PHP and Python, Visit our link https://support.mettl.com/portal/en/kb/articles/code-samples-for-signature-generation-for-mettl-api