Archive
Filling the Gaps: Introducing NicheVinDecoder – A Specialized #VIN Library for Forgotten Vehicles

When was the last time you tried to decode a VIN for an RV, specialty trailer, or electric scooter only to get a frustrating “manufacturer not found” error? If you’ve worked with vehicle data beyond mainstream cars and trucks, you’ve probably hit this wall more times than you’d care to count.
The standard NHTSA VIN decoder works brilliantly for Ford, Toyota, and GM vehicles. But what happens when you’re dealing with a Highland Ridge travel trailer, a Segway electric scooter, or a custom-built utility trailer? You’re often left with nothing but the basic World Manufacturer Identifier and a lot of guesswork.
That’s exactly the problem that led us to create NicheVinDecoder – an open-source .NET library specifically designed to decode VINs from the manufacturers that traditional decoders leave behind.
The Problem: A Tale of Two VIN Decoders
Picture this scenario: You’re building an application for an RV dealership. A customer walks in with a 2023 Highland Ridge Open Range travel trailer, VIN number 58TBM0BU8P3A13051. You run it through a standard VIN decoder and get:
Manufacturer: Highland Ridge RV (maybe)
Model Year: 2023
Everything else: Unknown
But with NicheVinDecoder, that same VIN reveals:
Manufacturer: Highland Ridge RV
Model Year: 2023
Model: Open Range 330BHS Travel Trailer
Body Style: RV Trailer [Standard] Enclosed Living Quarters
Trailer Type: Ball Pull (Travel Trailer)
Axle Configuration: Two Axles (Tandem)
Length: 38 ft - less than 40 ft
Plant Location: 3195 N. SR 5, Shipshewana, IN 46565
Model Code: A1 (330BHS)
Sequential Production Number: 3051
The difference is dramatic. Instead of generic data, you get actionable information that can drive business decisions, inventory management, and customer service.
๐ Check out NicheVinDecoder on GitHub
Who This Library Is For
NicheVinDecoder isn’t trying to replace existing VIN decoders – it’s designed to complement them. It’s perfect for developers working with:
RV and Trailer Industry
- Dealership management systems
- Insurance applications
- Parts lookup systems
- Rental platforms
Specialty Vehicle Markets
- Electric vehicle fleets
- Industrial equipment tracking
- Custom manufacturer databases
- International vehicle imports
Data Integration Projects
- Vehicle history reports
- Fleet management systems
- Auction platforms
- Compliance tracking
The Technical Architecture
We built NicheVinDecoder with extensibility as the core principle. The library uses a factory pattern that automatically detects which decoder to use based on the World Manufacturer Identifier (WMI):
csharp
// Simple usage
var result = VinDecoder.Decode("58TBM0BU8P3A13051");
if (result.IsValid)
{
Console.WriteLine($"Manufacturer: {result.Manufacturer}");
Console.WriteLine($"Model: {result.Model}");
Console.WriteLine($"Plant: {result.AdditionalProperties["PlantLocation"]}");
}
Each manufacturer decoder inherits from BaseVinDecoder and implements the specific VIN structure for that manufacturer. This means adding support for a new manufacturer is as simple as creating a new class and defining their VIN format.
Current Coverage and Growing
As of today, NicheVinDecoder supports six manufacturers across diverse vehicle types:
ManufacturerVehicle TypesExample ModelsHighland Ridge RVTravel Trailers, Fifth WheelsOpen Range, Mesa Ridge, Go PlayBrinkley RVLuxury Fifth WheelsModel Z, Model GAppalachian TrailersUtility TrailersCar Haulers, Equipment TrailersNine Tech (Segway)Electric ScootersA-Series, B-SeriesXPO ManufacturingCommercial TrailersDry Freight VansLoad Glide TrailersAluminum TrailersFlatbed Trailers
But here’s where it gets exciting – this is just the beginning.
๐ Contribute to NicheVinDecoder
Real-World Impact
We’re already seeing NicheVinDecoder make a difference in production environments:
RV Dealership Systems: Dealers can now automatically populate inventory details, generate accurate listings, and provide instant vehicle history to customers.
Insurance Applications: Underwriters can access precise vehicle specifications for accurate risk assessment and premium calculation.
Fleet Management: Companies managing specialized vehicle fleets can track detailed asset information for maintenance scheduling and compliance reporting.
The Open Source Advantage
One of the most exciting aspects of NicheVinDecoder is its open-source nature. Every manufacturer decoder is built using publicly available VIN specifications, and we encourage the community to contribute.
Adding a new manufacturer is surprisingly straightforward:
- Research the VIN Structure: Gather the manufacturer’s VIN specification
- Create the Decoder Class: Implement the decoding logic
- Add Unit Tests: Ensure reliability with comprehensive tests
- Submit a Pull Request: Share your work with the community
We’ve made the contribution process as smooth as possible with detailed documentation, code templates, and examples.
A Community-Driven Future
The beauty of focusing on niche manufacturers is that there’s a passionate community behind each one. RV enthusiasts know Highland Ridge inside and out. Electric vehicle advocates understand every nuance of their chosen brands. Trailer professionals have deep expertise in their specialized equipment.
By tapping into this collective knowledge, NicheVinDecoder can grow to cover hundreds of specialized manufacturers that would never make it into mainstream VIN decoders.
Getting Started
Ready to try NicheVinDecoder in your project? Here’s how to get started:
Installation
bash
# Clone the repository
git clone https://github.com/infiniteloopltd/NicheVinDecoder.git
# Or reference it in your project
# (NuGet package coming soon)
Basic Usage
csharp
using NicheVinDecoder;
var result = VinDecoder.Decode(yourVin);
if (result.IsValid)
{
// Access rich vehicle data
var make = result.AdditionalProperties["Make"];
var plantLocation = result.AdditionalProperties["PlantLocation"];
// And much more...
}
๐ Full Documentation Available on GitHub
What’s Next?
We have big plans for NicheVinDecoder:
Short Term
- NuGet package for easy installation
- Additional RV manufacturers (Forest River, Thor Industries)
- More electric vehicle brands
- Enhanced error handling and validation
Long Term
- Web API for non-.NET applications
- Machine learning for automatic VIN structure detection
- Integration with popular vehicle databases
- Mobile SDK for field applications
Community Driven
- Whatever manufacturers the community needs most
- International vehicle support
- Specialized industry focus areas
Join the Movement
NicheVinDecoder represents more than just another code library – it’s a movement to ensure that no vehicle gets left behind in our increasingly digital automotive world.
Whether you’re a developer who’s frustrated by VIN decoder limitations, a domain expert with knowledge of a specific manufacturer, or simply someone who believes that open source makes everything better, we’d love to have you join us.
Ways to Get Involved:
๐ง Developers: Contribute decoder classes for manufacturers you know ๐ Domain Experts: Share VIN specifications and vehicle knowledge
๐งช Testers: Help validate decoders with real-world VIN samples ๐ข Advocates: Spread the word in your professional networks
โญ Star NicheVinDecoder on GitHub
Conclusion
Every VIN tells a story. With mainstream vehicles, that story is usually easy to read. But for the millions of specialty vehicles on our roads – the RVs that enable adventure, the trailers that move commerce, the electric scooters that transform urban mobility – those stories have been largely untold.
NicheVinDecoder changes that. By focusing on the forgotten corners of the automotive world and leveraging the power of open source collaboration, we’re building something that couldn’t exist any other way.
The next time you encounter a VIN from a manufacturer you’ve never heard of, don’t just shrug and move on. That vehicle has a story to tell – and with your help, NicheVinDecoder can learn to tell it.
Ready to dive in? Check out the project on GitHub, try it with your own VINs, and let us know what manufacturers you’d like to see supported next.
๐ฏ Visit NicheVinDecoder on GitHub Today
Have experience with a manufacturer not yet covered by NicheVinDecoder? We’d love to hear from you! Open an issue on GitHub or reach out to discuss adding support for your area of expertise.
Porting a PHP OAuth Spotler Client to C#: Lessons Learned
Recently I had to integrate with Spotlerโs REST API from a .NET application. Spotler provides a powerful marketing automation platform, and their API uses OAuth 1.0 HMAC-SHA1 signatures for authentication.
They provided a working PHP client, but I needed to port this to C#. Hereโs what I learned (and how you can avoid some common pitfalls).
๐ The Goal
We started with a PHP class that:
โ Initializes with:
consumerKeyconsumerSecret- optional SSL certificate verification
โ Creates properly signed OAuth 1.0 requests
โ Makes HTTP requests with cURL and parses the JSON responses.
I needed to replicate this in C# so we could use it inside a modern .NET microservice.
๐ The Port to C#
๐ The tricky part: OAuth 1.0 signatures
Spotlerโs API requires a specific signature format. Itโs critical to:
- Build the signature base string by concatenating:
- The uppercase HTTP method (e.g.,
GET), - The URL-encoded endpoint,
- And the URL-encoded, sorted OAuth parameters.
- The uppercase HTTP method (e.g.,
- Sign it using HMAC-SHA1 with the
consumerSecretfollowed by&. - Base64 encode the HMAC hash.
This looks simple on paper, but tiny differences in escaping or parameter order will cause 401 Unauthorized.
๐ป The final C# solution
We used HttpClient for HTTP requests, and HMACSHA1 from System.Security.Cryptography for signatures. Hereโs what our C# SpotlerClient does:
โ
Generates the OAuth parameters (consumer_key, nonce, timestamp, etc).
โ
Creates the exact signature base string, matching the PHP implementation character-for-character.
โ
Computes the HMAC-SHA1 signature and Base64 encodes it.
โ
Builds the Authorization header.
โ
Sends the HTTP request, with JSON bodies if needed.
We also added better exception handling: if the API returns an error (like 401), we throw an exception that includes the full response body. This made debugging much faster.
๐ Debugging tips for OAuth 1.0
- Print the signature base string.
It needs to match exactly what Spotler expects. Any stray spaces or wrong escaping will fail. - Double-check timestamp and nonce generation.
OAuth requires these to prevent replay attacks. - Compare with the PHP implementation.
We literally copied the signature generation line-by-line from PHP into C#, carefully mappingrawurlencodetoUri.EscapeDataString. - Turn off SSL validation carefully.
During development, you might disable certificate checks (ServerCertificateCustomValidationCallback), but never do this in production.
using System.Security.Cryptography;
using System.Text;
namespace SpotlerClient
{
public class SpotlerClient
{
private readonly string _consumerKey;
private readonly string _consumerSecret;
private readonly string _baseUrl = "https://restapi.mailplus.nl";
private readonly HttpClient _httpClient;
public SpotlerClient(string consumerKey, string consumerSecret, bool verifyCertificate = true)
{
_consumerKey = consumerKey;
_consumerSecret = consumerSecret;
var handler = new HttpClientHandler();
if (!verifyCertificate)
{
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
}
_httpClient = new HttpClient(handler);
}
public async Task<string> ExecuteAsync(string endpoint, HttpMethod method, string jsonData = null)
{
var request = new HttpRequestMessage(method, $"{_baseUrl}/{endpoint}");
var authHeader = CreateAuthorizationHeader(method.Method, endpoint);
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", authHeader);
if (jsonData != null)
{
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
}
var response = await _httpClient.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
return body;
}
return await response.Content.ReadAsStringAsync();
}
private string CreateAuthorizationHeader(string httpMethod, string endpoint)
{
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
var nonce = Guid.NewGuid().ToString("N");
var paramString = "oauth_consumer_key=" + Uri.EscapeDataString(_consumerKey) +
"&oauth_nonce=" + Uri.EscapeDataString(nonce) +
"&oauth_signature_method=" + Uri.EscapeDataString("HMAC-SHA1") +
"&oauth_timestamp=" + Uri.EscapeDataString(timestamp) +
"&oauth_version=" + Uri.EscapeDataString("1.0");
var sigBase = httpMethod.ToUpper() + "&" +
Uri.EscapeDataString(_baseUrl + "/" + endpoint) + "&" +
Uri.EscapeDataString(paramString);
var sigKey = _consumerSecret + "&";
var signature = ComputeHmacSha1Signature(sigBase, sigKey);
var authHeader = $"OAuth oauth_consumer_key=\"{_consumerKey}\", " +
$"oauth_nonce=\"{nonce}\", " +
$"oauth_signature_method=\"HMAC-SHA1\", " +
$"oauth_timestamp=\"{timestamp}\", " +
$"oauth_version=\"1.0\", " +
$"oauth_signature=\"{Uri.EscapeDataString(signature)}\"";
return authHeader;
}
private string ComputeHmacSha1Signature(string data, string key)
{
using var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(key));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return Convert.ToBase64String(hash);
}
}
}
โ The payoff
Once the signature was constructed precisely, authentication errors disappeared. We could now use the Spotler REST API seamlessly from C#, including:
- importing contact lists,
- starting campaigns,
- and fetching campaign metrics.
๐ Sample usage
var client = new SpotlerClient(_consumerKey, _consumerSecret, false);
var endpoint = "integrationservice/contact/email@gmail.com";
var json = client.ExecuteAsync(endpoint, HttpMethod.Get).GetAwaiter().GetResult();
๐ Conclusion
Porting from PHP to C# isnโt always as direct as it looks โ especially when it comes to cryptographic signatures. But with careful attention to detail and lots of testing, we managed to build a robust, reusable client.
If youโre facing a similar integration, feel free to reach out or clone this approach. Happy coding!
๐ซ Why AWS SDK for S3 No Longer Works Smoothly with .NET Framework 4.8 โ and How to Fix It
In 2024, more .NET developers are finding themselves in a strange situation: suddenly, tried-and-tested .NET Framework 4.8 applications that interact with Amazon S3 start throwing cryptic build errors or runtime exceptions. The culprit? The AWS SDK for .NET has increasingly shifted toward support for .NET Core / .NET 6+, and full compatibility with .NET Framework is eroding.
In this post, weโll explain:
- Why this happens
- What errors you might see
- And how to remove the AWS SDK altogether and replace it with pure .NET 4.8-compatible code for downloading (and uploading) files from S3 using Signature Version 4.
๐งจ The Problem: AWS SDK & .NET Framework 4.8
The AWS SDK for .NET (like AWSSDK.S3) now depends on modern libraries like:
System.Text.JsonSystem.BuffersSystem.Runtime.CompilerServices.UnsafeMicrosoft.Bcl.AsyncInterfaces
These dependencies were designed for .NET Core and later versions โ not .NET Framework. While it was once possible to work around this with binding redirects and careful version pinning, the situation has become unstable and error-prone.
โ Common Symptoms
You may see errors like:
Could not load file or assembly ‘System.Text.Json, Version=6.0.0.11’
Or:
Could not load file or assembly ‘System.Buffers, Version=4.0.5.0’
Or during build:
Warning: Unable to update auto-refresh reference ‘system.text.json.dll’
Even if you install the correct packages, you may end up needing to fight bindingRedirect hell, and still not get a working application.
โ The Solution: Remove the AWS SDK
Fortunately, you donโt need the SDK to use S3. All AWS S3 requires is a properly signed HTTP request using AWS Signature Version 4, and you can create that yourself using standard .NET 4.8 libraries.
๐ Downloading from S3 Without the AWS SDK
Hereโs how you can download a file from S3 using HttpWebRequest and Signature Version 4.
โ๏ธ The Key Points:
- You must include the
x-amz-content-sha256header (even for GETs!) - You sign the request using your AWS secret key
- No external packages required โ works on plain .NET 4.8
๐งฉ Code Snippet
public static byte[] DownloadFromS3(string bucketName, string objectKey, string region, string accessKey, string secretKey)
{
var method = "GET";
var service = "s3";
var host = $"{bucketName}.s3.{region}.amazonaws.com";
var uri = $"https://{host}/{objectKey}";
var requestDate = DateTime.UtcNow;
var amzDate = requestDate.ToString("yyyyMMddTHHmmssZ");
var dateStamp = requestDate.ToString("yyyyMMdd");
var canonicalUri = "/" + objectKey;
var signedHeaders = "host;x-amz-content-sha256;x-amz-date";
var payloadHash = HashSHA256(string.Empty); // Required even for GET
var canonicalRequest = $"{method}\n{canonicalUri}\n\nhost:{host}\nx-amz-content-sha256:{payloadHash}\nx-amz-date:{amzDate}\n\n{signedHeaders}\n{payloadHash}";
var credentialScope = $"{dateStamp}/{region}/{service}/aws4_request";
var stringToSign = $"AWS4-HMAC-SHA256\n{amzDate}\n{credentialScope}\n{HashSHA256(canonicalRequest)}";
var signingKey = GetSignatureKey(secretKey, dateStamp, region, service);
var signature = ToHexString(HmacSHA256(signingKey, stringToSign));
var authorizationHeader = $"AWS4-HMAC-SHA256 Credential={accessKey}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}";
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.Headers["Authorization"] = authorizationHeader;
request.Headers["x-amz-date"] = amzDate;
request.Headers["x-amz-content-sha256"] = payloadHash;
try
{
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var memoryStream = new MemoryStream())
{
responseStream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
catch (WebException ex)
{
using (var errorResponse = (HttpWebResponse)ex.Response)
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
var errorText = reader.ReadToEnd();
throw new Exception($"S3 request failed: {errorText}", ex);
}
}
}
๐ง Supporting Methods
private static string HashSHA256(string text)
{
using (var sha256 = SHA256.Create())
{
return ToHexString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text)));
}
}
private static byte[] HmacSHA256(byte[] key, string data)
{
using (var hmac = new HMACSHA256(key))
{
return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
}
}
private static byte[] GetSignatureKey(string secretKey, string dateStamp, string region, string service)
{
var kSecret = Encoding.UTF8.GetBytes("AWS4" + secretKey);
var kDate = HmacSHA256(kSecret, dateStamp);
var kRegion = HmacSHA256(kDate, region);
var kService = HmacSHA256(kRegion, service);
return HmacSHA256(kService, "aws4_request");
}
private static string ToHexString(byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant();
}
๐ Uploading to S3 Without the AWS SDK
You can extend the same technique for PUT requests. The only differences are:
You calculate the SHA-256 hash of the file content
You include a Content-Type and Content-Length header
You use PUT instead of GET
Let me know in the comments if you’d like the full upload version โ it follows the same Signature V4 pattern.
โ
Summary
Feature AWS SDK for .NET Manual Signature V4
.NET Framework 4.8 support โ Increasingly broken โ
Fully supported
Heavy NuGet dependencies โ
โ Minimal
Simple download/upload โ
โ
(with more code)
Presigned URLs โ
๐ก Manual support
Final Thoughts
If you’re stuck on .NET Framework 4.8 and running into weird AWS SDK issues โ youโre not alone. But youโre not stuck either. Dropping the SDK and using HTTP + Signature V4 is entirely viable, especially for simple tasks like uploading/downloading S3 files.
Let me know if you’d like a full upload example, presigned URL generator, or if you’re considering migrating to .NET 6+.
๐ Fetching #Flickr Profile Information by #Email Using AvatarAPI
As developers, integrating rich user profile data can elevate the experience of our apps, websites, and services. Today, let’s dive into how you can fetch Flickr profile information by email using AvatarAPI, a handy service that consolidates avatar and profile data from multiple platforms โ including Flickr.
Why Flickr?
Flickr remains a popular photo-sharing platform with millions of users showcasing their photography. While many apps focus on social media giants like Twitter or LinkedIn, Flickr’s unique focus on imagery and photography makes it valuable for projects centered around visual content or creative communities.
What is AvatarAPI?
AvatarAPI is an API designed to fetch user profile avatars and metadata by providing common identifiers such as emails, usernames, or social media IDs. It supports many sources, including Flickr, making it a one-stop shop for profile enrichment.
How to Fetch Flickr Profile Data via AvatarAPI
When you request Flickr profile info through AvatarAPI, the data is returned in XML format, containing a rich set of fields to help you understand the user behind the email address.
Hereโs an example snippet of the raw XML you get from AvatarAPI for a Flickr profile:
xmlCopyEdit<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
<person id="12345678@N04" nsid="12345678@N04" ispro="0" is_deleted="0" iconserver="2257" iconfarm="3" path_alias="random_alias" has_stats="0" has_adfree="0" has_free_standard_shipping="0" has_free_educational_resources="0">
<username>Dr. Random</username>
<realname>Random Name</realname>
<location />
<timezone label="Random City, Random State" offset="+00:00" timezone_id="Europe/London" timezone="57" />
<description>Random Description</description>
<photosurl>https://www.flickr.com/photos/random_alias/</photosurl>
<profileurl>https://www.flickr.com/people/random_alias/</profileurl>
<mobileurl>https://m.flickr.com/photostream.gne?id=12345678</mobileurl>
<photos>
<firstdatetaken>2000-01-01 00:00:00</firstdatetaken>
<firstdate>946684800</firstdate>
<count>10</count>
</photos>
</person>
</rsp>
Breaking Down the XML
personattributes:idandnsid: The unique Flickr user ID.ispro: Whether the user has a pro account (1for yes,0for no).is_deleted: Indicates if the account is deleted.iconserverandiconfarm: Used to construct the user’s avatar image URL.path_alias: The user’s Flickr alias, used in URLs.
- Child elements:
<username>: The Flickr username.<realname>: The user’s real name, if provided.<location>: Location info, may be empty.<timezone>: Detailed timezone information with label and offset.<description>: Userโs personal description or bio.<photosurl>,<profileurl>,<mobileurl>: URLs to various Flickr profile pages.<photos>: Info about user’s photos:<firstdatetaken>: When the user took their first photo.<count>: Number of photos uploaded.
How to Use This Data
With this data, you can:
- Display user avatars and profile links inside your app or website.
- Show contextual user info like location and bio.
- Highlight photography activity through photo counts and dates.
- Personalize user experiences by leveraging timezone and locale info.
Constructing the Avatar URL
Flickr stores user icons using a combination of the iconfarm, iconserver, and nsid. The avatar URL can be built as:
bashCopyEdithttps://farm{iconfarm}.staticflickr.com/{iconserver}/buddyicons/{nsid}.jpg
For example, with iconfarm=3, iconserver=2257, and nsid=12345678@N04:
bashCopyEdithttps://farm3.staticflickr.com/2257/buddyicons/12345678@N04.jpg
Wrapping Up
Thanks to AvatarAPIโs support for Flickr, accessing rich profile data by just knowing a userโs email has never been easier. Whether youโre building a photography community platform, enhancing contact profiles, or adding social proof, the Flickr profile data returned by AvatarAPI can help bring your usersโ identities to life.
You can explore the full AvatarAPI docs for Flickr and other providers here: https://docs.avatarapi.com/.
If you want, I can help you write example code snippets in your favorite programming language to get started quickly with AvatarAPI and Flickr!
Happy coding!
โ Your Friendly .NET Dev Blog
Scam warning: Shaw Holdings Pte ltd
Scam warning!
TL; DR;
If you get approached by this company for investment. It’s a scam. Evidence below
https://drive.google.com/drive/folders/1s8PmzNv9YZQI_C50Tx118cqO9REkJgvu?usp=sharing
I got approached by this company, which in the exchange of 2 emails offered a $1M investment. To good to be true. With zero-due diligence. I’ve been trhough similar processes before, and expect a month’s worth of due dilligence document preparation before getting to the point of an offer.
Anyway, so I did due dilligence on them, and specifically, their director:
NRIC/FIN/Passport No. : S8838988C
Name : CHENG YONG TECK
Nationality/Citizenship : SINGAPORE CITIZEN
Address : 10 MARTIN PLACE, #17-14, MARTIN MODERN, SINGAPORE 237963
The director being involved in a bizarre mix of different companies, including immigration (ย linkย ) , weddings, plastic surgery (ย linkย )ย , Weight loss, and engineering companies.
ย Specifically, the Plastic surgery business has left lots of people our of pocket, and is connected to the other holding company;ย quote “Anyway, both Dore Aesthethics and Dore Clinic are owned by Kate Holdings.The Director is Cheng Yong Teck who lives in Orchard Residences. Born in 1988.”
๐ Fetching Adobe Profile Information by Email Using AvatarAPI
In the age of personalization and integration, being able to retrieve user profile images and basic information programmatically can be invaluable for CRMs, marketing platforms, and analytics systems. AvatarAPI provides a simple yet powerful way to fetch profile data from various providers, including Adobe, just by using an email address.
In this post, weโll walk through how to retrieve Adobe profile details using AvatarAPI, including how to interpret the JSON response and especially the RawData payload.
๐ฌ Making the Request
To fetch a user’s Adobe profile via AvatarAPI, youโll need to send a POST request to:
https://avatarapi.com/v2/api.aspx
Hereโs a sample request payload:
{
"username" : "demo",
"password" : "demo___",
"provider" : "Adobe",
"email" : "falecom@sergiolimabroker.com.br"
}
Replace
usernameandpasswordwith your actual AvatarAPI credentials.
๐ฆ Sample Response
Hereโs what a successful response might look like:
{
"Name": "",
"Image": "https://mir-s3-cdn-cf.behance.net/user/276/63d4f1907178277.60f249006a140.jpg",
"Valid": true,
"City": "",
"Country": "",
"IsDefault": false,
"Success": true,
"RawData": "[{\"type\":\"individual\",\"authenticationMethods\":[{\"id\":\"google\",\"url\":\"https://adobeid-na1.services.adobe.com/renga-idprovider/social/v2/signin/google\"},{\"id\":\"password\",\"url\":null}],\"status\":{\"code\":\"active\",\"reason\":null},\"images\":{\"50\":\"https://mir-s3-cdn-cf.behance.net/user/50/63d4f1907178277.60f249006a140.jpg\",\"100\":\"https://mir-s3-cdn-cf.behance.net/user/100/63d4f1907178277.60f249006a140.jpg\",\"115\":\"https://mir-s3-cdn-cf.behance.net/user/115/63d4f1907178277.60f249006a140.jpg\",\"138\":\"https://mir-s3-cdn-cf.behance.net/user/138/63d4f1907178277.60f249006a140.jpg\",\"230\":\"https://mir-s3-cdn-cf.behance.net/user/230/63d4f1907178277.60f249006a140.jpg\",\"276\":\"https://mir-s3-cdn-cf.behance.net/user/276/63d4f1907178277.60f249006a140.jpg\"},\"hasT2ELinked\":false}]",
"Source": {
"Name": "Adobe"
}
}
๐ง Understanding the Response Fields
- Image: URL of the profile image, typically hosted on Behance CDN.
- Valid: Boolean indicating whether a profile was found.
- IsDefault: Tells you whether the image is a generic placeholder or a custom user-uploaded image.
- Success: Boolean status of the request.
- Source: Confirms that the provider is Adobe.
- RawData: This is a stringified JSON array with more granular details from the provider.
๐ Deep Dive into RawData
Letโs parse the RawData field for a better understanding:
[
{
"type": "individual",
"authenticationMethods": [
{
"id": "google",
"url": "https://adobeid-na1.services.adobe.com/renga-idprovider/social/v2/signin/google"
},
{
"id": "password",
"url": null
}
],
"status": {
"code": "active",
"reason": null
},
"images": {
"50": "https://...50.jpg",
"100": "https://...100.jpg",
"115": "https://...115.jpg",
"138": "https://...138.jpg",
"230": "https://...230.jpg",
"276": "https://...276.jpg"
},
"hasT2ELinked": false
}
]
Key Elements:
- type: Usually
"individual", indicating a personal profile. - authenticationMethods: Shows available login methods for this Adobe account (e.g., Google, password).
- status: Account status, with
codetypically being"active". - images: Dictionary of image sizes for the profile picture. Useful for responsive UI.
- hasT2ELinked: Indicates whether the account is linked to two-factor authentication (T2E = Two-step or Two-element?).
๐ฏ Practical Use Case
If youโre building a user-facing dashboard, you can display a verified profile image directly using the Image field, and optionally allow your backend to parse RawData for more advanced logic, such as:
- Detecting authentication methods.
- Validating account status.
- Choosing image resolution dynamically based on device.
Example (JavaScript):
const profileImgUrl = response.Image;
document.getElementById('avatar').src = profileImgUrl;
๐งช Pro Tip: Parsing RawData
Since RawData is a stringified JSON array, youโll need to parse it manually:
const rawData = JSON.parse(response.RawData);
console.log(rawData[0].authenticationMethods);
โ Conclusion
Using AvatarAPI, retrieving Adobe profile details is seamless and efficient. The rich JSON response, especially the RawData, provides developers with a powerful toolkit to enhance user profiles, drive personalization, or even verify identity with minimal effort.
If you’re using AvatarAPI in production or need help parsing the Adobe-specific data, feel free to reach out or drop your questions in the comments!
How to Use the Car Rego API in WordPress
In this tutorial, weโll walk through how to integrate the Car Registration API into a WordPress site. This method ensures that your username and API key are not publicly exposed.
Tools Used in This Demo
- WordPress
- Code Snippets (Free plugin)
- Elementor Pro (Paid website builder)
We’ll be using both PHP and JavaScript scripts. While there are multiple ways to accomplish this, the approach described here prioritizes security by keeping sensitive credentials hidden.
Step 1: Register for the API
Visit carregistrationapi.com and create an account to get your username/API key.
Step 2: Add the PHP Script
Use the Code Snippets plugin to add the PHP code. Paste the script into a new snippet and activate it.
๐ Important: Replace the placeholder on line 16 with your actual username from Step 1.
add_action('elementor_pro/forms/new_record', function($record, $handler) {
if (!session_id()) session_start();
// โ
Confirm hook fired
//file_put_contents(WP_CONTENT_DIR . '/uploads/rego-debug.txt', "HOOK FIRED\n", FILE_APPEND);
//check https://abc.com.au/wp-content/uploads/rego-debug.txt
$form_id = $record->get_form_settings('form_id');
if ('regoform' !== $form_id) return;
//file_put_contents(WP_CONTENT_DIR . '/uploads/rego-debug.txt', "Form matched: $form_id\n", FILE_APPEND);
$fields = $record->get('fields');
$rego = $fields['rego']['value'] ?? '';
$state = $fields['state']['value'] ?? '';
$username = 'ABC';
$api_url = add_query_arg([
'RegistrationNumber' => $rego,
'State' => $state,
'username' => $username,
], 'https://www.regcheck.org.uk/api/reg.asmx/CheckAustralia');
// ๐ API call
$response = wp_remote_get($api_url);
// โ
ADD LOGGING BLOCK HERE
//file_put_contents(WP_CONTENT_DIR . '/uploads/rego-debug.txt', "API URL: $api_url\n", FILE_APPEND);
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
file_put_contents(WP_CONTENT_DIR . '/uploads/rego-debug.txt', "API Error: $error_message\n", FILE_APPEND);
} else {
$body = wp_remote_retrieve_body($response);
//file_put_contents(WP_CONTENT_DIR . '/uploads/rego-debug.txt', "API Response: $body\n", FILE_APPEND);
// Parse response
$xml = @simplexml_load_string($body);
$vehicleJson = (string) ($xml->vehicleJson ?? '');
$vehicleData = json_decode($vehicleJson, true);
$_SESSION['rego_result'] = [
'Description' => $vehicleData['Description'] ?? 'N/A',
'Year' => $vehicleData['RegistrationYear'] ?? 'N/A',
'Engine' => $vehicleData['Engine'] ?? 'N/A',
];
}
}, 10, 2);
// Shortcode to display result
add_shortcode('rego_vehicle_info', function() {
if (!session_id()) session_start();
//$log_path = WP_CONTENT_DIR . '/uploads/rego-debug.txt';
// Log shortcode execution
//file_put_contents($log_path, "SHORTCODE TRIGGERED\n", FILE_APPEND);
$data = $_SESSION['rego_result'] ?? null;
if (!$data) {
return '<p>No vehicle information available yet.</p>';
}
//file_put_contents($log_path, "Session Data: " . print_r($data, true) . "\n", FILE_APPEND);
ob_start();
?>
<div class="rego-vehicle-info">
<h3>Vehicle Details</h3>
<ul>
<li><strong>Description:</strong> <?= esc_html($data['Description']) ?></li>
<li><strong>Registration Year:</strong> <?= esc_html($data['Year']) ?></li>
<li><strong>Engine:</strong> <?= esc_html($data['Engine']) ?></li>
</ul>
</div>
<?php
return ob_get_clean();
});
add_action('rest_api_init', function() {
register_rest_route('rego/v1', '/data', [
'methods' => 'GET',
'callback' => function() {
if (!session_id()) session_start();
return $_SESSION['rego_result'] ?? ['error' => 'No data in session'];
},
'permission_callback' => '__return_true'
]);
});

