Get Started Login Sign Up Contact


[ LiveTrack24 API v2 Home ]
LiveTrack24 API v2

LiveTrack24 API v2 Index

Note: Always make sure you are reading the latest version of this manual.

LiveTrack24 API v2 intro

Obtaining your API Keys

To use the LiveTrack24 API you need to have an application key (appKey) and a secret key (appSecret).

Both are supplied by LiveTrack24 on request free of charge.

LiveTrack24 OTP Authentication Sessions

LiveTrack24 API v2 uses an OTP (One-Time-Password) authentication. It is an OTP-question / OTP-answer procedure, in which the server gives a question and you have to give the right answer.

This means that in each data or action request to the server you also add your appKey and the OTP-answer to the previous OTP-question and in each reply additionally to the data the server will give you a new OTP-question.

If your OTP-answer is not correct or if it is your first request, the server will give you a new OTP-question to answer and an error message indicating what is wrong.

In PHP the otpReply function is like this:

function otpReply($question)
	$vc = substr( hash_hmac("sha256", $question, LT24_appSecret), 0, 16);
	return "/ak/" . LT24_appKey . "/vc/" . $vc;

LiveTrack24 API v2 details

=> The API URL format is this:{op_code}/{parameters}/{OTP-answer}

{op_code} = operation code, it can be numeric or string
{parameters} = key1/value1/key2/value2/key3/value3/...
{OTP-answer} = in PHP that is: otpReply($question);

<= LiveTrack24 API v2 returns data in JSON format and it can be returned in a gzip compressed string with the /gzip/1 parameter.


=> request a test "ping"
/vc/2d12585900bc8359 : API url base
op : operation code
ak : appKey
vc : validation code (the OTP-answer)
<= server's reply with data
	"ip": "",
	"qwe": "5558e1573243c4b3"
ip : requested data for the given op code
qwe : OTP-question for your next request
<= server's reply with error
	"qwe": "0400e4d5b20b7bb4",
	"newqwe": 1,
	"error": "Server refused the connection."
qwe : OTP-question for your next request
newqwe : you need to reply the new OTP-question
error : error message


  • The value of "qwe" will be an empty string if the given appKey is wrong or missing.
  • "qwe" will not be present if the given op code is not valid.
  • Always calculate the "vc" based on the "qwe" you have, if the "qwe" you have has expired or is empty (your first call ever) the call will fail but you will get a fresh "qwe" to retry.
  • When you get a "newqwe:1" you will need to add the user token "ut" (see bellow) and the device ID "di" (see next) to the reply.
  • The device ID (for mobile devices) or browser ID is an MD5 string of yours, in combination with the IP it is used to detect account misuses and password leakages.

LiveTrack24 API v2 - One Lazy Step

Most applications will need to access LiveTrack24 on behalf of a user, this user needs to be logged in.

Step 1 - Use the API assuming everything is ready

Usually that will be enough.

Example of a "ping" call:

(the URL above is split in 3 parts to increase readability, the "ak" and "vc" values should be replaced with yours)

If you do not get "reLogin:1" or "newqwe:1" you are done with the call.

The reply will contain "reLogin:1" if the user was not previously logged in, or in case of password change, or in (rare) case of a change in the protocol.

Step 2 - if you get "reLogin:1"

(Re)login with LiveTrack24 user credentials.

=> Parameters
op : 6 or login
username : user name
pass : password in plain text, or
passe : encrypted password, in PHP: encryptWithKey($password, LT24_appSecret); //(see bellow for the function)
<= Returns:
	"qwe": "d029563294f33703",
	"error": "",
	"userID": "11401",
	"username": "GUST",
	"displayName": "GUST - Kostas Proitsakis",
	"country": "GR",
	"ut": "1324d2e3a4d5c6a7f7e8f91324de2a3d",
Special reply parameter:

ut : user token, handles automatic re-login, you should save this and pass it back to the server only if you get a "newqwe:1" or "reLogin:1", your initial ut can be any valid string like "0", "hello", "123", "ok", etc.

Step 3 - if you get "reLogin:1" during login

The user needs to edit his/her username and/or password.

Calling sequence

Let's say we want the result of "tasksList/tasksToGet/5" which will return info about the latest 5 competition tasks.

  1. we assume everything is ready, we call the server and store the special result values for the next call
  2. if there is not special result like "newqwe" or "reLogin" we return to the caller

  3. if there is "reLogin:1" we call "login" and then we go to step 1 (but only once per call from step 3)
  4. if there is "newqwe:1" we go to step 1 (but only once per call from step 4)

Pseudo code

result = callLiveTrack24("tasksList/tasksToGet/5")
begin function callLiveTrack24(params, calledSelf = 0)

	URL = ""
		+ params
		+ "/ak/" + saved_appKey
		+ "/vc/" + substr( hash_hmac('sha256', saved_qwe, saved_appSecret), 0, 16)

	if ( calledSelf ) URL = URL + "/di/" + saved_myDeviceID + "/ut/" + saved_ut

	reply = getURLcontents(URL)
	if URL contains '/gzip/1' then reply = gzdecode(reply)
	res = JSON.parse(reply)

	if res contains "ut" then save it to saved_ut
	if res contains "qwe" then save it to saved_qwe

	if NOT calledSelf
		if res contains "newqwe:1" res = callLiveTrack24(params, 1)
		if res contains "reLogin:1"
			res = callLiveTrack24("login/username/" + saved_username + "/pass/" + saved_password, 1)
			if res contains "reLogin:1"
				// "You need to enter your LiveTrack24 login credentials"
				// get from the user the saved_username and saved_password
				// and retry
				return callLiveTrack24(params, 1)
			end if
		end if
	end if

	return res

