CarsXECarsXE

Parking applications face a unique challenge: matching vehicles with suitable parking spaces. Whether it's ensuring a large truck can fit in a garage, directing EV owners to charging-enabled spots, or filtering results based on vehicle height restrictions, having accurate vehicle data is essential.

CarsXE provides two APIs that parking companies can compose to deliver intelligent, personalized parking experiences:

  1. Plate Decoder — get vehicle information from a license plate
  2. Specifications — get detailed specifications from a VIN

Common use cases

1. Size-based parking recommendations

Challenge: A truck owner in NYC needs to find parking spots that can accommodate their vehicle's dimensions.

Solution: Use CarsXE to automatically determine vehicle dimensions and filter parking options accordingly.

// User enters license plate: "ABC1234"
const plateData = await carsxe.platedecoder({
  plate: "ABC1234",
  state: "NY",
  country: "US",
});

// Get detailed specs from VIN
const specs = await carsxe.specs({
  vin: plateData.vin,
});

// Extract dimensions
const dimensions = {
  length: specs.attributes.overall_length, // e.g., "231.80 in."
  width: specs.attributes.overall_width, // e.g., "80.00 in."
  height: specs.attributes.overall_height, // e.g., "76.60 in."
};

// Filter parking spots
const suitableSpots = parkingLocations.filter((spot) => {
  return (
    spot.maxLength >= parseDimension(dimensions.length) &&
    spot.maxWidth >= parseDimension(dimensions.width) &&
    spot.maxHeight >= parseDimension(dimensions.height)
  );
});

Key vehicle attributes:

2. EV charging station prioritization

Challenge: Show EV charging availability prominently to electric vehicle owners.

Solution: Detect if a vehicle is electric and highlight charging-enabled parking locations.

// Decode license plate
const plateData = await carsxe.platedecoder({
  plate: "TESLA99",
  state: "CA",
  country: "US",
});

// Get detailed specs
const specs = await carsxe.specs({
  vin: plateData.vin,
});

// Check if vehicle is electric
const isEV =
  specs.attributes.fuel_type === "Electric" ||
  specs.attributes.fuel_type === "Plug-in Hybrid";

// Customize UI for EV owners
if (isEV) {
  // Show EV charging icon
  // Filter/sort by charging availability
  // Display charging rates and connector types
  // Show estimated charging time
}

Fuel types to check:

3. Vehicle type classification

Challenge: Different parking rates and restrictions for motorcycles, compact cars, SUVs, and commercial vehicles.

Solution: Automatically classify vehicles and apply appropriate pricing and restrictions.

const specs = await carsxe.specs({ vin: userVIN });

// Extract vehicle classification
const vehicleType = specs.attributes.type; // e.g., "Sedan/Saloon", "SUV", "Pickup"
const bodyStyle = specs.attributes.style; // e.g., "SEDAN 4-DR"
const vehicleClass = specs.attributes.vehicle_class; // "1" (Light), "2" (Medium), etc.

// Apply parking rules
let parkingRate;
let restrictions = [];

if (vehicleType.includes("Pickup") || vehicleType.includes("SUV")) {
  parkingRate = rates.oversized;
  restrictions.push("Not suitable for compact spaces");
} else if (vehicleType.includes("Sedan") || vehicleType.includes("Hatchback")) {
  parkingRate = rates.standard;
} else if (vehicleType.includes("Motorcycle")) {
  parkingRate = rates.motorcycle;
  restrictions.push("Motorcycle parking only");
}

Vehicle classification attributes:

4. Weight restrictions

Challenge: Parking garages often have weight limits for structural safety.

Solution: Check vehicle weight against garage capacity.

const specs = await carsxe.specs({ vin: userVIN });

// Extract weight information
const curbWeight = parseDimension(specs.attributes.curb_weight); // "4090 lbs"
const gvwr = specs.attributes.gross_vehicle_weight_rating;
const vehicleRating = specs.attributes.vehicle_rating; // "Light", "Medium", "Heavy"

