All posts

Introducing @cardog/api: The Official TypeScript Client for Automotive Data

Cardog Team7 min read
Introducing @cardog/api: The Official TypeScript Client for Automotive Data

Introducing @cardog/api: The Official TypeScript Client for Automotive Data

We built Cardog to make automotive data accessible to everyone. Today, we are making that data accessible to developers everywhere with the official release of @cardog/api - a TypeScript-first client library for the Cardog API.

Whether you are building a car marketplace, a dealership tool, a fleet management system, or a mobile app for car enthusiasts, you now have access to the same real-time data that powers Cardog - VIN decoding, market intelligence from millions of listings, safety recalls, fuel prices, and more.

Why We Built This

The automotive data landscape is fragmented and frustrating. Want VIN decoding? That is one API with slow response times. Market pricing? Another vendor with a different authentication scheme. Recalls? Yet another integration. Each comes with its own quirks, rate limits, and data formats.

We spent years aggregating and normalizing this data for our own platform. Now we are opening it up through a single, unified API with a client library that feels native to modern TypeScript development.

Quick Start

Get up and running in under a minute:

bash
npm install @cardog/api
# or
pnpm add @cardog/api
# or
yarn add @cardog/api

Initialize the client with your API key:

typescript
import { CardogClient } from "@cardog/api";

const client = new CardogClient({
  apiKey: "your-api-key", // Get one at cardog.app
});

// Decode a VIN
const vehicle = await client.vin.decode("1HGCM82633A123456");
console.log(vehicle.variants[0].make);  // Honda
console.log(vehicle.variants[0].model); // Accord
console.log(vehicle.variants[0].year);  // 2003

// Get market analysis
const market = await client.market.overview("Toyota", "Camry", 2022);
console.log(market.pricing.median);     // $28,500
console.log(market.totalListings);      // 12,847

That is it. Full TypeScript support, automatic request/response validation, and typed error handling out of the box.


VIN Decoding

Every vehicle sold in North America since 1981 has a 17-character Vehicle Identification Number. Our VIN decoder extracts comprehensive specifications from any valid VIN:

typescript
const result = await client.vin.decode("5YJSA1E26MF123456");

// Access decoded vehicle information
const vehicle = result.variants[0];
console.log(vehicle.make);        // Tesla
console.log(vehicle.model);       // Model S
console.log(vehicle.year);        // 2021
console.log(vehicle.trim);        // Long Range
console.log(vehicle.bodyStyle);   // Sedan
console.log(vehicle.msrp);        // 79990

// Deep specifications
console.log(vehicle.spec.Drivetrain);
// { "Drivetrain Type": "All Wheel Drive", "Motor Type": "Dual Motor" }

console.log(vehicle.spec.Battery);
// { "Battery Capacity": "100 kWh", "Range (EPA)": "412 miles" }

The decoder returns every specification we can extract - engine details, transmission, safety features, dimensions, fuel economy ratings, and more. For EVs, you get battery capacity, range estimates, and charging specifications.

Need VIN extraction from images? We have got you covered:

typescript
// Extract VIN from a photo (base64 encoded)
const result = await client.vin.image(base64ImageData);
console.log(result.vin);        // "1HGCM82633A123456"
console.log(result.confidence); // 0.98

This works with dashboard photos, registration documents, or any image containing a VIN.


Market Intelligence

This is where things get interesting. We track millions of vehicle listings across North America, giving you real-time market intelligence that was previously only available to large dealers and auction houses.

Market Overview

Get a comprehensive snapshot of any vehicle's market position:

typescript
const overview = await client.market.overview("Honda", "Civic", 2022);

console.log(overview.totalListings);      // 8,432
console.log(overview.pricing.median);     // 24500
console.log(overview.pricing.p25);        // 22000
console.log(overview.pricing.p75);        // 27500
console.log(overview.avgDaysOnMarket);    // 23
console.log(overview.avgOdometer);        // 28500

Price Distribution

Understand how prices cluster in the market:

typescript
const pricing = await client.market.pricing("Ford", "F-150", 2023);