end function callLiveTrack24

Deeper understanding of OTP

To the server your OTP answer is a key to a short lived user session cache block which is time expired and deleted or copied to a new block and the old one is deleted after one use (in reality that is after three uses to allow up to 3 parallel calls but you should tread it as one). You should always save the qwe you are getting and use it to generate the OTP reply (the vc) for your next call.

That user session block contains all the needed information for the server and it belongs to a guest until a user is logged in with it.

When you get "Wrong OTP" it means your OTP answer (the /vc ) does not (longer) correspond to a user session block in the cache and the server notifies you about it with newqwe:1

When you get "No user logged in" it means you are doing a call on behalf of a user while the user session block you are referring does not belong to a logged in user and the server notifies you about it with reLogin:1

Working source code in PHP

define("LiveTrack24_API", "");

// test key and secret, will be valid for limited time
define("LT24_appSecret", "83523469867234672146");    // !!!!!!!!! replace it with yours
define("LT24_appKey", "00DE262");                    // !!!!!!!!! replace it with yours

// if you cannot get the device id create a random one once!
if ( !myRead('deviceID') ) myWrite('deviceID', md5( microtime(true) . rand() ) );

// replace this function with one of yours that reads data (client side) from cookies/session/storage/db
function myRead($name)
	return ( array_key_exists($name, $_SESSION) ) ? $_SESSION[$name] : 0;

// replace this function with one of yours that writes data (client side) to cookies/session/storage/db
function myWrite($name, $val)
	return $_SESSION[$name] = $val;

function otpReply($question)
	return "/ak/" . LT24_appKey . "/vc/" . substr( hash_hmac('sha256', $question, LT24_appSecret), 0, 16);

// You call this and it handles the (re)Login and the OTP for you.
// e.g.:  callLiveTrack24old('status');
function callLiveTrack24($params, $calledSelf = 0)
	$url = LiveTrack24_API . $params . otpReply( myRead('qwe') );

	// on "reLogin:1" or "newqwe:1" we need to add our deviceID and the saved user token to the URL
	if ( $calledSelf ) $url .= "/di/" . myRead('deviceID') . "/ut/" . myRead('ut');

	// get the result from the server
	$reply = file_get_contents( $url );
	$onError = $reply;

	// handle gzip
	if ( strpos($url, '/gzip/1') ) $reply = @gzdecode($reply);

	// try to decode the JSON result
	$res = @json_decode($reply, TRUE);

	// if there is something wrong and we did not get a valid JSON reply return to the caller
	if ( !is_array($res) ) return ( strlen($res) ) ? $res : $onError;

	// we have got our valid reply:

	// save the user token if we get one
	if ( array_key_exists('ut', $res) ) myWrite('ut', $res['ut']);

	// save the OTP-question if we get one
	if ( array_key_exists('qwe', $res) ) myWrite('qwe', $res['qwe']);

	if ( !$calledSelf )
		// try once more on 'newqwe' it may catch up and login with the user token ut
		if ( array_key_exists('newqwe', $res) ) $res = callLiveTrack24($params, 1);

		// check if we need to re-login
		if ( is_array($res) && array_key_exists('reLogin', $res) )
		{ 	// try to re-login
			if ( myRead('LT24_username') && myRead('LT24_password') )
				$res = callLiveTrack24('login/username/' . urlencode(myRead('LT24_username'))
					. '/passe/' . myRead('LT24_password'), 1);

			// check if we need to edit username and or password
			if ( is_array($res) && array_key_exists('reLogin', $res) )
				$res['askForLoginInfo'] = "You need to enter your LiveTrack24 login credentials";
				// re-login was successful, now call LiveTrack24 again with the given params
				return callLiveTrack24($params, 1);
	return $res;

// encryptWithKey($str,$key) is used to encrypt passwords.
// It supports character codes from 32 (inclusive) to 224 (exclusive).
// For key you should use your appSecret and it returns the encrypted string in URL-friendly base64 format.
function encryptWithKey($str,$key) {

	$offset = rand(0,255);
	$multi = rand(0,255);
	$final= chr($offset) . chr($multi);
	$helpKey = '!' . $key;
	for($i = 0; $i < strlen($str) ; $i++ )
		$keypos = ( $i * $multi + $offset ) % strlen($key);
		// if the previous digit from the key is odd, 1 , else -1
		$sign = ( ord($helpKey[$keypos]) & 1 ) ? 1 : -1;
		$final .= chr( ord($str[$i]) + ( ord($key[$keypos]) & 0x3f ) * $sign );
	return rtrim(strtr(base64_encode($final), '+/=', '-_,'), ',');

function decryptWithKey($str,$key) {
	$str = base64_decode(strtr($str, '-_,', '+/='));
	$offset = ord($str[0]);
	$multi = ord($str[1]);
	$str = substr($str, 2);
	$helpKey = '!' . $key;
	for($i=0; $i< strlen($str); $i++ )
		$keypos = ( $i * $multi + $offset ) % strlen($key);
		// if the previous digit from the key is odd, 1 , else -1
		$sign = ( ord($helpKey[$keypos]) & 1 ) ? 1 : -1;
		$goodCode = ord($str[$i]) - ( ord($key[$keypos]) & 0x3f ) * $sign ;

	return $final;

Back to the the API index.