You have reached the previous version of our authentication guide. You will be redirected to our new authentication page momentarily.

Click here if you are not redirected.

 

Using a Shared Secret for Authentication and Creating a Digital Signature in Code

When using the digital signature, the value of sig is calculated by generating an MD5 hash made up of the API key, the API user’s shared secret, and a UNIX timestamp.

The system accepts timestamps up to five minutes before or after the server timestamp to accommodate for reasonable clock drift.

EAN syncs internal server times using Network Time Protocol (NTP). If you use NTP as well, clock sync issues should not occur. Most modern operating systems support this or similar time sync services – check your OS documentation.


Most programming languages provide some version of an md5() function, which should be used to generate the signature. The following example illustrates how to generate a valid signature with PHP:

$apiKey = 'xxx-YourAPIkey-xxx';
$secret = 'xxYourSecretxx';
$timestamp = gmdate('U'); // 1427233130 (Tue, 24 Mar 2015 21:38:50 +0000)
$sig = md5($apiKey . $secret . $timestamp);

The following example URL illustrates a REST request to the Hotel Version 3 service using a digital signature: an API key, a timestamp, and a shared secret:

http://api.ean.com/ean-services/rs/hotel/v3/avail?
cid=[yourCID]
&apiKey=[yourAPIKey]
&sig=[youSigValue]
&minorRev=[current minorRev #]
&customerUserAgent=[xxx]
&customerIpAddress=[xxx]
&locale=en_US
&currencyCode=USD
&hotelId=201252

NOTE: The timestamp is often the source of errors in generating a digital signature. Be sure to:

  • Use GMT time, not local time.
  • Use seconds, not milliseconds. (Some systems return the time in milliseconds by default).
  • Use the Server Info timestamp returned in the error message to send another request in order to sync your time with the server if you're receiving authentication errors with sig requests. EX: <ServerInfo serverTime="19:11:13.082-0500" timestamp="1311725473" instance="48" />
Parameter Description
apiKey Customer application identifier. This is a string with a maximum length of 255 characters, and may not include blank spaces or special characters. This is the unique key assigned to you when registering your application.
sig The digital signature for the request, created as an MD5 hash of apiKey, your shared secret, and the timestamp.

All sig values are required to be at least 32 lower-case characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value or to change to all lower-case characters.

If you are receiving authentication errors or have other issues when generating your own digital signature, check your value against EAN's Sig Generator.

Additional Common Request Elements

Review a list of Common Request Elements used in every call for data


Code Samples

You can send requests in any programming language. The following are samples of code for several popular languages (PHP, Python, Java, Ruby, Perl, and C#). Each example retrieves the data by passing query parameters with an API key (apiKey) and the digital signature (sig). The data in the response does not change from language to language.

To send a request without a digital signature and use the IP authentication set in your API account, remove the shared secret and sig process from the requests.

PHP

All sig values are required to be at least 32 characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value.

<?php
$secret = 'xxYourSecretxx';
$host = 'http://api.ean.com/';

// build path
$ver = 'v3/';
$method = 'list/';
$path = "ean-services/rs/hotel/{$ver}{$method}";

// query parameters
$apiKey = '[YourAPIkey]';
$cid = '[yourCID]';
$minorRev = '[currentMinorRev]';
$customerUserAgent = 'Mozilla/4.0';
$customerIpAddress = '172.16.82.13';
$locale = 'en_US';
$currencyCode = 'USD';
$hotelId = '201252';

$timestamp = gmdate('U');
$sig = md5($apiKey . $secret . $timestamp);

$query = "?apikey={$apiKey}&cid={$cid}&sig={$sig}&minorRev={$minorRev}"
. "&customerUserAgent={$customerUserAgent}&customerIpAddress={$customerIpAddress}"
. "&locale={$locale}&currencyCode={$currencyCode}&hotelIdList={$hotelId}";

// initiate curl
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $host . $path . $query);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Accept:application/json'));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
$headers = curl_getinfo($ch);

// close curl
curl_close($ch);

// return XML data
if ($headers['http_code'] != '200') {
 echo "An error has occurred.";
return false;
} else {
 echo $data;
 return($data);
}
?>

Python

If the credentials are valid, the call will return an XML payload into a variable named ‘xml.’

All sig values are required to be at least 32 characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value.

import urllib2
import md5
import time

service = 'http://api.ean.com/ean-services/rs/hotel/'
version = 'v3/'
method = 'list/'
hotelId = '201252'
otherElementsStr = 'cid=55505&minorRev=[x]&customerUserAgent=[xxx]&customerIpAddress=[xxx]&locale=en_US&currencyCode=USD' 

apiKey = 'YourAPIkey'
secret = 'YourSecret'

hash = md5.new()
# seconds since GMT Epoch
timestamp = str(int(time.time()))
# print timestamp
sig = md5.new(apiKey + secret + timestamp).hexdigest()
url = service + version + method+ '?apiKey=' + apiKey + '&sig=' + sig + otherElementsStr + '&hotelIdList=' + hotelId
# print url
xml = urllib2.urlopen(url).read()

print xml

Java

The following Java example illustrates how to execute a web service request for data via an HTTP GET. It relies on the HttpComponents package from the Apache Software Foundation:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class RestfulCallExample {

 public static String service = "http://api.ean.com/ean-services/rs/hotel/";
 public static String version = "v3/";
 public static String method = "list";
 public static String hotelId = "201252";
 public static String otherElementsStr = "&cid=55505&minorRev=[x]"
+ "&customerUserAgent=[xxx]&customerIpAddress=[xxx]&locale=en_US&currencyCode=USD";
 public static String apikey = "xxx-YourAPIkey-xxx";
 public static String secret = "xxYourSecretxx";

 public static void main(String[] args) throws NoSuchAlgorithmException {

MessageDigest md = MessageDigest.getInstance("MD5");
long timeInSeconds = (System.currentTimeMillis() / 1000);
String input = apikey + secret + timeInSeconds;
md.update(input.getBytes());
String sig = String.format("%032x", new BigInteger(1, md.digest()));

String url = service + version + method+ "?apikey=" + apikey
 + "&sig=" + sig + otherElementsStr + "hotelIdList=" + hotelId;
System.out.println("URL = " + url);
DefaultHttpClient httpclient = new DefaultHttpClient();

// Create an HTTP GET request
HttpGet httpget = new HttpGet(url);

// Execute the request
httpget.getRequestLine();
HttpResponse response = null;
try {
 response = httpclient.execute(httpget);
} catch (IOException e) {
 e.printStackTrace();
return;
} 

HttpEntity entity = response.getEntity();
// Print the response
System.out.println(response.getStatusLine());

if (entity != null) {
 try {
InputStream inputStream = entity.getContent();
// Process the response
BufferedReader bufferedReader = new BufferedReader(
 new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
 System.out.println(line);
}
bufferedReader.close();
 } catch (IOException e) {
e.printStackTrace();
 }
}
// shut down the connection manager to free up system resources.
httpclient.getConnectionManager().shutdown();
 }
}

Ruby

The following Ruby example uses Digest::MD5 to generate the digital signature, and Net::HTTP to send the request.

All sig values are required to be at least 32 characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value.

require 'net/http'
require 'digest/md5'

# hotelId to send
hotelId = '201252'

#additional parameters set in a single string for brevity
$otherElemntsStr = '&cid=55505&minorRev=[x]&customerUserAgent=[xxx]&customerIpAddress=[xxx]&locale=en_US&currencyCode=USD' 

# API location
PRODUCTION_ENDPOINT = 'api.ean.com/ean-services/rs/hotel/'
PRODUCTION_PORT = 80

# Your credentials
API_KEY = 'YourAPIkey'
SHARED_SECRET = 'YourSecret'
API_VERSION = 'v3'

current_time = Time.now
timestamp = Time.now.to_i.to_s
sig = Digest::MD5.hexdigest( API_KEY+SHARED_SECRET+timestamp )

request_url = "/#{API_VERSION}/list}?apiKey=#{API_KEY} & sig=#{sig} & #{otherElementsStr} & hotelIdList=#{hotelId}"

http = Net::HTTP.new( PRODUCTION_ENDPOINT , PRODUCTION_PORT )
http.start do |http|
req = Net::HTTP::Get.new(request_url)

resp, data = http.request(req)

print data
end

Perl

All sig values are required to be at least 32 characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value.

# perl

use strict;
# use LWP::Simple;
use LWP::UserAgent;
use Digest::MD5 qw(md5 md5_hex);

my $service = 'http://api.ean.com/ean-services/rs/hotel/';
my $method = 'list/';
my $version= 'v3/';
my $hotelId = '201252';
my $otherElemntsStr = '&cid=[xx]&minorRev=[x]&customerUserAgent=[xxx]&customerIpAddress=[xxx]&locale=en_US&currencyCode=USD';

# key and shared secret obtained from registering application
my $apiKey = 'YourAPIkey';
my $secret = 'YourSecret';

my $timestamp = time;
#above timestamp needs to be created in PERL !!! Placeholder
my $sig = md5_hex($apiKey . $secret . $timestamp);

# print $timestamp,"", $sig, "\n";

my $ua = new LWP::UserAgent;
$ua->timeout(120);

my $url=$service . $version . $method. '?apiKey=' . $apiKey . '&sig=' . $sig . $otherElementsStr . '&hotelIdList=' . $hotelId;
# print $url, "\n";

my $request = new HTTP::Request('GET', $url);
my $response = $ua->request($request);
my $xml = $response->content();
print $xml,"\n";

C#

The following C# example uses HttpWebRequest and HttpWebResponse.

All sig values are required to be at least 32 characters in length, so manipulation of the string may be necessary to add a leading 0 to the final value.

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Security.Cryptography;

namespace QuovaRESTSample
{
class Program
{
static void Main(string[] args)
{
string service = "http://api.ean.com/ean-services/rs/hotel/";
string version = "v3/";
string method = "list/";
string hotelId = "201252";
	string otherElemntsStr = "&cid=[x]&minorRev=[x]&customerUserAgent=[xxx]&customerIpAddress=[xxx]&locale=en_US&currencyCode=USD";
string apiKey = "xxx-YourAPIkey-xxx";
string secret = "xxYourSecretxx";
string sig = MD5GenerateHash(apiKey + secret + (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
string fullURL = service + version + method+ "?apiKey=" + apiKey + "&sig=" + sig + otherElementsStr + "&hotelIdList=" + hotelId;

// Create the web request
HttpWebRequest request = WebRequest.Create(fullURL) as HttpWebRequest;

// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());

// Write response to the console
Console.WriteLine(reader.ReadToEnd());
}

}

private static string MD5GenerateHash(string strInput)
{
// Create a new instance of the MD5CryptoServiceProvider object.
MD5 md5Hasher = MD5.Create();

// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(strInput));

// Create a new Stringbuilder to collect the bytes and create a string.
StringBuilder sBuilder = new StringBuilder();

// Loop through each byte of the hashed data and format each one as a hexadecimal string.
for (int nIndex = 0; nIndex < data.Length; ++nIndex)
{
sBuilder.Append(data[nIndex].ToString("x2"));
}

// Return the hexadecimal string.
return sBuilder.ToString();
}
}
}