// Get histogram data for visualizations
pricing.histogram.forEach(bucket => {
  console.log(`$${bucket.min}-${bucket.max}: ${bucket.count} listings`);
});

// Output:
// $35000-40000: 1,247 listings
// $40000-45000: 2,891 listings
// $45000-50000: 3,156 listings
// $50000-55000: 2,034 listings
// $55000-60000: 892 listings

Geographic Analysis

See how prices vary by region:

typescript
const geography = await client.market.geography("Tesla", "Model 3", 2022);

geography.regions.forEach(region => {
  console.log(`${region.name}: $${region.medianPrice} (${region.count} listings)`);
});

// Output:
// California: $42,500 (2,341 listings)
// Texas: $39,800 (1,567 listings)
// Florida: $41,200 (1,234 listings)
// Ontario: $44,100 (892 listings)

Odometer vs Price Correlation

Understand depreciation curves:

typescript
const odometer = await client.market.odometer("Toyota", "Camry", 2020);

odometer.brackets.forEach(bracket => {
  console.log(
    `${bracket.minMiles}-${bracket.maxMiles} miles: ` +
    `$${bracket.medianPrice} avg (${bracket.count} listings)`
  );
});

// Output:
// 0-25000 miles: $28,500 avg (1,234 listings)
// 25000-50000 miles: $25,200 avg (2,891 listings)
// 50000-75000 miles: $22,100 avg (1,567 listings)
// 75000-100000 miles: $19,800 avg (892 listings)

Track how prices change week over week or month over month:

typescript
const trends = await client.market.trends("Porsche", "911", 2021, "month");

trends.periods.forEach(period => {
  console.log(`${period.date}: $${period.medianPrice} (${period.listingCount} listings)`);
});

VIN-Based Analysis

Get market positioning for a specific vehicle:

typescript
const analysis = await client.market.analysis("WP0AB2A99NS123456");

console.log(analysis.vehicle.make);          // Porsche
console.log(analysis.vehicle.model);         // 911
console.log(analysis.marketPosition);        // "below_market"
console.log(analysis.percentile);            // 23 (cheaper than 77% of similar vehicles)
console.log(analysis.similarListings);       // Array of comparable vehicles

Individual Listing Position

For any listing in our database, understand exactly where it sits in the market:

typescript
const position = await client.market.position("listing-id-here");

console.log(position.pricePercentile);    // 35 (35th percentile - good value)
console.log(position.daysOnMarket);       // 12
console.log(position.priceVsMedian);      // -2500 (under median by $2,500)

Vehicle Listings

Search our database of millions of active listings across North America:

typescript
const results = await client.listings.search({
  makes: ["Toyota", "Honda"],
  models: { Toyota: ["Camry", "Corolla"], Honda: ["Accord", "Civic"] },
  year: { min: 2020, max: 2024 },
  price: { min: 15000, max: 40000 },
  odometer: { max: 50000 },
  bodyStyles: ["Sedan"],
  fuelTypes: ["Gasoline", "Hybrid"],
  pagination: { page: 1, limit: 20 },
});

console.log(results.pagination.total);  // 4,521 matching listings

results.data.forEach(listing => {
  console.log(
    `${listing.year} ${listing.make} ${listing.model} - ` +
    `$${listing.price} - ${listing.odometer} miles`
  );
});

Get Listing Counts

Perfect for showing users how many results match their criteria:

typescript
const count = await client.listings.count({
  makes: ["BMW"],
  year: { min: 2022 },
  price: { max: 60000 },
});

console.log(count.total);  // 2,847

Build filter UIs with accurate counts:

typescript
const facets = await client.listings.facets({
  makes: ["Mercedes-Benz"],
  year: { min: 2020 },
});

// Returns counts for each filterable attribute
console.log(facets.bodyStyles);
// [{ value: "SUV", count: 1234 }, { value: "Sedan", count: 892 }, ...]

console.log(facets.fuelTypes);
// [{ value: "Gasoline", count: 1567 }, { value: "Hybrid", count: 432 }, ...]