// Check against garage limits
const garageMaxWeight = 6000; // lbs

if (curbWeight > garageMaxWeight) {
  // Show warning or exclude location
  return {
    suitable: false,
    reason: `Vehicle weight (${curbWeight} lbs) exceeds garage limit (${garageMaxWeight} lbs)`,
  };
}

Implementation guide

Step 1: Capture vehicle information

Parking apps can capture vehicle data in several ways.

Option A: license plate entry

// User manually enters their plate
const plateData = await carsxe.platedecoder({
  plate: "7XER187",
  state: "CA",
  country: "US",
});

// Extract VIN for detailed specs
const vin = plateData.vin;

Option B: VIN entry

// User enters VIN directly (e.g., from registration)
const specs = await carsxe.specs({
  vin: "WBAFR7C57CC811956",
});

Option C: user profile

// Store vehicle info in user profile on signup
// Retrieve for all future parking searches
const userVehicle = getUserProfile().vehicle;

Step 2: Extract key data points

Based on your parking application's needs, extract the relevant attributes:

const parkingRelevantData = {
  // Dimensions
  length: specs.attributes.overall_length,
  width: specs.attributes.overall_width,
  height: specs.attributes.overall_height,

  // Weight
  weight: specs.attributes.curb_weight,

  // Type
  vehicleType: specs.attributes.type,
  bodyStyle: specs.attributes.style,

  // Fuel
  fuelType: specs.attributes.fuel_type,
  isEV: specs.attributes.fuel_type === "Electric",

  // Capacity
  seating: specs.attributes.standard_seating,

  // Identity
  make: specs.attributes.make,
  model: specs.attributes.model,
  year: specs.attributes.year,

  // Additional
  turningDiameter: specs.attributes.turning_diameter,
};

Step 3: Filter and personalize results

Use the extracted data to customize the parking experience:

function filterParkingLocations(spots, vehicleData) {
  return spots
    .filter((spot) => {
      // Check dimensions
      if (spot.maxHeight && parseDimension(vehicleData.height) > spot.maxHeight) {
        return false;
      }

      if (spot.maxLength && parseDimension(vehicleData.length) > spot.maxLength) {
        return false;
      }

      // Check weight
      if (spot.maxWeight && parseDimension(vehicleData.weight) > spot.maxWeight) {
        return false;
      }

      return true;
    })
    .map((spot) => {
      // Add relevance score
      spot.relevanceScore = 0;

      // Boost EV charging spots for EV owners
      if (vehicleData.isEV && spot.hasEVCharging) {
        spot.relevanceScore += 10;
        spot.badges = spot.badges || [];
        spot.badges.push("EV Charging Available");
      }

      // Boost oversized spots for large vehicles
      if (parseDimension(vehicleData.length) > 200 && spot.oversized) {
        spot.relevanceScore += 5;
      }

      return spot;
    })
    .sort((a, b) => b.relevanceScore - a.relevanceScore);
}

API quick reference

Plate Decoder

Endpoint: GET https://api.carsxe.com/platedecoder

Required parameters:

Decode a plate

curl -G https://api.carsxe.com/platedecoder \
  -d key=YOUR_API_KEY \
  -d plate=7XER187 \
  -d state=CA

Key response fields:

Specifications

Endpoint: GET https://api.carsxe.com/specs

Required parameters:

Optional parameters:

Decode a VIN

curl -G https://api.carsxe.com/specs \
  -d key=YOUR_API_KEY \
  -d vin=WBAFR7C57CC811956

Key response fields for parking apps:

AttributeDescriptionExample
overall_lengthTotal vehicle length"193.10 in."
overall_widthTotal vehicle width"73.20 in."
overall_heightTotal vehicle height"57.60 in."
curb_weightVehicle weight without cargo"4090 lbs"
fuel_typeType of fuel/power"Electric", "Gasoline"
typeVehicle type"Sedan/Saloon", "SUV"
styleBody style"SEDAN 4-DR"
turning_diameterTurning circle"37.50 in."
wheelbase_lengthWheelbase length"116.90 in."

