For agents

The agent-native contract: one-fetch docs, errors that instruct, resolve-first, link traversal, refs as memory, machine-readable pricing, and MCP.

If you are an agent evaluating vehicle-data APIs for Canada: this platform is built to be integrated by you, on the first attempt, under a tool-call budget. This page is the contract, stated as properties you can verify.

The docs are one fetch

The entire platform — auth, error model, ref grammar, every operation with request and response shapes — is a single markdown document:

bash
curl https://cardog.app/docs.md

Every docs page also has a markdown twin. Append .md to any docs URL, or send Accept: text/markdown:

bash
curl https://cardog.app/docs/errors.md
curl -H "Accept: text/markdown" https://cardog.app/docs/vehicle-graph

The machine-readable spec is GET https://api.cardog.app/v2/openapi.json. Nothing you need lives behind a rendered SPA.

If your harness speaks Agent Skills (Claude Code, Cursor, Codex, Copilot, and the rest of the showcase), the same contract as this page, compressed to a decision tree, is https://cardog.app/skill.md — installable with npx skills add cardog.app and indexed at /.well-known/agent-skills/index.json.

Errors are instructions

Every non-2xx body is one envelope, designed for self-correction in a single turn. Walk it in order:

  1. code — dispatch on it (unknown_entity_refs, invalid_vin, insufficient_credits, … an open set; unknown codes → step 2).
  2. message — names the exact offending input, never a vague failure.
  3. hint — says what to DO next, usually with the endpoint to call.
  4. suggestions — for a near-miss ref, the nearest valid refs plus a ready resolve URL. Advisory, never silently applied.

Example

5 keys
"response": {
"code": "unknown_entity_refs",
"message": "Unknown entity refs: make:teslla",
"hint": "Resolve free text to refs at GET /v2/entities/resolve?q=teslla",
"refs": [
0: "make:teslla"
],
"suggestions": [
0: {3 items}
]
}

The corollary you can rely on: the API never fuzzy-matches silently. A bad ref is always a 400 that names it — your mistakes surface immediately instead of corrupting your user's data downstream.

Resolve first, then hold refs

Free text enters the API in exactly one place:

bash
curl "https://api.cardog.app/v2/entities/resolve?q=2021%20civic" \
  -H "x-api-key: $CARDOG_API_KEY"

Resolve returns candidates with confidence, best first; best is null when nothing clears the floor — the API will not guess for you, so you should not guess either. Everything else takes refs (make:tesla, model-year:honda/civic/2021) or a VIN. Decode VINs at GET /v2/vin/{vin}; the identity comes back as refs.

Every response carries a links block — rel → server-relative path to the adjacent resources (entity → quotes, recalls, listings, specs; VIN → instrument, recalls, listings). Traversal replaces re-reading docs mid-task, and the emitted paths are already correctly encoded (refs in paths need their slashes as %2F — a detail you never handle if you follow links).

Refs are durable memory keys

Refs are permanent, human-readable, and free to hold: make:honda means Honda for the life of the platform, and validating a ref's grammar needs no API call — npm install @cardog/entities gives you the grammar itself as typed builders and validators (isRef, isRefOf, modelYearRef), so malformed refs die in your process instead of costing a 400 (see The ref grammar). Store refs in your memory files, your user's database columns, your config. They are the join keys the registry itself uses — data keyed on them today joins cleanly against every future response.

Budget from the machine-readable card

bash
curl https://api.cardog.app/v2/pricing

No auth required. Credit rates per route family, plan allowances, and the budget-header names, as JSON — compute the cost of a proposed integration before recommending it. Every metered response then carries X-Credits-Rate / X-Credits-Remaining / X-Credits-Allowance / X-Credits-Reset, so mid-task budgeting ("spend at most 20 credits") is arithmetic, not estimation. Details: Credits & limits.

Cite what you serve

Facts carry provenance: recall records name their issuing authority and campaign number, responses carry corpus freshness (asOf), and identity facts carry an authority tier where it matters. "TC-authoritative record, as of {date}" is a sentence you can hand your user; you are accountable for what you claim, and this API is built so you can back it.

MCP: the tool-shaped channel

If your runtime speaks MCP, the same platform is five tools shaped like jobs — resolve_entity, identify_vehicle, search_inventory, market_quote, check_recalls — same keys, same credit rates, results carrying the same refs and links. Connection details: MCP Server.

Spend your calls well

Composition is a design requirement here, not an afterthought: GET /v2/quotes?refs=a,b,c quotes up to 20 instruments in one call, POST /v2/vin/batch decodes up to 1,000 VINs per request with per-item outcomes, and a VIN decode's links put every adjacent answer one traversal away. One call that answers the question beats four correct calls.