API Key Authentication and Access

EAN's signature authentication method is required for all API requests. Along with your CID and API key, you must send a signature hash based on your shared secret, your API key, and a current UNIX timestamp. Send this hash as the value of the sig common element for every request.

You can find your API key's shared secret by logging in to Affiliate Center and viewing your Key Details under the API top menu.

While developing, you can use our sig generator to quickly make your own sig values for test requests in our sandbox, or to verify values created by your implementation.

IP authentication remains supported only for previously established accounts.

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:

&minorRev=[current minorRev #]

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" />
  • If you receive an error for invalid authentication, please wait for at least 5 minutes before trying a corrected request. Retrying more frequently will cause repeated failures due to cache timing.
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.


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.

$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 = '';
$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_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

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


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


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;
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
HttpResponse response = null;
try {
 response = httpclient.execute(httpget);
} catch (IOException e) {

HttpEntity entity = response.getEntity();
// Print the response

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) {
 } catch (IOException e) {
// shut down the connection manager to free up system resources.


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/'

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

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.start do |http|
req = Net::HTTP::Get.new(request_url)

resp, data = http.request(req)

print data


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;

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";


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


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)

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