The online racing simulator
LFS REST API General support
1
(26 posts, started )
LFS REST API General support
Starting a new thread about REST API so that I can work out some issues and possibly help others on their way going forward.

Here is some known info so far:

First, register your application at https://www.lfs.net/account/api .
You can then request a Bearer token with your client ID and client secret at id.lfs.net. Quick example:

// Request a Bearer token by using the client_credentials grant type.
// This requires client_id and client_secret.
// One can simply fetch that by POSTing those values. See below for example.

$accessTokenUrl = 'https://id.lfs.net/oauth2/access_token';
$accessTokenPost = [
'grant_type' => 'client_credentials',
'client_id' => 'dfffniwufhnfr823nhr',
'client_secret' => '4n8rrrn3ycnf48ycf8ny4r',
];

$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query($accessTokenPost),
'ignore_errors' => true,
]
]);
$result = file_get_contents($accessTokenUrl, false, $context);
if ($result)
{
$json = json_decode($result);
print_r($json);
}
else
{
var_dump($http_response_header);
var_dump($result);
}

With the obtained Bearer token, you can use our new API at https://api.lfs.net . Quick example:

$bearerToken = 'abcdefetc';
$apiUrl = 'https://api.lfs.net/vehiclemod';
$opts = array('http' =>
array(
'method' => 'GET',
'header' => 'Authorization: Bearer '.$bearerToken,
)
);

$result = file_get_contents(
$apiUrl,
false,
stream_context_create($opts)
);

if ($result)
{
header('Content-Type: application/json');
echo $result;
}
else
{
var_dump($http_response_header);
var_dump($result);
}

That gives you a list of all vehicle mods. The schema of a VehicleModSummary object:

{
"data": {
"id": string // Vehicle Mod identifier. AKA Skin ID, in HEX format
"name": string // Vehicle Mod name
"descriptionShort": string // Short description
"description": string // Description
"userId": int // Uploader user ID
"userName": string // Uploader user Name
"wip": boolean // Work In Progress
"publishedAt": int // Unixtimestamp of publish date
"numDownloads": int // Number of downloads
"curUsage": int // Number of racers using this mod online right now
"rating": int // Rating, from 0 - 5
"numRatings": int // Number of people who rated
"version": int // Vehicle Mod Version
"lastDownloadedAt": int // Unixtimestamp of last download date
"class": int // Vehicle class
"ev": boolean // Electric Vehicle if true
}
}
}

"class":
0: Object
1: Touring car
2: Saloon car
3: Buggy
4: Formula
5: GT
6: Kart
7: Bike
8: Van
9: Truck
10: Formula 1
11: Formula SAE

You can also get more detailed by performing a GET /vehiclemod/{id} which will return:
{
"data": {
"id": string // Vehicle Mod identifier. AKA Skin ID, in HEX format
"name": string // Vehicle Mod name
"descriptionShort": string // Short description
"description": string // Description
"userId": int // Uploader user ID
"userName": string // Uploader user Name
"wip": boolean // Work In Progress
"publishedAt": int // Unixtimestamp of publish date
"numDownloads": int // Number of downloads
"curUsage": int // Number of racers using this mod online right now
"rating": int // Rating, from 0 - 5
"numRatings": int // Number of people who rated
"version": int // Vehicle Mod Version
"lastDownloadedAt": int // Unixtimestamp of last download date
"class": int // Vehicle class
"ev": boolean // Electric Vehicle if true
"vehicle": {
"iceCc": int // ICE cc
"iceNumCylinders": int // ICE number of cylinders
"iceLayout": int // ICE engine layout
"evRedLine": float // EV redline
"drive": int // Drive
"shiftType": int // Shift type
"power": float // Power in kW
"maxPowerRpm": int // Max power at RPM
"torque": float // Torque in Nm
"maxTorqueRpm": int // Max torque at RPM
"mass": float // Total mass of vehicle in kg
"bhp": float // BHP
"powerWightRatio": float // Power to weight ratio
"bhpTon": float // BHP per ton
"fuelTankSize": float // Fuel tank size. If "ev" = true, its unit is kWh, otherwise litres
}
}
}

"class":
0: Object
1: Touring car
2: Saloon car
3: Buggy
4: Formula
5: GT
6: Kart
7: Bike
8: Van
9: Truck
10: Formula 1
11: Formula SAE

"iceLayout":
0: inline
1: flat
2: V

"drive":
0: None
1: Rear wheel drive
2: Front wheel drive
3: All wheel drive

"shiftType":
0: None
1: H-pattern gearbox
2: Motorbike
3: Sequential
4: Sequential with ignition cut
5: Paddle
6: Electric motor
7: Centrifugal clutch

From the PHP code it seems that the parameters should be POSTed in x-www-form-urlencoded format.

I'm using Postman to do that, but the server responds with 401:

{
"error": {
"message": "Client authentication failed: invalid_client"
}
}

