@cardog/api

中文文档
3.4.0发布于 2026/11/06MITTypeScriptESM + CJS近 30 天下载 2734

TypeScript client for the Cardog API — Canadian VIN decode, vehicle specs, live listings, market quotes, and Transport Canada + NHTSA recalls.

原始使用文档
文档目录21 节
  1. Installation
  2. Quick start
  3. Feeds
  4. React Hooks
  5. API Reference
  6. VIN Decoding
  7. Market Analysis
  8. Vehicle Listings
  9. Safety Recalls
  10. Research & Specs
  11. Fuel & Charging
  12. Locations
  13. EPA Efficiency
  14. NHTSA Complaints
  15. Error Handling
  16. Query Keys
  17. Configuration
  18. Pricing
  19. Links
  20. Related Packages
  21. License

@cardog/api

The TypeScript client for the Cardog API — the system of record for the Canadian vehicle. Decode VINs, resolve names to permanent refs, search live Canadian listings, quote the market, and check Transport Canada + NHTSA recalls behind one key.

Installation

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

For React hooks, also install:

npm install @tanstack/react-query

Quick start

import { CardogV2 } from "@cardog/api";

const cardog = new CardogV2({ apiKey: process.env.CARDOG_API_KEY });

// Free text enters exactly once. Everything after this takes refs.
const { best } = await cardog.entities.resolve("2021 Civic");
// best.ref === "model-year:honda/civic/2021"

const vehicle = await cardog.vin.getByVin("2HGFC2F53MH500001");
const recalls = await cardog.recalls.vin("2HGFC2F53MH500001");
const quote = await cardog.quotes.getByRef(best.ref);

Canadian VIN decode coverage is 99.77%. Types, methods, and errors are generated from the same OpenAPI contract the API validates against, so the client cannot drift from the server.

Errors are typed and actionable. Every non-2xx carries { code, message, hint, docs_url, suggestions }. An unknown ref returns a 400 that names it and suggests the nearest real ones — the API never fuzzy-matches you into the wrong vehicle.

import { APIErrorV2 } from "@cardog/api";

try {
  await cardog.listings.search({ filters: { makes: ["make:teslla"] } });
} catch (err) {
  if (err instanceof APIErrorV2) {
    err.code; // "unknown_entity_refs"
    err.hint; // what to do instead
    err.suggestions; // nearest real refs — advisory, never auto-applied
  }
}

Whole platform in one fetch: https://cardog.app/docs.md** Reference: https://cardog.app/docs · Python: pip install cardog · Refs offline: @cardog/entities

Feeds

A feed is an organization's own set of vehicle identity rows, rebuilt every night and handed over as files. Read it with the organization's crdg_org_ key. Every feed read costs 0 credits.

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

const client = new CardogClient({ apiKey: process.env.CARDOG_ORG_KEY });

const { feeds } = await client.v2.feeds.list();

const run = await client.v2.feeds.latest("vehicle-identity@1");
run.runId; // the SHA-256 of the uncompressed full file
run.deliveryId; // the complete delivery context, when present
run.columns; // the files' columns, in order, under the names the organization chose
run.manifest; // kind, baselineRunId, artifacts with record counts and hashes

// Rows, streamed. The file is never held in memory.
for await (const row of run.rows("delta")) {
  // new and changed rows since the run before
}

// Keep your own copy current. Picks the full file or the change file for you,
// checks every file against its SHA-256 first, and returns where you now stand.
const result = await client.v2.feeds.sync("vehicle-identity@1", {
  since: lastRunId, // what the previous sync returned; omit the first time
  sinceDeliveryId: lastDeliveryId, // retain the delivery ID when the result has one
  reset: () => store.clear(),
  upsert: (row) => store.upsert(row),
  remove: (key) => store.remove(key),
});
lastRunId = result.runId; // result.mode is "full", "delta" or "unchanged"
lastDeliveryId = result.deliveryId; // save both IDs only after a successful sync

