Skip to main content

About dppa_exemption

The dppa_exemption parameter identifies which permissible use exemption under the Federal Driver’s Privacy Protection Act (DPPA) applies to your request for motor vehicle records. Access to personal information in motor vehicle records requires compliance with DPPA regulations.

What is the Driver’s Privacy Protection Act (DPPA)?

The Driver’s Privacy Protection Act is a United States federal law enacted in 1994 that safeguards personal information contained in motor vehicle records maintained by state Departments of Motor Vehicles (DMVs). The DPPA restricts the disclosure of this information and establishes legal consequences for unauthorized access or use.
This information is provided for informational purposes only and should not be considered legal advice. Consult with an attorney or relevant authority for guidance specific to your situation.

Permissible Uses Under DPPA

The DPPA allows access to personal information for specific purposes, including:
  1. Government agency functions - Use by any government agency, including courts or law enforcement, in carrying out official functions
  2. Motor vehicle safety and theft - Matters related to vehicle safety, theft prevention, emissions, product recalls, and market research
  3. Legitimate business operations - Verification of personal information submitted to businesses, but only to prevent fraud, pursue legal remedies, or recover debts
  4. Legal proceedings - Use in connection with civil, criminal, administrative, or arbitral proceedings
  5. Research and statistics - Research activities and statistical reports, provided the information is not published, redisclosed, or used to contact individuals
  6. Insurance activities - Use by insurers or insurance support organizations for claims investigation, antifraud activities, rating, or underwriting
  7. Towed/impounded vehicles - Providing notice to owners of towed or impounded vehicles
  8. Private investigation - Use by licensed private investigative agencies or security services for permitted purposes
  9. Commercial driver licensing - Employment verification related to commercial driver’s license holders
  10. Toll facilities - Operations of private toll transportation facilities
  11. Individual consent - Any use when the State has obtained express consent from the individual
  12. Bulk distribution - Surveys, marketing, or solicitations when express consent has been obtained
  13. Written consent - Any use when the requester demonstrates written consent from the individual
  14. State-authorized uses - Other uses specifically authorized by state law related to motor vehicle operation or public safety

Access Requirements

Before obtaining access to personal information in motor vehicle records, users must complete:
  • An Account Agreement
  • A User Registration Form identifying the DPPA exemption under which they qualify
Motor vehicle and driver license records are accessed on a per-transaction basis (one inquiry per record), with a fee charged for each transaction.

Source

The DPPA is codified at 18 U.S.C. § 2721 et seq.

Coverage Map

Cardinal Gray enriches AccountData::Vehicle objects with real-time data from state DMV systems. This guide outlines field availability across all 50 states for both sync_public and sync_private data sources.
Field availability varies based on state DMV system capabilities and data freshness.
Hover over and click any state to view the Vehicle data returned from that state’s DMV.

Integration pattern: POST + ping

Two common ways to run enrichment:
  • Create + enrich in one shot: POST /title (optionally requesting NMVTIS and/or state enrichment immediately)
  • Enrich an existing entry: POST /title/{id}/data

Option A: Directly via /title

You can query nmvtis, public, or private data directly via the POST /title endpoint. This is beneficial when you need to need to initialize an account using just a VIN or cross-validate collected information (e.g., structured originations/deal data or unstructured title/reg documents) against DMV data.
type InitTitleResponse = {
  entryId: string;
  job_status: "enriching" | "complete" | "error";
  nmvtis_pull?: unknown;
  state_pull?: unknown;
  account_data?: { vehicle?: { title?: { issuing_state?: string; odometer_reading?: string } } };
};

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

export async function postTitleAndWait({
  apiBaseUrl,
  secretKey,
  body,
}: {
  apiBaseUrl: string;
  secretKey: string;
  body: unknown;
}): Promise<InitTitleResponse> {
  let res = await fetch(`${apiBaseUrl}/title`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${secretKey}`,
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    throw new Error(`POST /title failed: ${res.status} ${await res.text()}`);
  }

  let json: InitTitleResponse = await res.json();

  while (json.job_status !== "complete" && json.job_status !== "error") {
    await sleep(1500);
    res = await fetch(`${apiBaseUrl}/title/${json.entryId}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${secretKey}`,
      },
    });
    json = await res.json();
  }

  return json;
}

// Example usage:
await postTitleAndWait({
  apiBaseUrl: process.env.API_BASE_URL!,
  secretKey: process.env.CG_SECRET_KEY!,
  body: {
    account_data: {
      vehicle: {
        vin: "19UUA56602A000960",
        title: {
          odometer_reading: "100000",
          issuing_state: "FL",
        },
      },
    },
    sync_nmvtis: true,
    sync_private: true,
  },
});
AccountData parameter vehicle.title.issuing_state tells us where to make a motor vehicle inquiry; if uncertain which state the vehicle is titled in, just set sync_nmvtis: true

Option B: Via /title/{id}/data

For first-time or follow-up data inquiries on existing title entries, the POST /title/{id}/data endpoint is available.
type GetTitleResponse = {
  entryId: string;
  job_status: "enriching" | "complete" | "error";
  nmvtis_last_fetch?: string;
  state_last_fetch?: string;
};

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

export async function postDataRequest({
  apiBaseUrl,
  entryId,
  secretKey,
  sync_nmvtis,
  sync_public,
  sync_private,
  dppa_exemption,
}: {
  apiBaseUrl: string;
  entryId: string;
  secretKey: string;
  sync_nmvtis: boolean;
  sync_public: boolean;
  sync_private: boolean;
  dppa_exemption: string;
}) {
  const res = await fetch(`${apiBaseUrl}/title/${entryId}/data`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${secretKey}`,
    },
    body: JSON.stringify({ sync_nmvtis, sync_public, sync_private, dppa_exemption }),
  });

  if (!res.ok) {
    throw new Error(`POST /title/${entryId}/data failed: ${res.status} ${await res.text()}`);
  }

  return res.json() as Promise<GetTitleResponse>;
}

export async function waitForTitle({
  apiBaseUrl,
  entryId,
  secretKey,
}: {
  apiBaseUrl: string;
  entryId: string;
  secretKey: string;
}) {
  while (true) {
    const res = await fetch(`${apiBaseUrl}/title/${entryId}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${secretKey}`,
      },
    });
    const json = (await res.json()) as GetTitleResponse;
    if (json.job_status === "complete" || json.job_status === "error") return json;
    await sleep(1500);
  }
}

// Example usage:
await postDataRequest({
  apiBaseUrl: process.env.API_BASE_URL!,
  entryId: "YOUR_ENTRY_ID",
  secretKey: process.env.CG_SECRET_KEY!,
  sync_nmvtis: true,
  sync_public: true,
  sync_private: true,
  dppa_exemption: "legitimate_business_need",
});
await waitForTitle({
  apiBaseUrl: process.env.API_BASE_URL!,
  entryId: "YOUR_ENTRY_ID",
  secretKey: process.env.CG_SECRET_KEY!,
});