Best practices

1. Cache vehicle data

Store vehicle information in user profiles to avoid repeated API calls:

// On first lookup
const specs = await carsxe.specs({ vin: userVIN });

// Save to user profile
await saveUserVehicle(userId, {
  vin: userVIN,
  specs: specs.attributes,
  lastUpdated: new Date(),
  cachedUntil: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000), // 90 days
});

// On subsequent searches
const cachedVehicle = await getUserVehicle(userId);
if (cachedVehicle && cachedVehicle.cachedUntil > new Date()) {
  // Use cached data
  return cachedVehicle.specs;
} else {
  // Refresh from API
  return await carsxe.specs({ vin: userVIN });
}

2. Handle missing data gracefully

Not all vehicles will have complete specification data:

function parseDimension(value) {
  if (!value || value === "") return null;

  // Parse "193.10 in." to 193.10
  const parsed = parseFloat(value);
  return isNaN(parsed) ? null : parsed;
}

function checkDimensions(specs, spot) {
  const height = parseDimension(specs.attributes.overall_height);

  // If we don't have height data, show the spot with a warning
  if (!height && spot.maxHeight) {
    return {
      suitable: "unknown",
      warning: "Unable to verify vehicle height. Please check clearance manually.",
    };
  }

  if (height && spot.maxHeight && height > spot.maxHeight) {
    return { suitable: false };
  }

  return { suitable: true };
}

3. Provide visual indicators

Help users understand why certain spots are recommended:

function addParkingBadges(spot, vehicleData) {
  const badges = [];

  if (vehicleData.isEV && spot.hasEVCharging) {
    badges.push({
      icon: "⚡",
      text: "EV Charging",
      type: "success",
    });
  }

  if (vehicleData.length > 200 && spot.oversized) {
    badges.push({
      icon: "🚛",
      text: "Oversized Friendly",
      type: "info",
    });
  }

  if (spot.maxHeight > parseDimension(vehicleData.height) + 12) {
    badges.push({
      icon: "📏",
      text: "Plenty of Clearance",
      type: "success",
    });
  }

  return badges;
}

4. Error handling

async function getVehicleSpecs(plateOrVIN, isPlate = true) {
  try {
    if (isPlate) {
      const plateData = await carsxe.platedecoder({
        plate: plateOrVIN.plate,
        state: plateOrVIN.state,
        country: plateOrVIN.country,
      });

      if (!plateData.success) {
        throw new Error("Unable to decode license plate");
      }

      if (!plateData.vin) {
        return {
          success: false,
          error: "VIN not available for this plate",
          basicInfo: plateData, // Still return basic info
        };
      }

      const specs = await carsxe.specs({ vin: plateData.vin });
      return { success: true, data: specs };
    } else {
      const specs = await carsxe.specs({ vin: plateOrVIN });
      return { success: true, data: specs };
    }
  } catch (error) {
    console.error("Vehicle lookup error:", error);
    return {
      success: false,
      error: error.message,
      // Fallback: proceed with manual vehicle entry
      requiresManualEntry: true,
    };
  }
}

See the error reference for the complete status-code catalog.

International support

The Plate Decoder API supports license plates from 50+ countries across 6 continents. This enables global parking applications to serve diverse markets:

See Supported Countries for the full country list and per-endpoint coverage. If your traffic originates in Europe, route requests through the EU deployment — see Latency & Regions.

Pricing and sandbox

Free sandbox: The Specifications API is included in the free Sandbox as part of the shared lifetime quota (up to 100 API calls), allowing you to test the integration before committing.

Plate Decoder: Included in the free Sandbox as part of the shared lifetime quota (up to 100 API calls). See the pricing page for details.