// Answer a VIN.
const index = await run.index();
const row = index.lookup("2T3W1RFV3SC776931"); // the row, or null when the pattern is not in the feed

run.rows(role), run.toJSON(role) and run.artifact(role) take "full" (the default), "delta" or "deletes". run.artifact(role) is null when the run has no such file. CSV, JSON Lines and JSON runs, plain or gzipped, read the same way in the browser and in Node. Guide: cardog.app/docs/feeds.

The full checksum identifies content. The delivery ID also identifies the contract, baseline and review context. Equal full checksums can have different delivery IDs. For an exact delivery, sync returns unchanged only when both saved IDs match. A delta must match both baseline IDs. If the context is absent or different, sync requires a full reset. An exact record from an older producer can omit the public baseline delivery ID; sync then uses the full file. Legacy feeds retain their existing behavior. currentDeliveryId() returns the current exact ID, or null for a legacy run or no current run.

The sync implementation checks both IDs. The delivery sync tests cover resets, deltas, missed deliveries, and legacy records. Use the MTO stack guide to review the complete producer path.

React Hooks

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

const queryClient = new QueryClient();
const client = new CardogClient({ apiKey: "your-api-key" });
const { useVinDecode, useMarketOverview, useListingsSearch } = createHooks(client);

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

function VehicleLookup() {
  const { data, isLoading, error } = useVinDecode("1HGCM82633A123456");

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

  return (
    <div>
      {data?.make} {data?.model} ({data?.year})
    </div>
  );
}

API Reference

The sections below document the legacy v1 surface (CardogClient). New integrations should use the v2 groups shown in the quick start — CardogV2 (or new CardogClient().v2): entities, vin, specs, listings, instruments, quotes, tape, recalls, safety, feeds, platform — documented in full at cardog.app/docs.

VIN Decoding

// Decode a VIN
const vehicle = await client.vin.decode("1HGCM82633A123456");

// Decode from image (base64)
const result = await client.vin.image(base64Image);

Market Analysis

// Market overview for a specific vehicle
const overview = await client.market.overview("Toyota", "Camry", 2022);

// Price distribution
const pricing = await client.market.pricing("Honda", "Civic", 2021);

// Geographic breakdown
const geography = await client.market.geography("Ford", "F-150", 2023);

// Market trends over time
const trends = await client.market.trends("Tesla", "Model 3", 2022, "month");

// Listing market position
const position = await client.market.position("listing-id");

// Overall market pulse
const pulse = await client.market.pulse({
  priceRangeMin: 20000,
  priceRangeMax: 50000,
});

Vehicle Listings

// Search listings with filters
const results = await client.listings.search({
  makes: ["Toyota", "Honda"],
  models: { Toyota: ["Camry", "Corolla"] },
  year: { min: 2020, max: 2024 },
  price: { min: 15000, max: 40000 },
  odometer: { max: 50000 },
  bodyStyles: ["Sedan", "SUV"],
  fuelTypes: ["Gasoline", "Hybrid"],
});

// Get listing count
const count = await client.listings.count({ makes: ["BMW"] });

// Get facets for filtering UI
const facets = await client.listings.facets({ makes: ["Mercedes-Benz"] });

// Get specific listing
const listing = await client.listings.getById("listing-id");

Safety Recalls

// Search recalls
const recalls = await client.recalls.search({
  country: "us", // or "ca" for Canada
  makes: ["Toyota"],
  models: ["RAV4"],
  year: { min: 2019, max: 2023 },
});

Research & Specs

// Get vehicle lineup for a make
const lineup = await client.research.lineup("Toyota");

// Get model year details
const modelYear = await client.research.modelYear("Toyota", "Camry", 2023);

// Get vehicle images
const images = await client.research.images("Toyota", "Camry", 2023);

// Get available colors
const colors = await client.research.colors("Honda", "Civic", 2024);

