Recalls Batch API
Check thousands of vehicles for safety recalls in a single batch by submitting VINs and polling for results.
The Recalls Batch API allows you to submit up to 10,000 VINs in a single request for bulk recall checking. Unlike the standard Vehicle Recalls API which checks one VIN at a time, the batch API is designed for high-volume operations like fleet management, dealership inventory scans, and wholesale auction processing.
The Recalls Batch API is asynchronous: submit your VINs, poll for status (or use a webhook), then retrieve results when the job is completed or partial. VINs that are not already in CarsXE cache are queued for full batch processing; turnaround is typically 30-60 minutes depending on batch size and system load.
How It Works
- Submit — POST your VINs (JSON array, inline CSV, or HTTPS URL to a CSV). You get a
batchIdimmediately. The HTTP status is 202 Accepted when the batch is accepted. - Poll — Call the status endpoint with
batchIduntil status iscompleted,partial, orfailed(or wait for your customer webhook). - Retrieve — GET results as JSON or download CSV from
/v1/recalls-batch/download.
Caching: VINs that were checked recently may be served from cache. If every VIN in the batch is cached, the submit response can already show status: "completed" with full processedVins and 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.
Step 1: Submit a Batch
Send a POST request with VINs to start a batch recall check. You can provide VINs in three ways — use whichever is most convenient, or even combine them:
Input methods (provide at least one)
- Name
vins- Type
- string[]
- Description
JSON array of 17-character VIN strings.
- Name
csv- Type
- string
- Description
Inline CSV text containing VINs (one per line, or a single
vincolumn).
- Name
csvUrl- Type
- string
- Description
HTTPS URL to a CSV file containing VINs. Supported hosts: Google Sheets, Google Cloud Storage, AWS S3, Dropbox, Azure Blob, DigitalOcean Spaces, and Box. Google Sheets sharing links and Dropbox sharing links are auto-converted to direct download format. Max file size: 5 MB.
You can combine input methods — for example, pass some VINs in vins and a csvUrl for the rest. All VINs are merged and deduplicated before processing. The combined total must not exceed 10,000.
Required query parameter
- Name
key- Type
- string
- Description
Your CarsXE API key (query parameter). Official SDKs may send the same key in the
x-api-keyheader instead.
Optional attributes
- Name
webhookUrl- Type
- string
- Description
HTTPS URL for a customer webhook: CarsXE POSTs a JSON payload when the batch finishes (see Webhook notifications). Must be a valid HTTPS URL allowed by CarsXE validation rules.
Submit response
Successful submission returns HTTP 202 with:
- Name
success- Type
- boolean
- Description
truewhen the batch was accepted.
- Name
data.batchId- Type
- string
- Description
Unique identifier for your batch. Use this for status, results, and download.
- Name
data.status- Type
- string
- Description
uploading(batch being prepared),processing(recall check in progress), orcompletedif all VINs were satisfied from cache.
- Name
data.totalVins- Type
- number
- Description
Number of unique VINs in the batch (after deduplication).
- Name
data.processedVins- Type
- number
- Description
VINs already reflected in this response (e.g. cache hits); increases again when the batch completes.
- Name
data.hitCount- Type
- number
- Description
Count of VINs with at least one safety recall (aligned with
hasRecallson results).
- Name
data.hitRate- Type
- number
- Description
Percentage
(hitCount / processedVins) × 100when processing is done; may be0on the initial 202 until completion.
- Name
data.createdAt- Type
- string
- Description
ISO 8601 timestamp when the batch was created.
- Name
data.updatedAt- Type
- string
- Description
ISO 8601 timestamp of the last job update.
Request — JSON array
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=CARSXE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"vins": [
"1HGBH41JXMN109186",
"5YJSA1E26HF000001",
"1C4JJXR64PW696340"
],
"webhookUrl": "https://your-server.com/webhook"
}'Request — CSV URL
# Google Sheets sharing link (auto-converted to CSV export)
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=CARSXE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csvUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit"
}'
# AWS S3 signed URL
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=CARSXE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csvUrl": "https://my-bucket.s3.amazonaws.com/vins.csv?X-Amz-Signature=..."
}'
# Dropbox sharing link (auto-converted to direct download)
curl -X POST "https://api.carsxe.com/v1/recalls-batch/submit?key=CARSXE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csvUrl": "https://www.dropbox.com/s/abc123/vins.csv"
}'Response (202 Accepted)
{
"success": true,
"data": {
"batchId": "brb_mnablbn7_wvbaqv",
"status": "uploading",
"totalVins": 3,
"processedVins": 0,
"hitCount": 0,
"hitRate": 0,
"createdAt": "2026-03-24T10:00:00.000Z",
"updatedAt": "2026-03-24T10:00:00.000Z"
},
"message": "Batch submitted and queued for processing. Poll the status endpoint or wait for webhook notification."
}Step 2: Check Status
Poll the status endpoint to check if your batch has finished processing.
Required attributes
- Name
key- Type
- string
- Description
Your CarsXE API key.
- Name
batchId- Type
- string
- Description
The batch ID returned from the submit endpoint.
Status values
| Status | Description |
|---|---|
pending | Reserved for future use; batches created through this API typically start as uploading or completed. |
uploading | Batch accepted; CarsXE is preparing the batch for processing. |
processing | Recall check in progress. Poll every 30–60 seconds. |
completed | All VINs processed. Results are ready. |
partial | Results available, but fewer VIN rows were returned than totalVins (treat as complete for retrieval). |
failed | Processing failed. See errorMessage. |
Status response attributes
- Name
data.batchId- Type
- string
- Description
The batch identifier.
- Name
data.numericBatchId- Type
- number
- Description
Optional numeric correlation id assigned when results are finalized.
- Name
data.status- Type
- string
- Description
Current processing status (see table above).
- Name
data.totalVins- Type
- number
- Description
Total VINs submitted in this batch.
- Name
data.processedVins- Type
- number
- Description
Number of VINs with rows in the merged result set.
- Name
data.hitCount- Type
- number
- Description
VINs with at least one safety recall.
- Name
data.hitRate- Type
- number
- Description
Percentage of processed VINs with a safety recall hit (0–100, two decimal places).
- Name
data.completedAt- Type
- string
- Description
ISO 8601 timestamp when processing finished (
undefined/ omitted while in progress).
- Name
data.errorMessage- Type
- string
- Description
Error details if status is
failed.
Request
curl -G "https://api.carsxe.com/v1/recalls-batch/status" \
-d key=CARSXE_API_KEY \
-d batchId=brb_mnablbn7_wvbaqvResponse
{
"success": true,
"data": {
"batchId": "brb_mnablbn7_wvbaqv",
"numericBatchId": 200426,
"status": "completed",
"totalVins": 3,
"processedVins": 3,
"hitCount": 2,
"hitRate": 66.67,
"createdAt": "2026-03-24T10:00:00.000Z",
"updatedAt": "2026-03-24T10:16:43.000Z",
"completedAt": "2026-03-24T10:16:43.000Z",
"errorMessage": null
}
}Step 3: Retrieve Results
Once the batch status is completed or partial, fetch full recall rows as JSON or download CSV.
Required attributes
- Name
key- Type
- string
- Description
Your CarsXE API key.
- Name
batchId- Type
- string
- Description
The batch ID returned from the submit endpoint.
Results shape
Each VIN has vin, hasRecalls (true if there is at least one safety recall), recallCount, and recalls — an array of sparse objects in camelCase, mirroring CarsXE’s bulk recall row layout:
- Only non-empty string fields and booleans are included per recall.
- Dealer and batch metadata (
dealerName,dealerCode, batch name/date fields) are not exposed in JSON.
Common keys include (when present): recallNhtsaNumber, recallOemNumber, recallTitle, recallDescription, recallRiskDescription, recallRemedyDescription, recallType, recallState, recallStatus, recallIssueDate, recallRefreshDate, severityCode, vehicleYear, vehicleMake, vehicleModel, isRemedied, optional field1–field10, etc. See the @carsxe/shared type BulkRecallBatchRow for the full schema; the API returns the trimmed BulkRecallBatchRowApi projection.
CSV download
GET /v1/recalls-batch/download with the same key and batchId. Returns text/csv with a Content-Disposition filename. You can also build the URL with getBulkRecallBatchDownloadUrl (JS) or get_bulk_recall_batch_download_url (Python).
Request — JSON
curl -G "https://api.carsxe.com/v1/recalls-batch/results" \
-d key=CARSXE_API_KEY \
-d batchId=brb_mnablbn7_wvbaqvRequest — CSV download
curl -G "https://api.carsxe.com/v1/recalls-batch/download" \
-d key=CARSXE_API_KEY \
-d batchId=brb_mnablbn7_wvbaqv \
-o recalls_brb_mnablbn7_wvbaqv.csvResponse — JSON (illustrative)
{
"success": true,
"data": {
"job": {
"batchId": "brb_mnablbn7_wvbaqv",
"numericBatchId": 200426,
"status": "completed",
"totalVins": 3,
"processedVins": 3,
"hitCount": 2,
"hitRate": 66.67,
"createdAt": "2026-03-24T10:00:00.000Z",
"completedAt": "2026-03-24T10:16:43.000Z"
},
"results": [
{
"vin": "1HGBH41JXMN109186",
"hasRecalls": true,
"recallCount": 1,
"recalls": [
{
"recallNhtsaNumber": "20V123000",
"vehicleMake": "Honda",
"recallTitle": "Passenger frontal air bag inflator",
"recallDescription": "Takata front passenger air bag inflator may rupture.",
"recallRiskDescription": "Rupture may cause injury from metal fragments.",
"recallRemedyDescription": "Dealers will replace the inflator, free of charge.",
"recallType": "Safety",
"recallStatus": "Open",
"recallIssueDate": "2020-03-15",
"isRemedied": false
}
]
},
{
"vin": "5YJSA1E26HF000001",
"hasRecalls": false,
"recallCount": 0,
"recalls": []
}
]
}
}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. The request times out on CarsXE’s side after about 30 seconds — respond quickly on your server.
{
"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 yourself. Your API key is not repeated as a separate JSON field.
Complete example: submit, poll, and retrieve
Full workflow
import { CarsXE } from "@carsxe/sdk";
const carsxe = new CarsXE({ apiKey: "CARSXE_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)`);
}
}
}Error responses
| Status | Error | Description |
|---|---|---|
| 400 | BULK_RECALL_BATCH_MISSING_VINS | No VINs provided. Supply vins, csv, or csvUrl. |
| 400 | BULK_RECALL_BATCH_TOO_MANY_VINS | Combined VIN count exceeds 10,000. |
| 400 | BULK_RECALL_BATCH_INVALID_VIN | One or more VINs are not 17 valid characters. |
| 400 | BULK_RECALL_BATCH_CSV_URL_INVALID | The csvUrl is not a valid HTTPS URL. |
| 400 | BULK_RECALL_BATCH_CSV_URL_HOST_NOT_ALLOWED | The csvUrl host is not allowed. |
| 400 | BULK_RECALL_BATCH_CSV_URL_TOO_LARGE | The CSV at csvUrl exceeds the size limit (5 MB). |
| 400 | BULK_RECALL_BATCH_CSV_URL_NOT_TEXT | The URL did not return a plain text CSV. |
| 400 | BULK_RECALL_BATCH_CSV_URL_HTTP_ERROR | The storage server returned an HTTP error (e.g. expired signed URL). |
| 400 | BULK_RECALL_BATCH_CSV_URL_REDIRECT_ERROR | Too many redirects or an invalid redirect when fetching csvUrl. |
| 400 | BULK_RECALL_BATCH_CSV_URL_TIMEOUT | Downloading the CSV from csvUrl timed out. |
| 400 | BULK_RECALL_BATCH_INVALID_WEBHOOK_URL | The webhookUrl is not a valid allowed HTTPS URL. |
| 401 | MISSING_API_KEY | No API key provided. |
| 401 | USER_NOT_FOUND | Invalid API key. |
| 401 | USER_NOT_ACTIVE | Account is not active. |
| 404 | BULK_RECALL_BATCH_NOT_FOUND | Batch not found or you don't have access. |
| 405 | ONLY_POST_ALLOWED | Submit endpoint requires POST. |
| 409 | BULK_RECALL_BATCH_NOT_COMPLETE | Batch still processing (results/download only). |
| 429 | (usage message) | Plan or usage limit exceeded (when usage metering applies). |
| 500 | BULK_RECALL_BATCH_STORAGE_ERROR | Internal storage or batch handoff error. Retry later. |
| 502 | BULK_RECALL_BATCH_CSV_URL_FETCH_FAILED | Server could not fetch the CSV from csvUrl. |