CarsXECarsXE

Submit up to 10,000 VINs in one request for bulk recall checking. Unlike the single-VIN Recalls API, this endpoint is built for high-volume workflows — fleet management, dealership inventory scans, and wholesale auction processing.

Recalls Batch is asynchronous: submit your VINs, poll for status (or use a webhook), then retrieve results when the job is completed or partial. Uncached VINs are queued for full processing; turnaround is typically 30–60 minutes depending on batch size and load.

How it works

  1. SubmitPOST VINs (JSON array, inline CSV, or HTTPS URL to a CSV). You receive a batchId immediately (202 Accepted).
  2. Poll — Call the status endpoint with batchId until completed, partial, or failed (or wait for your customer webhook).
  3. RetrieveGET results as JSON, or download CSV from /v1/recalls-batch/download.

Caching: Recently checked VINs may be served from cache. If every VIN in the batch is cached, the submit response can already show status: "completed" with full processedVins — no uploading / processing phase.

Full processing path: Uncached VINs move through uploading, then processing, while CarsXE prepares and runs the batch; results are written when processing finishes.

For interactive try-it-live, see the API Reference.

Parameters

Provide at least one of vins, csv, or csvUrl. You can combine them — all VINs are merged and deduplicated. The combined total must not exceed 10,000.

ParameterRequiredDescription
vinsNo*JSON array of 17-character VIN strings
csvNo*Inline CSV text (one VIN per line, or a single vin column)
csvUrlNo*HTTPS URL to a CSV file (max 5 MB). Supported hosts: Google Sheets, Google Cloud Storage, AWS S3, Dropbox, Azure Blob, DigitalOcean Spaces, and Box. Google Sheets and Dropbox sharing links are auto-converted to direct download
webhookUrlNoHTTPS URL for a customer webhook when the batch finishes
keyYesYour CarsXE API key (query parameter; official SDKs may send x-api-key instead)

* At least one of vins, csv, or csvUrl is required.

Step 1: Submit a batch

Submit a batch

Code
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vins": [
      "1HGBH41JXMN109186",
      "5YJSA1E26HF000001",
      "1C4JJXR64PW696340"
    ],
    "webhookUrl": "https://your-server.com/webhook"
  }'

Submit with a CSV URL

# Google Sheets sharing link (auto-converted to CSV export)
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "csvUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit"
  }'

Submit response fields

Successful submission returns HTTP 202 with:

Step 2: Check status

Poll until the batch reaches a terminal state. Recommended interval: every 30–60 seconds while uploading or processing.

StatusDescription
pendingReserved for future use; batches from this API typically start as uploading or completed
uploadingBatch accepted; CarsXE is preparing it for processing
processingRecall check in progress
completedAll VINs processed; results are ready
partialResults available, but fewer VIN rows than totalVins (treat as complete for retrieval)
failedProcessing failed; see errorMessage

Check batch status

Code
curl -G "https://api.carsxe.com/v1/recalls-batch/status" \
  -d key=YOUR_API_KEY \
  -d batchId=brb_mnablbn7_wvbaqv

Status response fields

Step 3: Retrieve results

Once status is completed or partial, fetch full recall rows as JSON or download CSV.

Get results (JSON)

Code
curl -G "https://api.carsxe.com/v1/recalls-batch/results" \
  -d key=YOUR_API_KEY \
  -d batchId=brb_mnablbn7_wvbaqv

Results shape

Each VIN has vin, hasRecalls (true if there is at least one safety recall), recallCount, and recalls — an array of sparse camelCase objects:

Common keys when present: recallNhtsaNumber, recallOemNumber, recallTitle, recallDescription, recallRiskDescription, recallRemedyDescription, recallType, recallState, recallStatus, recallIssueDate, severityCode, vehicleYear, vehicleMake, vehicleModel, isRemedied.

CSV download

GET /v1/recalls-batch/download with the same key and batchId. Returns text/csv with a Content-Disposition filename. SDKs also expose a download URL helper (getBulkRecallBatchDownloadUrl / get_bulk_recall_batch_download_url).

curl -G "https://api.carsxe.com/v1/recalls-batch/download" \
  -d key=YOUR_API_KEY \
  -d batchId=brb_mnablbn7_wvbaqv \
  -o recalls_brb_mnablbn7_wvbaqv.csv

Webhook notifications

If you pass webhookUrl on submit, CarsXE sends an HTTPS POST with Content-Type: application/json when the batch reaches a terminal state (completed or partial). Redirects are not followed. Respond quickly — the request times out on CarsXE’s side after about 30 seconds.

{
  "event": "bulk_recall_batch_complete",
  "batchId": "brb_mnablbn7_wvbaqv",
  "status": "completed",
  "totalVins": 100,
  "processedVins": 100,
  "hitCount": 25,
  "hitRate": 25,
  "downloadUrl": "https://api.carsxe.com/v1/recalls-batch/download?key=…&batchId=…",
  "timestamp": "2026-03-24T10:16:43.000Z"
}

The downloadUrl includes your API key in the query string so you can fetch the CSV without assembling the URL. Your API key is not repeated as a separate JSON field.

Complete example: submit, poll, and retrieve

Full workflow

Code
import { CarsXE } from "carsxe-api";

const carsxe = new CarsXE("YOUR_API_KEY");

const submitResponse = await carsxe.submitBulkRecallBatch({
  vins: [
    "1HGBH41JXMN109186",
    "5YJSA1E26HF000001",
    "1C4JJXR64PW696340",
  ],
});
const batchId = submitResponse.data?.batchId;
if (!batchId) throw new Error("No batchId");
console.log(`Batch submitted: ${batchId}`);

let status;
do {
  await new Promise((r) => setTimeout(r, 30_000));
  status = await carsxe.getBulkRecallBatchStatus(batchId);
  console.log(`Status: ${status.data?.status}`);
} while (
  status.data?.status === "processing" ||
  status.data?.status === "uploading"
);

if (status.data?.status === "completed" || status.data?.status === "partial") {
  const results = await carsxe.getBulkRecallBatchResults(batchId);
  console.log(`Processed: ${results.data?.job.processedVins} VINs`);
  console.log(`Safety recall hits: ${results.data?.job.hitCount}`);

  for (const result of results.data?.results ?? []) {
    if (result.hasRecalls) {
      console.log(`${result.vin}: ${result.recallCount} recall row(s)`);
    }
  }
}

Errors

StatusWhen it happens
400Missing VINs, too many VINs (>10,000), invalid VIN, invalid/disallowed/oversized csvUrl, or invalid webhookUrl
401Missing or invalid API key, or inactive account
404Batch not found or you don't have access
405Submit called with a method other than POST
409Batch still processing (results/download only)
429Usage limit exceeded
500Internal storage or batch handoff error — retry later
502Server could not fetch the CSV from csvUrl

See the Errors guide for general error handling guidance.