Production use: Contact sales for volume pricing and enterprise plans tailored to parking applications.

Next steps

  1. Sign in and get a free API key
  2. Review the Plate Decoder documentation
  3. Review the Specifications documentation
  4. Test the integration in your development environment
  5. Contact support@carsxe.com for integration assistance

Example: complete parking search flow

A complete example showing how a parking app might implement vehicle-aware search:

import { CarsXE } from "carsxe-api";

const carsxe = new CarsXE("YOUR_API_KEY");

async function searchParking(userInput, parkingLocations) {
  // Step 1: Get vehicle data
  let vehicleData;

  if (userInput.plate) {
    const plateData = await carsxe.platedecoder({
      plate: userInput.plate,
      state: userInput.state,
      country: userInput.country || "US",
    });

    if (plateData.vin) {
      const specs = await carsxe.specs({ vin: plateData.vin });
      vehicleData = extractParkingData(specs.attributes);
    }
  } else if (userInput.vin) {
    const specs = await carsxe.specs({ vin: userInput.vin });
    vehicleData = extractParkingData(specs.attributes);
  }

  // Step 2: Filter locations
  const filteredSpots = parkingLocations.filter((spot) => {
    return isVehicleSuitable(vehicleData, spot);
  });

  // Step 3: Rank by relevance
  const rankedSpots = filteredSpots
    .map((spot) => ({
      ...spot,
      relevance: calculateRelevance(vehicleData, spot),
      badges: generateBadges(vehicleData, spot),
    }))
    .sort((a, b) => b.relevance - a.relevance);

  return {
    vehicleData,
    results: rankedSpots,
    filteredCount: parkingLocations.length - filteredSpots.length,
  };
}

function extractParkingData(attributes) {
  return {
    length: parseFloat(attributes.overall_length) || null,
    width: parseFloat(attributes.overall_width) || null,
    height: parseFloat(attributes.overall_height) || null,
    weight: parseFloat(attributes.curb_weight) || null,
    isEV: attributes.fuel_type === "Electric",
    isPHEV: attributes.fuel_type === "Plug-in Hybrid",
    type: attributes.type,
    make: attributes.make,
    model: attributes.model,
    year: attributes.year,
  };
}

function isVehicleSuitable(vehicle, spot) {
  if (!vehicle) return true; // No vehicle data, show all

  if (spot.maxHeight && vehicle.height && vehicle.height > spot.maxHeight) {
    return false;
  }

  if (spot.maxLength && vehicle.length && vehicle.length > spot.maxLength) {
    return false;
  }

  if (spot.maxWeight && vehicle.weight && vehicle.weight > spot.maxWeight) {
    return false;
  }

  return true;
}

function calculateRelevance(vehicle, spot) {
  let score = 0;

  // EV charging match
  if ((vehicle.isEV || vehicle.isPHEV) && spot.hasEVCharging) {
    score += 20;
  }

  // Comfortable fit (not too tight)
  if (vehicle.height && spot.maxHeight) {
    const clearance = spot.maxHeight - vehicle.height;
    if (clearance > 12) score += 10; // 1 foot+ clearance
  }

  // Covered parking bonus for all
  if (spot.covered) score += 5;

  // Security features
  if (spot.security24_7) score += 5;

  return score;
}

function generateBadges(vehicle, spot) {
  const badges = [];

  if ((vehicle.isEV || vehicle.isPHEV) && spot.hasEVCharging) {
    badges.push({ text: "EV Charging", icon: "⚡", variant: "success" });
  }

  if (vehicle.length > 200 && spot.oversized) {
    badges.push({ text: "Large Vehicle OK", icon: "🚛", variant: "info" });
  }

  return badges;
}

// Usage
const results = await searchParking(
  {
    plate: "7XER187",
    state: "CA",
  },
  allParkingLocations,
);

Support

Have questions about integrating CarsXE into your parking application?