Step 3: Create the Form and Layout on Your Website
a) Create the Form (Using Elementor or similar)
Structure your form with the following settings:
- Form ID:
regoform - Form Name:
regoform - Rego Field:
- ID:
rego - Shortcode:
[field id="rego"]
- ID:
- State Field:
- ID:
state - Shortcode:
[field id="state"]
- ID:
These field IDs will be referenced in the PHP and JavaScript scripts.
b) Add HTML Widgets
Use two separate HTML widgets in Elementor:
- For Displaying the Result:
Add this HTML element:<div id="rego-result-container"></div> - For the JavaScript Logic:
Add the JavaScript snippet (you can remove or comment out any log messages if not needed).
<script>
window.addEventListener('load', function () {
function waitForjQueryAndForm() {
if (typeof jQuery === 'undefined') {
console.log("โณ Waiting for jQuery...");
setTimeout(waitForjQueryAndForm, 100);
return;
}
jQuery(function ($) {
const $form = $('#regoform');
if (!$form.length) {
console.log("โณ Waiting for form #regoform to appear...");
setTimeout(waitForjQueryAndForm, 100);
return;
}
console.log("โ
Found form #regoform");
// Listen for form success response from Elementor Pro
$form.on('submit_success', function () {
console.log("โ
Form #regoform successfully submitted via AJAX");
setTimeout(function () {
$.ajax({
url: '/wp-json/rego/v1/data',
method: 'GET',
success: function (data) {
console.log("โ
API response:", data);
if (data && !data.error) {
const html = `
<div class="rego-vehicle-info">
<h3>Vehicle Details</h3>
<ul>
<li><strong>Description:</strong> ${data.Description}</li>
<li><strong>Registration Year:</strong> ${data.Year}</li>
<li><strong>Engine:</strong> ${data.Engine}</li>
</ul>
</div>
`;
$('#rego-result-container').html(html);
} else {
$('#rego-result-container').html('<p>No vehicle info available.</p>');
}
},
error: function () {
$('#rego-result-container').html('<p>Failed to load vehicle info.</p>');
}
});
}, 1000);
});
});
}
waitForjQueryAndForm();
});
</script>

How the Flow Works
- The user fills out the form and clicks the “Send” button.
- The form captures the rego and state values.
- The PHP script listens for the form action, calls the API, and fetches the results.
- The JavaScript reads the result and displays the data dynamically on the page.
Example
Hereโs a basic demo in action

How to Query #LinkedIn from an #Email Address Using AvatarAPI.com

Introduction
When working with professional networking data, LinkedIn is often the go-to platform for retrieving user information based on an email address. Using AvatarAPI.com, developers can easily query LinkedIn and other data providers through a simple API request. In this guide, we’ll explore how to use the API to retrieve LinkedIn profile details from an email address.
API Endpoint
To query LinkedIn using AvatarAPI.com, send a request to:
https://avatarapi.com/v2/api.aspx
JSON Payload
A sample JSON request to query LinkedIn using an email address looks like this:
{
"username": "demo",
"password": "demo___",
"provider": "LinkedIn",
"email": "jason.smith@gmail.com"
}
Explanation of Parameters:
- username: Your AvatarAPI.com username.
- password: Your AvatarAPI.com password.
- provider: The data source to query. In this case, “LinkedIn” is specified. If omitted, the API will search a default set of providers.
- email: The email address for which LinkedIn profile data is being requested.
API Response
A successful response from the API may look like this:
{
"Name": "Jason Smith",
"Image": "https://media.licdn.com/dms/image/D4E12AQEud3Ll5MI7cQ/article-inline_image-shrink_1500_2232/0/1660833954461?e=1716422400&v=beta&t=r-9LmmNBpvS4bUiL6k-egJ8wUIpEeEMl9NJuAt7pTsc",
"Valid": true,
"City": "Los Angeles, California, United States",
"Country": "US",
"IsDefault": false,
"Success": true,
"RawData": "{\"resultTemplate\":\"ExactMatch\",\"bound\":false,\"persons\":[{\"id\":\"urn:li:person:DgEdy8DNfhxlX15HDuxWp7k6hYP5jIlL8fqtFRN7YR4\",\"displayName\":\"Jason Smith\",\"headline\":\"Creative Co-founder at Mega Ventures\",\"summary\":\"Jason Smith Head of Design at Mega Ventures.\",\"companyName\":\"Mega Ventures\",\"location\":\"Los Angeles, California, United States\",\"linkedInUrl\":\"https://linkedin.com/in/jason-smith\",\"connectionCount\":395,\"skills\":[\"Figma (Software)\",\"Facebook\",\"Customer Service\",\"Event Planning\",\"Social Media\",\"Sales\",\"Healthcare\",\"Management\",\"Web Design\",\"JavaScript\",\"Software Development\",\"Project Management\",\"APIs\"]}]}",
"Source": {
"Name": "LinkedIn"
}
}
Explanation of Response Fields:
- Name: The full name of the LinkedIn user.
- Image: The profile image URL.
- Valid: Indicates whether the returned data is valid.
- City: The city where the user is located.
- Country: The country of residence.
- IsDefault: Indicates whether the data is a fallback/default.
- Success: Confirms if the request was successful.
- RawData: Contains additional structured data about the LinkedIn profile, including:
- LinkedIn ID: A unique identifier for the user’s LinkedIn profile.
- Display Name: The name displayed on the user’s profile.
- Headline: The professional headline, typically the current job title or a short description of expertise.
- Summary: A brief bio or description of the user’s professional background.
- Company Name: The company where the user currently works.
- Location: The geographical location of the user.
- LinkedIn Profile URL: A direct link to the user’s LinkedIn profile.
- Connection Count: The number of LinkedIn connections the user has.
- Skills: A list of skills associated with the user’s profile, such as programming languages, software expertise, or industry-specific abilities.
- Education History: Details about the userโs academic background, including universities attended, degrees earned, and fields of study.
- Employment History: Information about past and present positions, including company names, job titles, and employment dates.
- Projects and Accomplishments: Notable work the user has contributed to, certifications, publications, and other professional achievements.
- Endorsements: Skill endorsements from other LinkedIn users, showcasing credibility in specific domains.
- Source.Name: The data provider (LinkedIn in this case).
LinkedIn Rate Limiting
By default, LinkedIn queries are subject to rate limits. To bypass these limits, additional parameters can be included in the JSON request:
{
"overrideAccount": "your_override_username",
"overridePassword": "your_override_password"
}
Using these credentials allows queries to be processed without rate limiting. However, to enable this feature, you should contact AvatarAPI.com to discuss setup and access.
Conclusion
AvatarAPI.com provides a powerful way to retrieve LinkedIn profile data using just an email address. While LinkedIn is one of the available providers, the API also supports other data sources if the provider field is omitted. With proper setup, including rate-limit bypassing credentials, you can ensure seamless access to professional networking data.
For more details, visit AvatarAPI.com.
Get #GAIA ID from #Gmail using #AvatarAPI
In this blog post, we will explore how to retrieve a user’s name, profile picture, and GAIA ID from an email address using the AvatarAPI.
Introduction to AvatarAPI
AvatarAPI is a powerful tool that allows developers to fetch user information from various providers. In this example, we will focus on retrieving data from Google, but it’s important to note that AvatarAPI supports multiple providers.
Making a Request to AvatarAPI
To get started, you need to make a POST request to the AvatarAPI endpoint with the necessary parameters. Here’s a step-by-step guide:
Step 1: Endpoint and Parameters
- Endpoint:ย
https://avatarapi.com/v2/api.aspx - Parameters:
username: Your AvatarAPI username (e.g.,ยdemo)password: Your AvatarAPI password (e.g.,ยdemo___)provider: The provider from which to fetch data (e.g.,ยGoogle)email: The email address of the user (e.g.,ยjenny.jones@gmail.com)
Step 2: Example Request
Here’s an example of how you can structure your request:
Copy{
"username": "demo",
"password": "demo___",
"provider": "Google",
"email": "jenny.jones@gmail.com"
}
Step 3: Sending the Request
You can use tools like Postman or write a simple script in your preferred programming language to send the POST request. Below is an example using Python with the requests library:
Copyimport requests
url = "https://avatarapi.com/v2/api.aspx"
data = {
"username": "demo",
"password": "demo___",
"provider": "Google",
"email": "jenny.jones@gmail.com"
}
response = requests.post(url, json=data)
print(response.json())
Step 4: Handling the Response
If the request is successful, you will receive a JSON response containing the user’s information. Here’s an example response:
Copy{
"Name": "Jenny Jones",
"Image": "https://lh3.googleusercontent.com/a-/ALV-UjVPreEBCPw4TstEZLnavq22uceFSCS3-KjAdHgnmyUfSA9hMKk",
"Valid": true,
"City": "",
"Country": "",
"IsDefault": true,
"Success": true,
"RawData": "108545052157874609391",
"Source": {
"Name": "Google"
}
}
Understanding the Response
- Name:ย The full name of the user.
- Image:ย The URL of the user’s profile picture.
- Valid:ย Indicates whether the email address is valid.
- City and Country:ย Location information (if available).
- IsDefault:ย Indicates if the returned data is the default for the provider.
- Success:ย Indicates whether the request was successful.
- RawData:ย The GAIA ID, which is a unique identifier for the user.
- Source:ย The provider from which the data was fetched.
Other Providers
While this example focuses on Google, AvatarAPI supports other providers as well. You can explore the AvatarAPI documentation to learn more about the available providers and their specific requirements.
Conclusion
Using AvatarAPI to retrieve user information from an email address is a straightforward process. By sending a POST request with the necessary parameters, you can easily access valuable user data such as name, profile picture, and GAIA ID. This information can be instrumental in enhancing user experiences and integrating with various applications.
Stay tuned for more insights on leveraging APIs for efficient data retrieval!
Database of Malaysian #NVIC codes available on #PayHip
Malaysian NVIC Vehicle Database โ 23,715 Vehicle Models
Comprehensive NVIC Database for Malaysian Vehicles
Our Malaysian NVIC Vehicle Database provides a detailed reference for 23,715 car makes and models, covering essential vehicle details along with insurance and valuation data. This dataset is invaluable for automotive businesses, insurance companies, financial institutions, and regulatory bodies that require accurate and up-to-date vehicle information.
Key Features:
โ
Extensive Coverage โ Includes 23,715 unique vehicle records spanning multiple manufacturers and models.
โ
Structured Data โ Organized into 18 columns for easy reference and integration.
โ
Complete Vehicle Identification โ Features NVIC codes, model year, make, family, variant, series, and body style.
โ
Engine & Transmission Details โ Provides engine capacity (CC) and transmission type.
โ
Market Valuation Data โ Includes new and used prices (WM & EM), recommended retail price (RRR), and sum insured values.
โ
Historical Updates โ Contains timestamps for data creation, updates, and valuation dates.
Column Breakdown:
- Id โ Unique identifier for each vehicle.
- NVIC โ National Vehicle Identification Code.
- Year โ Model year of the vehicle.
- Make โ Manufacturer (e.g., Toyota, Honda, Proton).
- Family โ General vehicle classification within the brand.
- Variant โ Specific model variation.
- Series โ Trim or sub-model series.
- Style โ Body style (e.g., sedan, SUV, hatchback).
- CC โ Engine displacement (in cubic centimeters).
- Transmission โ Type of gearbox (manual/automatic).
- WM New Price & RRR โ West Malaysia pricing data.
- EM New Price & RRR โ East Malaysia pricing data.
- Sum Insured โ Suggested insured value.
- TimeCreated & TimeUpdated โ Timestamps for record creation and last modification.
- ValuationDate โ Date of the latest vehicle valuation.
Use Cases:
๐น Insurance & Valuation โ Provides essential data for insurance pricing and underwriting.
๐น Automotive Sales & Financing โ Assists in loan approvals and resale evaluations.
๐น Fleet Management & Logistics โ Helps businesses manage and assess vehicle assets.
๐น Regulatory Compliance & Government Agencies โ Useful for vehicle registration and taxation.
This dataset is available in a structured format (CSV, SQL, or API-ready) for seamless integration into your systems.
More info here: https://payhip.com/b/STZvc
Source: https://www.vehicleapi.com.my/