Signing requests with X-Signature
All requests must be signed using your API Token and your private Secret Key.
Your string-to-be-signed should always include the ? query parameter delimiter regardless of whether or not there are query string parameters.
GET Requests
To start, you will need to create the string to use in computing the X-Signature string that includes the request method GET, the host name (e.g.api.ticketevolution.com), the path (e.g. /brokerages), and an optional query string that must be sorted by key (e.g. ?page=1&per_page=1).
Seriously, if you do not sort your query string alphabetically by key you will get a 401 error.
Here's what that full string should look like when you put it all together:
GET api.ticketevolution.com/v9/brokerages?page=1&per_page=1
or a request without parameters
GET api.ticketevolution.com/v9/categories?
POST, PUT, and DELETE requests
In the case of POST,PUT and DELETE requests when a request body is present, the request body should be used in the source string in lieu of the query string.
POST api.ticketevolution.com/v9/clients?{"clients":[{"name":"Michael Starr"}]}
Computing the X-Signature
Use our X-Signature Generator to check if the signatures you're making are correct, and generate cURL requests right in the browser.
Once you have created the input string as shown above, it should be hashed using HMAC-SHA256 using your API Secret. Below are some examples of how to compute X-Signature. Some examples for additional languages may be found at http://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/:
Postman
If you are testing via Postman you can use a pre-request script to generate the X-Signature.
const URL = require('url');
URL.parse(pm.variables.replaceIn(pm.request.url).toString());
var reqParams = pm.request.url.query.all();
pm.request.removeQueryParams(reqParams);
pm.request.addQueryParams(reqParams.sort())
const reqUrl = URL.parse(pm.request.url.toString());
var stringToSign = pm.request.method + ' ' + reqUrl.hostname + reqUrl.path;
if (pm.request.body.raw != undefined) {
stringToSign = stringToSign + '?' + pm.request.body;
} else if (reqUrl.query = null) {
stringToSign = stringToSign + '?';
}
var xSignature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(stringToSign, pm.variables.replaceIn('{{apiSecret}}')));
// console.log('reqParams: ' + reqParams);
// console.log('reqUrl: ' + reqUrl.toString());
// console.log('stringToSign: ' + stringToSign);
// console.log('xSignature: ' + xSignature);
pm.request.headers.add({key: 'X-Signature', value: xSignature });
pm.request.headers.add({key: 'X-Token', value: '{{apiToken}}' });
pm.request.headers.add({key: 'Accept', value: 'application/json' });Ruby
require 'base64'
require 'openssl'
secret = "xyz"
request = "GET api.ticketevolution.com/v9/brokerages?page=1&per_page=1"
digest = OpenSSL::Digest::Digest.new('sha256')
signature = Base64.encode64(OpenSSL::HMAC.digest(digest, secret, request)).chomp
puts signature # => "ohGcFIHF3vg75A8Kpg42LNxuQpQZJsTBKv8xnZASzu0="PHP
We highly recommend using our PHP Library.
$secret = 'xyz';
$request = 'GET api.ticketevolution.com/v9/brokerages?page=1&per_page=1';
$signature = base64_encode(hash_hmac('sha256', $request, $secret, true));
echo $signature; // Outputs ohGcFIHF3vg75A8Kpg42LNxuQpQZJsTBKv8xnZASzu0=Swift
func digest(secret: String, request: String) -> String! {
let key = secret.cStringUsingEncoding(NSUTF8StringEncoding)
let data = request.cStringUsingEncoding(NSUTF8StringEncoding)
let result = UnsafeMutablePointer<CUnsignedChar>.alloc(Int(CC_SHA256_DIGEST_LENGTH))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key!, strlen(key!), data!, strlen(data!), result)
let HMAC = NSData(bytes: result, length:Int(CC_SHA256_DIGEST_LENGTH))
let signature = HMAC.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithLineFeed)
result.destroy()
return signature
}This hashed string should then be passed in the X-Signature header. If the secret were xyz, this would look like X-Signature: ohGcFIHF3vg75A8Kpg42LNxuQpQZJsTBKv8xnZASzu0=
cURL
curl -i \
-H Accept: application/json \
-H X-Signature: ohGcFIHF3vg75A8Kpg42LNxuQpQZJsTBKv8xnZASzu0= \
-H X-Token: abc \
-X GET
'http://api.ticketevolution.com/v9/brokerages?page=1&per_page=1'Postman Pre Request Signature
// Constants to strip protocol and port numbers from the URL
const PROTOCOL_MATCHER = /^.*\/\//;
const PORT_MATCHER = /:\d+/;
// Function to create HMAC input based on the request method
function createHmacInput() {
const method = pm.request.method;
const url = pm.request.url.toString().replace(PROTOCOL_MATCHER, '').replace(PORT_MATCHER, '');
if (method === 'GET') {
return createHmacInputQuery(url);
} else {
return createHmacInputBody(url);
}
}
// Function to create HMAC input using the request body
function createHmacInputBody(url) {
const body = pm.request.body.raw;
const suffix = `?${body}`;
return `${pm.request.method} ${url}${suffix}`;
}
// Function to create HMAC input using the request query parameters
function createHmacInputQuery(url) {
const suffix = pm.request.url.query.length === 0 ? '?' : '';
return `${pm.request.method} ${url}${suffix}`;
}
// Set the HMAC input to an environment variable
const hmacInput = createHmacInput();
pm.environment.set('hmac_input', hmacInput);
// Generate HMAC using the input and secret
const secret = pm.environment.get('api_secret'); // Ensure api_secret is set in environment
const hmac = CryptoJS.HmacSHA256(hmacInput, secret);
const hmacBase64 = CryptoJS.enc.Base64.stringify(hmac);
// Set HMAC to an environment variable
pm.environment.set('x_signature', hmacBase64);401 Unauthorized
If you are getting 401 Unauthorized responses, please use the X-Signature Generator to make sure you are correctly computing the X-Signature.