console.log(facets.priceRanges);
// [{ min: 30000, max: 40000, count: 892 }, ...]

Individual Listing Details

typescript
const listing = await client.listings.getById("listing-id");

console.log(listing.title);
console.log(listing.price);
console.log(listing.odometer);
console.log(listing.vin);
console.log(listing.seller.name);
console.log(listing.seller.location);
console.log(listing.images);
console.log(listing.description);

Safety Data: Recalls and Complaints

Safety information is critical for any automotive application. We aggregate data from NHTSA (US) and Transport Canada.

Search Recalls

typescript
// Search US recalls
const usRecalls = await client.recalls.search({
  country: "us",
  makes: ["Toyota"],
  models: ["RAV4"],
  year: { min: 2019, max: 2024 },
});

usRecalls.data.forEach(recall => {
  console.log(`Campaign: ${recall.campaignNumber}`);
  console.log(`Component: ${recall.component}`);
  console.log(`Summary: ${recall.summary}`);
  console.log(`Remedy: ${recall.remedy}`);
  console.log(`Affected: ${recall.affectedCount} vehicles`);
});

// Search Canadian recalls
const caRecalls = await client.recalls.search({
  country: "ca",
  makes: ["Honda"],
  models: ["CR-V"],
  year: { min: 2020, max: 2023 },
});

NHTSA Complaints Database

Consumer complaints often predict future recalls. Search the NHTSA complaints database:

typescript
const complaints = await client.complaints.search({
  makes: ["Ford"],
  models: ["Explorer"],
  year: { min: 2020, max: 2023 },
  components: ["ENGINE", "BRAKES"],
});

complaints.data.forEach(complaint => {
  console.log(`Date: ${complaint.dateReceived}`);
  console.log(`Component: ${complaint.componentDescription}`);
  console.log(`Mileage: ${complaint.mileage}`);
  console.log(`Description: ${complaint.complaintDescription}`);
  console.log(`Crash: ${complaint.crashInvolved}`);
  console.log(`Injuries: ${complaint.injuredCount}`);
});

Research and Vehicle Database

Access our complete vehicle database - every make, model, year, and trim sold in North America:

Browse Make Lineups

typescript
const toyota = await client.research.lineup("Toyota");

toyota.models.forEach(model => {
  console.log(`${model.name}: ${model.years.join(", ")}`);
});

// Output:
// Camry: 1983, 1984, ..., 2024, 2025
// Corolla: 1968, 1969, ..., 2024, 2025
// RAV4: 1996, 1997, ..., 2024, 2025
// ...

Get Model Year Details

typescript
const camry2024 = await client.research.byModelYear("Toyota", "Camry", 2024);

camry2024.forEach(variant => {
  console.log(`${variant.trim}: $${variant.msrp}`);
  console.log(`  Engine: ${variant.spec.Engine?.["Engine Type"]}`);
  console.log(`  Horsepower: ${variant.spec.Engine?.Horsepower}`);
  console.log(`  MPG: ${variant.spec.Fuel?.["Fuel Consumption: City/HWY Combined"]}`);
});

Vehicle Images

Get stock images for any vehicle:

typescript
const images = await client.research.getImages({
  make: "Porsche",
  model: "911",
  year: 2024,
  limit: 10,
  shotType: "exterior",
});

images.forEach(image => {
  console.log(image.url);
  console.log(image.shotType);  // "front", "side", "rear", etc.
});

Available Colors

typescript
const colors = await client.research.getColors({
  make: "BMW",
  model: "M3",
  year: 2024,
});

console.log(colors.exterior);
// [{ name: "Alpine White", code: "300", hex: "#FFFFFF" }, ...]

console.log(colors.interior);
// [{ name: "Black Merino Leather", code: "LCSW" }, ...]

EV Charging and Fuel Stations

For apps that help drivers find fuel or charging:

Find EV Charging Stations

typescript
const chargers = await client.charging.getStations({
  lat: 37.7749,
  lng: -122.4194,
  radius: 25,       // km
  minPower: 50,     // kW - for fast chargers
  connector: [32],  // CCS connector type
});

