Developer Documentation

VINbarcode API 3.0 Documentation

Read VIN barcodes from submitted images and return structured XML or JSON results for intake, inspection, and mobile capture workflows.

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.

Our VINbarcode API only works with Code 39. Generally speaking, unlike a VIN captured by our VINocr API, a VIN captured through VINbarcode API requires no sanity check.

To achieve the highest possible recognition speed, the image size is a key factor.

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. The following three parameters and their values are required.

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/vinbarcode/v3?saveimage=TRUE with multipart/form-data file
Save Image** saveimage** TRUE or FALSE (default: FALSE) POST https://www.recognition.ws/vinbarcode/v3?saveimage=TRUE
VIN Decode*** vindecode*** TRUE or FALSE (default: FALSE) POST https://www.recognition.ws/vinbarcode/v3?saveimage=TRUE&vindecode=TRUE
Data Format**** format**** XML or JSON (default: XML) POST https://www.recognition.ws/vinbarcode/v3?saveimage=TRUE&vindecode=TRUE&format=JSON
Request a JWT first from POST https://identity.vinquery.com/connect/token using an API Consumer with audience vinquery:api:vinbarcode.
* Only one image file is allowed in a POST request. A POST request with multiple files would be rejected immediately. Only the first found barcode will be processed if an input image contains more than one barcode.
** Set parameter "saveimage" to "TRUE" if you'd like our system to save the input image so that later you can log in to your account to review it. Set the value of this parameter to "FALSE" otherwise.
*** Set parameter "vindecode" to "TRUE" if you'd like the service to retrieve make/model/year for the captured VIN code. Set the value of this parameter to "FALSE" otherwise.
**** Set parameter "format" to "JSON" if you'd like the service to send data in JSON format. If you don't include this parameter at all in the API URL, or explicitly set the value of this parameter to "XML" to get data in XML format.

                    
    <html>
       <form enctype="multipart/form-data" action="https://www.recognition.ws/vinbarcode/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>
        
    

Output in XML or JSON

  • VIN: VIN number in ASCII
  • Position of the barcdoe 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.
VINbarcode without VINdecode output: POST https://www.recognition.ws/vinbarcode/v3 with Authorization: Bearer <jwt-token>
                
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <VINbarcode 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>
    </VINbarcode>
        
    
VINbarcode without VINdecode output in JSON format: POST https://www.recognition.ws/vinbarcode/v3?format=JSON with Authorization: Bearer <jwt-token>
                
    {
      "service": "vinbarcode",
      "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
    }
        
    
VINbarcode with VINdecode output: POST https://www.recognition.ws/vinbarcode/v3?vindecode=TRUE with Authorization: Bearer <jwt-token>
                
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <VINbarcode 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>
    </VINbarcode>
        
    
VINbarcode with VINdecode output in JSON format: POST https://www.recognition.ws/vinbarcode/v3?vindecode=TRUE&format=JSON with Authorization: Bearer <jwt-token>
            
    {
      "service": "vinbarcode",
      "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

Following errors can occur when the system attempts to locate & read a VIN barcode in a given image:
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"?>
    <VINbarcode version="3.0" Date="5/28/2025 1:39:10 PM" Status="FAILED">
      <Message Key="0" Value="Database Errors." />
    </VINbarcode>
        
    
                

    // JSON

    {
      "service": "vinbarcode",
      "version": "3.0",
      "date": "03/08/21 3:23:27 PM",
      "status": "FAILED",
      "message_key": 0,
      "message": "Database Errors." 
    }
        
    
Following errors can occur when the system attempts to decode the captured VIN:
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 Invalid VIN number: 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"?>
    <VINbarcode version="3.0" Date="7/24/2026 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>
    </VINbarcode>
        
    
                

    // JSON

    {
      "service": "vinbarcode",
      "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)

VINbarcode image requests use JWT bearer authentication plus multipart upload. Request a token with the VINbarcode audience, then upload the image with the bearer token. Keep API Consumer credentials on your server.

cURL
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:vinbarcode"}' \
  | jq -r '.jwtToken')

curl -X POST "https://www.recognition.ws/vinbarcode/v3?vindecode=TRUE&format=JSON" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@/path/to/vin-barcode.jpg"
JavaScript
// 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:vinbarcode"
  })
});
const { jwtToken } = await tokenResponse.json();

const form = new FormData();
form.append("file", new Blob([await readFile("./vin-barcode.jpg")]), "vin-barcode.jpg");

const response = await fetch("https://www.recognition.ws/vinbarcode/v3?vindecode=TRUE&format=JSON", {
  method: "POST",
  headers: { Authorization: `Bearer ${jwtToken}` },
  body: form
});

console.log(await response.json());
Python
import requests

token_response = requests.post(
    "https://identity.vinquery.com/connect/token",
    json={
        "clientId": "YOUR_CLIENT_ID",
        "clientSecret": "YOUR_CLIENT_SECRET",
        "audience": "vinquery:api:vinbarcode",
    },
)
token_response.raise_for_status()
jwt_token = token_response.json()["jwtToken"]

with open("vin-barcode.jpg", "rb") as image:
    response = requests.post(
        "https://www.recognition.ws/vinbarcode/v3",
        params={"vindecode": "TRUE", "format": "JSON"},
        headers={"Authorization": f"Bearer {jwt_token}"},
        files={"file": ("vin-barcode.jpg", image, "image/jpeg")},
    )
response.raise_for_status()
print(response.json())
PHP
<?php
$tokenRequest = json_encode([
    'clientId' => 'YOUR_CLIENT_ID',
    'clientSecret' => 'YOUR_CLIENT_SECRET',
    'audience' => 'vinquery:api:vinbarcode'
]);

$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/vinbarcode/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-barcode.jpg')]
]);

$response = curl_exec($apiCurl);
curl_close($apiCurl);
echo $response;
?>
Java
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:vinbarcode\"}";

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-barcode.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/vinbarcode/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);
Go
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:vinbarcode"}`)
    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-barcode.jpg")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    part, err := writer.CreateFormFile("file", "vin-barcode.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/vinbarcode/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))
}
C#
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:vinbarcode\"}";
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-barcode.jpg"));
imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
form.Add(imageContent, "file", "vin-barcode.jpg");

using var request = new HttpRequestMessage(HttpMethod.Post, "https://www.recognition.ws/vinbarcode/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());