Feed Formats
TruckRadar accepts bulk inventory as XML or CSV for dealers who can't call the REST API directly. The pipeline resolves aliases and converts units, so the feed does not need pre-cleaned data — only the fields documented here. Every field also exists on the JSON API, so you can move between ingestion methods without re-mapping your DMS.
Submission methods
- HTTPS pull — host the feed at a stable URL; TruckRadar fetches on a cron cadence you set (hourly, 4x/day, daily).
- SFTP push — drop into
/inbound/{dealer-slug}/on our SFTP host with credentials you generate. - POST multipart upload — one-off or ad-hoc via the dashboard feeds page.
Contact api@truckradar.ai to provision SFTP credentials or register a scheduled pull URL.
XML format
Root element <inventory> with attributes and child <truck> / <trailer> elements. Attributes on the root are informational; the listing's source_provider_id is set at the feed level when we configure your SourceProvider.
Sample (annotated)
Below is a real record taken from the fixture at public/test-inventory.xml. Each element maps 1:1 to a JSON field in the Inventory API reference.
<?xml version="1.0" encoding="UTF-8"?>
<inventory dealer_id="TEST-DEALER-001"
dealer_name="Test Dealer Group"
exported_at="2026-03-17T14:50">
<truck>
<!-- Universal dedup key. MUST be exactly 17 characters. Pre-1981 serials rejected. -->
<vin>3ALHCYFE3LDLM8435</vin>
<!-- Model year. Range: 1990 to current_year + 2. -->
<year>2020</year>
<!-- Resolved via MakeAlias: FRTLNR, Freightliner Trucks, etc. all normalize. -->
<make>Freightliner</make>
<!-- Resolved via ModelAlias scoped to make. Defaults to "Unknown" if absent. -->
<model>M2 106</model>
<!-- Resolved via CategoryAlias: Refer -> Reefer Truck, Daycab -> Day Cab, etc. -->
<category>Reefer Truck</category>
<!-- truck | trailer. Auto-detected if omitted. -->
<listing_type>truck</listing_type>
<!-- new | used | certified_preowned -->
<new_or_used>used</new_or_used>
<!-- USD dollars. Values under $1,000 rejected as junk. Stored as BIGINT cents. -->
<price>65000</price>
<odometer_miles>144882</odometer_miles>
<engine_make>Cummins</engine_make>
<engine_model>L9</engine_model>
<horsepower>300</horsepower>
<!-- diesel | gasoline | cng | lng | electric | hybrid | hydrogen -->
<fuel_type>diesel</fuel_type>
<!-- manual | automated | automatic -->
<transmission_type>automatic</transmission_type>
<!-- 4x2 | 6x4 | 6x2 | 8x4 | 8x6 -->
<axle_config>6x4</axle_config>
<location_city>Norton</location_city>
<location_state>MA</location_state>
<!-- Free text; cleaned by the enrich stage. -->
<description>8,738 REEFER HOURS AS OF 10/13/2025; MULTI-TEMP</description>
<!-- Array of public image URLs. /pending/ placeholders are skipped. Re-hosted to R2. -->
<photo_urls>
<url>https://cdn.example.com/img/282354/1.jpg</url>
<url>https://cdn.example.com/img/282354/2.jpg</url>
</photo_urls>
</truck>
<!-- Trailers use <trailer> with the same field set; omit engine_* and transmission_*. -->
</inventory>Element cardinality
<vin>,<year>,<make>are required per record.- All other elements are optional but strongly encouraged — they drive quality score and search ranking.
- Unknown elements are preserved on
raw_payloadfor reprocessing but not indexed.
CSV format
Comma-separated, UTF-8, RFC 4180-compliant (quote fields containing ,, ", or newlines). One record per row; first row must be the header.
Recommended header
vin,year,make,model,category,listing_type,new_or_used,price,odometer_miles,engine_make,engine_model,horsepower,fuel_type,transmission_type,axle_config,location_city,location_state,location_zip,description,photo_urlsphoto_urls is semicolon-delimited within a single CSV cell: https://a.com/1.jpg;https://a.com/2.jpg.
Sample row
3ALHCYFE3LDLM8435,2020,Freightliner,"M2 106",Reefer Truck,truck,used,65000,144882,Cummins,L9,300,diesel,automatic,6x4,Norton,MA,02766,"8,738 reefer hours",https://cdn.example.com/img/282354/1.jpg;https://cdn.example.com/img/282354/2.jpgColumn aliases
VIN, Vin, vehicle_identification_number all resolve to vin; Year, model_year, modelYear resolve to year; etc. Prefer snake_case when generating fresh feeds.Normalization rules
The pipeline applies these transforms automatically. Do not pre-apply them in your feed — the canonical values are what the search index is built against.
Alias resolution
- Makes:
FRTLNR→ Freightliner,KW→ Kenworth,Pete→ Peterbilt,INTL/Navistar→ International,W Star→ Western Star. - Categories:
Conventional Sleeper/Sleeper Cab/OTR Sleeper→ Sleeper Truck;Daycab→ Day Cab;Refer/Refrigerated→ Reefer Truck;Van Truck/Box/Straight Truck→ Box Truck. - Models: scoped to make via
ModelAlias(e.g.W900LvsW900).
Unit conversions
- km → miles (÷ 1.60934) when
odometer_kmsupplied - kg → lbs (× 2.20462) for weight fields
- cm → inches (÷ 2.54) for dimensions
- kW → HP (× 1.34102) for engine power
- CAD → USD (× daily FX rate) when
currency=CAD
Hard validation rules
Records that violate these are rejected, not quarantined
failed: N and the per-record error codes are written to the feed run log visible in Dashboard → Feeds.- VIN must be exactly 17 characters. Pre-1981 serial numbers are rejected.
- Year must be between 1990 and current year + 2.
- Price under $1,000 is rejected as junk (treated as “Call for Price”).
- GVWR, if supplied, must be ≥ 10,001 lbs (Class 3 floor). Rows at or below 10,000 lbs are explicitly rejected as consumer vehicles.
- Body type
sedan,suv,coupe,crossover,hatchback,convertible,minivan,wagonare rejected. - Dual-use OEMs (Ford, Chevrolet, GMC, RAM, Dodge) require either an explicit truck class or GVWR ≥ 10,001 lbs, otherwise the record is quarantined for manual review.
Photos
- URLs must be publicly fetchable (HTTP 200 without auth).
- URLs containing
/pending/are skipped silently — DMS placeholder convention. - Originals are re-hosted to Cloudflare R2 under
listings/{id}/original.webp. - A studio-cutout variant is generated at
listings/{id}/studio.webpvia Cloudflare Image Transformations. - Max file size: 70 MB. Max dimension: 12,000 px. Max area: 100 megapixels.
Cadence and freshness
- Feeds are processed in full on each run — send every active unit, not a delta.
- Unseen VINs (present last run, absent this run) are marked
expiredafter 72 hours. - Recommended cadence: every 4 hours or more frequent. Buyers filter stale results aggressively.
- Call
PATCH /api/v1/inventorythe instant a unit sells — don't wait for the next feed run.
See also
- Inventory API — JSON field reference (authoritative).
- Error Codes — remediation per code.
- OpenAPI 3.1 descriptor — machine-readable schema.