chargers.data.forEach(station => {
  console.log(station.name);
  console.log(station.address);
  console.log(station.distance);       // km from search point
  console.log(station.connections);    // Available connector types
  console.log(station.maxPowerKW);     // Max charging speed
});

Find Gas Stations with Real-Time Prices

typescript
const gasStations = await client.fuel.search({
  country: "US",
  fuelType: "REGULAR",
  lat: 37.7749,
  lng: -122.4194,
  radius: 10,
  limit: 20,
});

gasStations.data.forEach(station => {
  console.log(`${station.name}: $${station.price}/gallon`);
  console.log(`  ${station.address}`);
  console.log(`  Updated: ${station.lastUpdated}`);
});

Fuel Efficiency Data

Access global fuel efficiency data from EPA (US), Transport Canada, UK VCA, and EU EEA:

typescript
const efficiency = await client.efficiency.byVehicle("Toyota", "Prius", 2024);

efficiency.data.forEach(variant => {
  console.log(`${variant.trim}`);
  console.log(`  City: ${variant.cityMpg} MPG`);
  console.log(`  Highway: ${variant.highwayMpg} MPG`);
  console.log(`  Combined: ${variant.combinedMpg} MPG`);
  console.log(`  Annual Fuel Cost: $${variant.annualFuelCost}`);
  console.log(`  CO2 Emissions: ${variant.co2Emissions} g/mi`);
});

React Integration

For React applications, we provide first-class TanStack Query (React Query) integration:

tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { CardogClient } from "@cardog/api";
import { createHooks } from "@cardog/api/react";

// Setup
const queryClient = new QueryClient();
const client = new CardogClient({ apiKey: "your-api-key" });
const cardog = createHooks(client);

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <VehicleLookup />
    </QueryClientProvider>
  );
}

function VehicleLookup() {
  const [vin, setVin] = useState("1HGCM82633A123456");

  const { data, isLoading, error } = cardog.useVinDecode(vin);

  if (isLoading) return <div>Decoding VIN...</div>;
  if (error) return <div>Error: {error.message}</div>;

  const vehicle = data?.variants[0];
  return (
    <div>
      <h2>{vehicle?.year} {vehicle?.make} {vehicle?.model}</h2>
      <p>Trim: {vehicle?.trim}</p>
      <p>MSRP: ${vehicle?.msrp?.toLocaleString()}</p>
    </div>
  );
}

All Available Hooks

The createHooks factory returns typed hooks for every API endpoint:

typescript
const cardog = createHooks(client);

// VIN
cardog.useVinDecode(vin)
cardog.useVinImage(base64)

// Market
cardog.useMarketOverview({ make, model, year })
cardog.useMarketPricing(make, model, year)
cardog.useMarketOdometer(make, model, year)
cardog.useMarketGeography(make, model, year)
cardog.useMarketTrends(make, model, year, period)
cardog.useMarketPosition(listingId)
cardog.useMarketPulse(options)
cardog.useLocalMarket({ make, model, year, lat, lng })

// Listings
cardog.useListingsSearch(params)
cardog.useListingsCount(params)
cardog.useListingsFacets(params)
cardog.useListingById(id)
cardog.useInfiniteListingsSearch(params)  // For infinite scroll

// Research
cardog.useResearchLineup(make)
cardog.useResearchByMake(make)
cardog.useResearchByModel(make, model)
cardog.useResearchByModelYear(make, model, year)
cardog.useResearchImages(params)
cardog.useResearchColors(params)

// Safety
cardog.useRecalls(params)
cardog.useComplaints(params)

// Fuel & Charging
cardog.useFuelSearch(params)
cardog.useChargingStations(params)

// Locations
cardog.useLocationsSearch(params)
cardog.useLocationById(id)

Infinite Scroll Example