And yes, my app is registered with no redirect url and SPA option turned off
#3 - Racon
I'm getting the same, but using the code above with just my credentials pasted in.
I can reproduce. Will investigate.
Aha - even if you only use the client_credentials flow, the lib I use still requires you to enter a redirect-uri. For both of you I've added https://www.lfs.net as a test and it works.
I don't wanna hack this in the lib itself, so I think I have to enforce the redirect uri in the form, even if you don't use it.
#6 - Racon
Thanks Victor, that's got it!
#7 - Racon
I can get a token and use it to access /vehiclemod now, but /vehiclemod/{id} is returning a 404.
should be fixed, sry about that one - forgot to update a rewrite rule on prod.
#9 - Racon
That's got that one too, thanks.
Oh crap. I should probably update the LFSWorld SDK
Hi,
I've just wasted good 4 hours trying to figure out why the API server did not accept Authorization header Shrug
It looks like there's nginx standing as a load balancer before the API and it rewrites calls to the
https://api.lfs.net/vehiclemod endpoint
but it does it with a 302 Redirect response (to the same endpoint but with / at the end..) which somehow cancels Authorization flow in the .NET side.

So any .NET users (and possibly c++) should use the "correct" url: https://api.lfs.net/vehiclemod/ (with the / at the end).

Here's a code example to get List of all mod vehicles:

Quote from .net core :
public async Task<List<ModCarEntry>> GetModdedCars()
{
var client = new HttpClient();
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"client_secret", "your_client_secret"},
{"client_id", "your_client_id"},
{"grant_type", "client_credentials"}
});

var tokenResponse = await client.PostAsync("https://id.lfs.net/oauth2/access_token", content);
var tokenText = await tokenResponse.Content.ReadAsStringAsync();
var tokenObject = JsonConvert.DeserializeObject<TokenResponse>(tokenText);
var accessToken = tokenObject.access_token;

client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var carEntriesResponse = await client.GetStringAsync("https://api.lfs.net/vehiclemod/");

return JsonConvert.DeserializeObject<ModCarEntriesResponse>(carEntriesResponse).Data;
}

public class TokenResponse
{
public string token_type { get; set; }
public int expires_in { get; set; }
public string access_token { get; set; }
}

class ModCarEntriesResponse
{
public List<ModCarEntry> Data { get; set; }
}

public class ModCarEntry
{
public string id { get; set; }
public string name { get; set; }
public string descriptionShort { get; set; }
public string description { get; set; }
public int userId { get; set; }
public string userName { get; set; }
public bool wip { get; set; }
public int publishedAt { get; set; }
public int numDownloads { get; set; }
public int curUsage { get; set; }
public float rating { get; set; }
public int numRatings { get; set; }
public int version { get; set; }
public int lastDownloadedAt { get; set; }
public int _class { get; set; }
public bool ev { get; set; }
}


Oooh sorry, I hate it when sites do that. This was an oversight and I usually write my configs to allow both with and without / .
So that's fixed now.
Quote from Scawen :New update W45!

Changes from 0.6W43 to 0.6W45:

LFS:

New mod filters Staff picks only / Include tweak mods / Include WIP
You can now set list of mods allowed on host (via InSim or LFS.net)
...

Will there be staff_pick/tweak flags included in the mod data?


P.S. from what I saw - ratings go from 1 to 5, because you can't click 0 stars, right? Big grin
Quote :
"rating": int // Rating, from 0 - 5


And its also actually float
Ah, yeah I've added those:
"staffPick": boolean // Mod is selected for Staff Pick
"tweakMod": boolean // Mod is categorised as a Tweak Mod

Thanks for the rating float remark Have adjusted my doc.
It can be 0 though, if noone has voted.
Quote from xspeedasx :Here's a code example to get List of all mod vehicles:

Just a note on this. I had to add this line
Quote :
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new HttpClient();

or else i was getting an error about TLS. Same as you too i had to also add the redirect link to lfs.net and now it works as expected!
Quote from DarkKostas :Just a note on this. I had to add this line

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;


Yes, if you're using insim.net standard version, your project is probably also set to the .NET 4.5 version.
The .NET 4.5 only supports TLS 1.0 by default.
Upgrading your project to .NET 4.6 would support 1.2 by default (and would allow to use C# 6.0 syntax Big grin), and it should still allow to reference the 4.5 version dll, but this is trivial, since it can be solved with the ServicePointManager option adjust.

There shouldn't be such problems in .NET 6 insim.net version
Well until it is explicitly forbidden, for backwards-compatibility purposes InSim.NET will still have the 4.5 version. The end user can choose their own framework at will Smile

Quote from PeterN :Should really move away from .NET 4.5, it'll be unsupported soon...

https://devblogs.microsoft.com/dotnet/net-framework-4-5-2-4-6-4-6-1-will-reach-end-of-support-on-april-26-2022/

the 4.5 version is already in lower priority than the .NET 6 version, meaning when there will be more inSim changes, version 6 will be updated first.
I can't find the documentation Shrug
Quote from xspeedasx :Here's a code example to get List of all mod vehicles

That would take me about 5 lifetimes to code, thanks for sharing!

Quote from NeOn_sp :I can't find the documentation Shrug

The one that's supposed to be in the LFS Manual? I didn't find that either, I guess it doesn't actually exist yet.
The API manual is not there yet, indeed. The API endpoints / bodies are also not yet final. When they are, I'll create the manual pages. The above endpoints were provided so ppl have something to request info regarding vehicle mods for now.
Could access flag be included in the mod data?
Second this, would be nice to be able filter out private mods, or mods that have been removed.

EDIT: Also can we get an approved status flag added too?
Would it be terribly hard to include configuration names with their respective ids for cars?
Configurations are not included in the veh header atm, so I don't have that information.
1

LFS REST API General support
(26 posts, started )
FGED GREDG RDFGDR GSFDG