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 our REST APIs, Query Parameters have to be URL encoded 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 parameters in 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 er ror "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  (URL encoded) 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%22Test%20Link%20Name%22%2C%22sourceApp%22%3A%22App%20Name%22%2C%22access%22%3A%7B%22type%22%3A%22OpenForAll%22%7D%2C%22scheduleType%22%3A%22AlwaysOn%22%2C%22testGradedNotificationUrl%22%3A%22https%3A%2F%2Fwww.application.com%2Fpath%2Fpost_call_listener%22%7D

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  ,   sc  and   ts  in order, for this example)
String-to-Sign = "POST" + "https://api.mettl.com/v2/assessments/999999/schedules" + "\n" + "ab12c345-6789-0123-456d-78e9f0123456" + "\n" + "{"name":"Test Link Name","sourceApp":"App Name","access":{"type":"OpenForAll"},"scheduleType":"AlwaysOn","testGradedNotificationUrl":"https://www.application.com/path/post_call_listener"}" + "\n" + "1635976200"
c. Output of the  Sting-to-Sign created above
ab12c345-6789-0123-456d-78e9f0123456
{"name":"Test Link Name","sourceApp":"App Name","access":{"type":"OpenForAll"},"scheduleType":"AlwaysOn","testGradedNotificationUrl":"https://www.application.com/path/post_call_listener"}
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)
bwWR7GZLgOPR23DqLzWS47lKwBxCEFKDAlHmdr43pgo%3D

Request with Signature
f. Final   POST  request URL with queries   ak  ,   ts  ,   sc  (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%22Test%20Link%20Name%22%2C%22sourceApp%22%3A%22App%20Name%22%2C%22access%22%3A%7B%22type%22%3A%22OpenForAll%22%7D%2C%22scheduleType%22%3A%22AlwaysOn%22%2C%22testGradedNotificationUrl%22%3A%22https%3A%2F%2Fwww.application.com%2Fpath%2Fpost_call_listener%22%7D&asgn=bwWR7GZLgOPR23DqLzWS47lKwBxCEFKDAlHmdr43pgo%3D


2) Sample Signature Generation for  Register Candidates in Schedule API
Request without Signature
a.   POST  request URL, with queries   ak  ,   ts  and   rd  (URL encoded) 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%22Name%22%2C%22Email%20Address%22%3A%22name%40email.com%22%7D%5D%7D

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  ,   rd  and   ts  in order, for this example)
String-to-Sign = "POST" + "https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates" + "\n" + "ab12c345-6789-0123-456d-78e9f0123456" + "\n" + "{"registrationDetails":[{"First Name":"Name","Email Address":"name@email.com"}]}" + "\n" + "1635976200"
c. Output of the  Sting-to-Sign created above
ab12c345-6789-0123-456d-78e9f0123456
{"registrationDetails":[{"First Name":"Name","Email Address":"name@email.com"}]}
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)
t72%2BcLqiOZPD4qIKLuabKh2czEebF6ELG8kZt%2F4HPRQ%3D

Request with Signature
f. 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%22Name%22%2C%22Email%20Address%22%3A%22name%40email.com%22%7D%5D%7D&asgn=t72%2BcLqiOZPD4qIKLuabKh2czEebF6ELG8kZt%2F4HPRQ%3D


3) Sample Signature Generation for Get Result of Candidate in Schedule API
Request without Signature
a.  GET request URL, with queries   ak   ts  ,   ir  (URL encoded) ,   rs  ,   qr  but without   asgn  (Signature)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates/name@email.com?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&ir=%7B%22recommendation%22%3Atrue%7D&rs=true&qr=true

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  ,   ir  ,   qr  ,   rs  and   ts  in order, for this example)
String-to-Sign = "GET" +  "https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates/name@email.com"  + "\n" + "ab12c345-6789-0123-456d-78e9f0123456"  + "\n" + "{"recommendation":true}" + "\n" + "true" + "\n" + "true" + "\n" + "1635976200"
c. Output of the  Sting-to-Sign created above
ab12c345-6789-0123-456d-78e9f0123456
{"recommendation":true}
true
true
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)
lR1lOIUIAa23E2vFoZjZaoZu26AuJ7GDdSy7Ef0aT20%3D

Request with Signature
f. Final   GET  request URL with queries   ak  ,   ts  ,   ir  (URL encoded) ,   rs  ,   qr  and   asgn  (URL Encoded)
https://api.mettl.com/v2/schedules/0x0x0x0x0x/candidates/name@email.com?ak=ab12c345-6789-0123-456d-78e9f0123456&ts=1635976200&ir=%7B%22recommendation%22%3Atrue%7D&rs=true&qr=true&asgn=lR1lOIUIAa23E2vFoZjZaoZu26AuJ7GDdSy7Ef0aT20%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