tsx
function ListingsGrid() {
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = cardog.useInfiniteListingsSearch({
    makes: ["Toyota"],
    year: { min: 2020 },
    price: { max: 40000 },
  });

  const allListings = data?.pages.flatMap(page => page.data) ?? [];

  return (
    <div>
      {allListings.map(listing => (
        <ListingCard key={listing.id} listing={listing} />
      ))}

      {hasNextPage && (
        <button
          onClick={() => fetchNextPage()}
          disabled={isFetchingNextPage}
        >
          {isFetchingNextPage ? "Loading..." : "Load More"}
        </button>
      )}
    </div>
  );
}

Query Keys for Cache Invalidation

We export query key factories for manual cache management:

typescript
import { queryKeys } from "@cardog/api";

// Invalidate all market data for a specific vehicle
queryClient.invalidateQueries({
  queryKey: queryKeys.market.overview("Toyota", "Camry", 2022),
});

// Invalidate all listings queries
queryClient.invalidateQueries({
  queryKey: queryKeys.listings.all,
});

Error Handling

The client provides typed error handling with the APIError class:

typescript
import { CardogClient, APIError } from "@cardog/api";

try {
  const vehicle = await client.vin.decode("INVALID-VIN");
} catch (error) {
  if (error instanceof APIError) {
    console.log(error.status);   // 400
    console.log(error.code);     // "INVALID_VIN"
    console.log(error.message);  // "The provided VIN is invalid"
    console.log(error.data);     // Additional error details
  }
}

Common error codes:

StatusCodeDescription
400INVALID_VINVIN format is invalid
400INVALID_PARAMSRequest parameters are invalid
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENAPI key lacks permission
404NOT_FOUNDResource not found
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORServer error

Technical Details

Runtime Compatibility

@cardog/api works everywhere JavaScript runs:

  • Node.js 18+
  • Modern browsers (Chrome, Firefox, Safari, Edge)
  • Edge runtimes (Cloudflare Workers, Vercel Edge, Deno Deploy)
  • React Native

Bundle Size

The client is lightweight and tree-shakeable:

  • Core client: ~8KB gzipped
  • With React hooks: ~12KB gzipped
  • Zero runtime dependencies (axios bundled, zod bundled)

TypeScript

Full TypeScript support with complete type definitions for every API response. All types are exported for use in your own code:

typescript
import type {
  VinDecodeResponse,
  MarketOverview,
  Listing,
  RecallResponse,
  // ... and many more
} from "@cardog/api";

Pricing

We designed pricing to be developer-friendly. Start free, scale as you grow:

PlanRequests/MonthPriceBest For
Free100$0Testing and development
Pro10,000$29/moSmall apps and side projects
Business100,000$199/moProduction applications
EnterpriseUnlimitedCustomHigh-volume integrations

All plans include:

  • Access to all API endpoints
  • Full TypeScript client
  • React Query hooks
  • Email support (priority for Business+)

No credit card required for the free tier. Get your API key at cardog.app.


What Developers Are Building

Since opening up beta access, we have seen developers build some incredible things:

  • Car buying assistants that help users understand if a listing is fairly priced
  • Dealership inventory tools that track market positioning in real-time
  • Fleet management dashboards with recall monitoring
  • Mobile apps that decode VINs from photos
  • Price comparison widgets embedded in marketplace listings
  • Data journalism tools analyzing automotive market trends

We are excited to see what you build.


What is Next

This is v0.1.2, but we are just getting started. On the roadmap:

  • Vehicle history reports - Title status, accident history, ownership records
  • Valuation API - Instant trade-in and retail values
  • Dealer inventory sync - Push your inventory to Cardog
  • Webhook notifications - Get notified when prices change or recalls are issued
  • Python and Go clients - Official clients for more languages

Get Started

  1. Get an API key at cardog.app
  2. Install the client: npm install @cardog/api
  3. Read the docs at docs.cardog.app
  4. View the source at github.com/cardog-ai/api

Questions? Issues? Feature requests? Open an issue on GitHub or reach out to api-support@cardog.ai.

We built Cardog to democratize automotive data. Now that data is available to every developer. We cannot wait to see what you create.

bash
npm install @cardog/api