API access uses API Consumers and JWT bearer tokens. Create credentials in your dashboard, keep Client Secrets on your server, and request an audience-specific token before calling this API. See the API access and authentication guidance.
Please be aware that the VIN output from the VINocr API may need additional verification due to potential complications in the recognition and translation process. However, proofreading the extracted VIN will be significantly faster and easier than manually typing it character by character. Additionally, to maximize recognition speed, image size plays a crucial role.
Avoid Submitting The Same Image More Than Once
Our system deducts one credit from your account balance for each XML or JSON result returned, regardless of the outcome. Therefore, please ensure your system has a mechanism in place to prevent sending the same image to the API service more than once.
REST API Description
This API uses multipart POST HTTP method. Ensure your POST is a multipart/form-data request. Five parameters and their values are available as follows.
| Parameter Name | Parameter | Value | Used in Request |
| JWT Bearer Token | Authorization header | Bearer <jwt-token> | Authorization: Bearer <jwt-token> |
| Input Image* | Image File* | JPG, JPEG, PNG, GIF, BMP | POST https://www.recognition.ws/vinocr/v3?saveimage=TRUE with multipart/form-data file |
| Save Image** | saveimage** | TRUE or FALSE (default: FALSE) | POST https://www.recognition.ws/vinocr/v3?saveimage=TRUE |
| VIN Decode*** | vindecode*** | TRUE or FALSE (default: FALSE) | POST https://www.recognition.ws/vinocr/v3?saveimage=TRUE&vindecode=TRUE |
| Data Format**** | format**** | XML or JSON (default: XML) | POST https://www.recognition.ws/vinocr/v3?saveimage=TRUE&vindecode=TRUE&format=JSON |
POST https://identity.vinquery.com/connect/token using an API Consumer with audience vinquery:api:vinocr.
<html>
<form enctype="multipart/form-data" action="https://www.recognition.ws/vinocr/v3?saveimage=FALSE&vindecode=FALSE"
method="POST">
Add HTTP header: Authorization: Bearer <jwt-token>
Choose an image to process: <input name="anyName" type="file" />
<input type="submit" value="Go" />
</form>
</html>
Input Image Specs
VIN characters have to meet the specification of at least 25 pixels high characters. In general, OCR can decode characters lower than this requirement but not at the extremely high(99.8%) accuracies required.
| Input Image Specs | |
| Height of the VIN portion in an input image | 20 - 150 pixels |
| Width of the VIN portion in an input image | 80 - 400 pixels |
| Length of a VIN | 17 characters |
| Size of Input Image | < 2.0 MB |
Output in XML or JSON
- VIN: VIN number in ASCII
- Position of the VIN portion in an input image: Top(pixels), Left(pixels), Width(pixels), Height(pixels). The origin(0,0) is the top-left corner of an input image.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<VINocr Version="3.0." Date="12/14/2025 3:23:58 PM" Status="SUCCESS">
<VIN_Captured>XXXXXXXXXXXXXXXXX</VIN_Captured>
<Left>299</Left>
<Top>429</Top>
<Width>450</Width>
<Height>42</Height>
</VINocr>
{
"service": "vinocr",
"version": "3.0",
"date": "3/7/2026 3:53:26 PM",
"status": "SUCCESS",
"vin_captured": "XXXXXXXXXXXXXXXXX",
"left": 299.0,
"top": 429.0,
"width": 450.0,
"height": 42.0
}
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<VINocr Version="3.0" Date="8/14/2025 10:13:32 AM" Status="SUCCESS">
<VIN_Captured>XXXXXXXXXXXXXXXXX</VIN_Captured>
<VINdecode Status="SUCCESS">
<Make>Audi</Make>
<Model>A4</Model>
<Year>2010</Year>
</VINdecode>
<Left>299</Left>
<Top>429</Top>
<Width>450</Width>
<Height>42</Height>
</VINocr>
{
"service": "vinocr",
"version": "3.0",
"date": "3/7/2026 3:53:26 PM",
"status": "SUCCESS",
"vin_captured": "XXXXXXXXXXXXXXXXX",
"vindecode": {
"status": "SUCCESS",
"make": "Audi",
"model": "A4",
"year": 2010
},
"left": 299.0,
"top": 429.0,
"width": 450.0,
"height": 42.0
}
Error Codes
| Error Code (Key) | Description (Value) |
| 0 | Database Errors. |
| 23 | Insufficient balance for Recognition. |
| 25 | No image has been uploaded. |
| 26 | Recognition failed. |
| 27 | Unknown error(s) occured. |
| 29 | One or more required parameters missing. |
// XML
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<VINocr version="3.0" Date="5/28/2026 1:39:10 PM" Status="FAILED">
<Message Key="0" Value="Database Errors." />
</VINocr>
// JSON
{
"service": "vinocr",
"version": "3.0",
"date": "03/08/26 3:23:27 PM",
"status": "FAILED",
"message_key": 0,
"message": "Database Errors."
}
| Error Code (Key) | Description (Value) |
| 0 | Database Errors. |
| 2 | Valid VIN number. However, no data available for it at this moment. |
| 3 | Invalid VIN number: This VIN number did not pass checksum test |
| 4 | A valid VIN number must be exactly 17 digits. |
| 5 | Invalid VIN number: This VIN number contains invalid letters: I, O or Q. |
| 7 | Invalid VIN number: The last 4 digits of a VIN number must be numeric.. |
| 14 | Invalid VIN number: The 10th digit of a VIN number cannot be letter U, letter Z or number 0. |
| 16 | A VIN can only contain alphanumeric characters. |
// XML
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<VINocr version="3.0" Date="9/24/2025 1:43:16 AM" Status="SUCCESS">
<VIN_Captured>1FTRF02W24KXXXXXX</VIN_Captured>
<VINdecode>
<Message Key="3" Value="Invalid VIN number: This VIN number did not pass checksum test." />
</VINdecode>
<Left>40</Left>
<Top>60</Top>
<Width>195</Width>
<Height>45</Height>
</VINocr>
// JSON
{
"service": "vinocr",
"version": "3.0",
"date": "03/08/26 3:23:27 PM",
"status": "SUCCESS",
"vin_captured": "1FTRF02W24KXXXXXX<",
"vindecode": {
"status": "FAILED",
"message_key": 3,
"message": "Invalid VIN number: This VIN number did not pass checksum test."
},
"left": 40.0,
"top": 60.0,
"width": 195.0,
"height": 45.0
}
Coding Examples (JWT Authentication)
VINocr image requests use JWT bearer authentication plus multipart upload. Request a token with the VINocr audience, then upload the image with the bearer token. Keep API Consumer credentials on your server.
TOKEN=$(curl -s -X POST "https://identity.vinquery.com/connect/token" \
-H "Content-Type: application/json" \
-d '{"clientId":"YOUR_CLIENT_ID","clientSecret":"YOUR_CLIENT_SECRET","audience":"vinquery:api:vinocr"}' \
| jq -r '.jwtToken')
curl -X POST "https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@/path/to/vin-image.jpg"
// JavaScript / Node.js server-side example.
import { readFile } from "node:fs/promises";
const tokenResponse = await fetch("https://identity.vinquery.com/connect/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
audience: "vinquery:api:vinocr"
})
});
const { jwtToken } = await tokenResponse.json();
const form = new FormData();
form.append("file", new Blob([await readFile("./vin-image.jpg")]), "vin-image.jpg");
const response = await fetch("https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON", {
method: "POST",
headers: { Authorization: `Bearer ${jwtToken}` },
body: form
});
console.log(await response.json());
import requests
token_response = requests.post(
"https://identity.vinquery.com/connect/token",
json={
"clientId": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET",
"audience": "vinquery:api:vinocr",
},
)
token_response.raise_for_status()
jwt_token = token_response.json()["jwtToken"]
with open("vin-image.jpg", "rb") as image:
response = requests.post(
"https://www.recognition.ws/vinocr/v3",
params={"vindecode": "TRUE", "format": "JSON"},
headers={"Authorization": f"Bearer {jwt_token}"},
files={"file": ("vin-image.jpg", image, "image/jpeg")},
)
response.raise_for_status()
print(response.json())
<?php
$tokenRequest = json_encode([
'clientId' => 'YOUR_CLIENT_ID',
'clientSecret' => 'YOUR_CLIENT_SECRET',
'audience' => 'vinquery:api:vinocr'
]);
$tokenCurl = curl_init('https://identity.vinquery.com/connect/token');
curl_setopt_array($tokenCurl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => $tokenRequest
]);
$tokenResult = json_decode(curl_exec($tokenCurl), true);
curl_close($tokenCurl);
$apiCurl = curl_init('https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON');
curl_setopt_array($apiCurl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $tokenResult['jwtToken']],
CURLOPT_POSTFIELDS => ['file' => new CURLFile('vin-image.jpg')]
]);
$response = curl_exec($apiCurl);
curl_close($apiCurl);
echo $response;
?>
import java.io.File;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.util.UUID;
HttpClient client = HttpClient.newHttpClient();
String tokenBody = "{\"clientId\":\"YOUR_CLIENT_ID\",\"clientSecret\":\"YOUR_CLIENT_SECRET\",\"audience\":\"vinquery:api:vinocr\"}";
HttpRequest tokenRequest = HttpRequest.newBuilder()
.uri(URI.create("https://identity.vinquery.com/connect/token"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(tokenBody))
.build();
String tokenJson = client.send(tokenRequest, HttpResponse.BodyHandlers.ofString()).body();
String jwtToken = tokenJson.replaceAll(".*\\\"jwtToken\\\"\\s*:\\s*\\\"([^\\\"]+)\\\".*", "$1");
File image = new File("vin-image.jpg");
String boundary = "----VinqueryBoundary" + UUID.randomUUID();
byte[] fileBytes = Files.readAllBytes(image.toPath());
String header = "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"file\"; filename=\"" + image.getName() + "\"\r\n"
+ "Content-Type: image/jpeg\r\n\r\n";
String footer = "\r\n--" + boundary + "--\r\n";
byte[] body = ByteBuffer.allocate(header.getBytes().length + fileBytes.length + footer.getBytes().length)
.put(header.getBytes())
.put(fileBytes)
.put(footer.getBytes())
.array();
HttpRequest apiRequest = HttpRequest.newBuilder()
.uri(URI.create("https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON"))
.header("Authorization", "Bearer " + jwtToken)
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(body))
.build();
String response = client.send(apiRequest, HttpResponse.BodyHandlers.ofString()).body();
System.out.println(response);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
tokenPayload := []byte(`{"clientId":"YOUR_CLIENT_ID","clientSecret":"YOUR_CLIENT_SECRET","audience":"vinquery:api:vinocr"}`)
tokenResp, err := http.Post("https://identity.vinquery.com/connect/token", "application/json", bytes.NewReader(tokenPayload))
if err != nil {
panic(err)
}
defer tokenResp.Body.Close()
var tokenResult struct {
JwtToken string `json:"jwtToken"`
}
if err := json.NewDecoder(tokenResp.Body).Decode(&tokenResult); err != nil {
panic(err)
}
var body bytes.Buffer
writer := multipart.NewWriter(&body)
file, err := os.Open("vin-image.jpg")
if err != nil {
panic(err)
}
defer file.Close()
part, err := writer.CreateFormFile("file", "vin-image.jpg")
if err != nil {
panic(err)
}
if _, err := io.Copy(part, file); err != nil {
panic(err)
}
writer.Close()
req, err := http.NewRequest("POST", "https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON", &body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+tokenResult.JwtToken)
req.Header.Set("Content-Type", writer.FormDataContentType())
apiResp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer apiResp.Body.Close()
responseBody, _ := io.ReadAll(apiResp.Body)
fmt.Println(string(responseBody))
}
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using var http = new HttpClient();
var tokenPayload = "{\"clientId\":\"YOUR_CLIENT_ID\",\"clientSecret\":\"YOUR_CLIENT_SECRET\",\"audience\":\"vinquery:api:vinocr\"}";
var tokenResponse = await http.PostAsync(
"https://identity.vinquery.com/connect/token",
new StringContent(tokenPayload, Encoding.UTF8, "application/json"));
tokenResponse.EnsureSuccessStatusCode();
using var tokenJson = JsonDocument.Parse(await tokenResponse.Content.ReadAsStringAsync());
var jwtToken = tokenJson.RootElement.GetProperty("jwtToken").GetString();
using var form = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(await File.ReadAllBytesAsync("vin-image.jpg"));
imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
form.Add(imageContent, "file", "vin-image.jpg");
using var request = new HttpRequestMessage(HttpMethod.Post, "https://www.recognition.ws/vinocr/v3?vindecode=TRUE&format=JSON");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
request.Content = form;
var response = await http.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