Fuel & Charging

// Find gas stations
const gasStations = await client.fuel.search({
  lat: 43.6532,
  lng: -79.3832,
  radius: 10,
  fuelType: "REGULAR",
});

// Find EV charging stations
const chargers = await client.charging.search({
  lat: 43.6532,
  lng: -79.3832,
  radius: 25,
  minPower: 50, // kW
});

Locations

// Search dealer/seller locations
const dealers = await client.locations.search({
  lat: 43.6532,
  lng: -79.3832,
  radius: 50,
});

// Get seller details
const seller = await client.locations.getById("seller-id");

EPA Efficiency

// Search EPA fuel economy data
const efficiency = await client.efficiency.search({
  make: "Toyota",
  model: "Prius",
  year: 2023,
});

NHTSA Complaints

// Search vehicle complaints
const complaints = await client.complaints.search({
  make: "Ford",
  model: "Explorer",
  year: { min: 2020, max: 2023 },
});

Error Handling

Every v2 failure throws APIErrorV2 carrying the full error envelope — code, hint, docsUrl, the offending refs, nearest-ref suggestions, and field-level details. See the quick start above for the idiomatic catch. Legacy v1 routes throw APIError (status / code / message / data).

Query Keys

For manual React Query integration:

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

// Use in custom queries
const { data } = useQuery({
  queryKey: queryKeys.vin.decode("1HGCM82633A123456"),
  queryFn: () => client.vin.decode("1HGCM82633A123456"),
});

// Available key factories
queryKeys.vin.decode(vin)
queryKeys.market.overview(make, model, year)
queryKeys.listings.search(params)
queryKeys.recalls.search(params)
// ... and more

Configuration

const client = new CardogClient({
  apiKey: "your-api-key",
  baseUrl: "https://api.cardog.app", // Default
});

// Update config at runtime
client.setConfig({
  apiKey: "new-api-key",
});

Pricing

Usage is credit-metered per call family, and the price of your next call is in the headers of your last one (X-Credits-Rate, X-Credits-Remaining). The client keeps the last set parsed on client.lastCredits, errors included (a 402 states the budget too), so a budget-aware task never reads raw headers:

await client.v2.vin.getByVin("5YJSA1E28MF420053");
const { rate, remaining, allowance, reset, source } = client.lastCredits!;
// rate: what that call cost · remaining: allowance headroom + pack balance
// (-1 = custom plan) · reset: when the allowance rolls over · source: which
// pool paid ("allowance" | "pack" | "overage"), null when nothing was debited

The machine-readable rate card is a free endpoint — await client.v2.pricing() — and the human one is cardog.app/pricing.

License

MIT

版本与发布记录

@cardog/api 共发布 21 个版本,首次发布于 2026/03/16;过去 12 个月发布了 19 个版本。

版本发布日期距今
3.4.0latest2026/11/063 天前
3.3.02026/11/054 天前
3.2.02026/11/036 天前
3.1.02026/10/2812 天前
3.0.02026/10/2614 天前
2.4.02026/10/2218 天前

关于 @cardog/api 的常见问题

@cardog/api 是什么?

TypeScript client for the Cardog API — Canadian VIN decode, vehicle specs, live listings, market quotes, and Transport Canada + NHTSA recalls.

如何安装 @cardog/api?

在项目目录运行 npm install @cardog/api,或使用 pnpm add / yarn add / bun add。

@cardog/api 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cardog/api 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@cardog/api 可以商用吗?

@cardog/api 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cardog/api 的下载量有多少?

根据 npm 官方下载统计,@cardog/api 在 2026/10/09 – 2026/11/07 这 30 天内被下载 2,734 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cardog/api 还在维护吗?

最新版本 3.4.0 发布于 2026/11/06(3 天前);至今共发布 21 个版本,其中过去 12 个月发布了 19 个;首次发布于 2026/03/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。