The files your customers actually send
A freight brokerage is moving onto your platform. Its shipment history comes from the old TMS with the header on row three, under a report title and a date range. The carrier list has SCAC codes in one column and MC numbers in another, except where someone typed both into the same cell. The rate sheet lists lanes by city name in one tab and by zip code in another. Equipment type reads "53' Dry Van", "DV", "Van", and "Dry". Weights are pounds on most rows and kilograms on the ones from the Canadian carrier.
That is one customer. Every shipper, broker, and carrier they work with has a template of its own, and the templates change whenever a partner upgrades its software. A delivery date earlier than the pickup date, a zip code missing its leading zero, or a load ID that appears twice will each break a dispatch board, a rate quote, or an invoice downstream.
Fields and rules that matter in logistics
| Field | What goes wrong in real files | How Dromo catches it |
|---|---|---|
| Load or shipment ID | Duplicates across overlapping exports | unique validator |
| PRO or BOL number | Spaces, prefixes, and missing digits | String field with regex_match on your expected format |
| SCAC | Lowercase, too long, or mixed with an MC number | regex_match for two to four capital letters; a column hook uppercases and trims |
| MC or DOT number | Prefixes like "MC-" and stray characters | regex_match on digits; a column hook strips the prefix |
| Origin and destination | City names, zips without leading zeros, country missing | us-zip-code and country field types; a column hook resolves city names against your locations |
| Pickup and delivery dates | Mixed formats, delivery before pickup | Date parsing with a fixed output format; a row hook rejects delivery dates before pickup |
| Weight | Pounds and kilograms in the same column | Number field with min; a row hook converts using the unit column |
| Equipment type | "53' Dry Van", "DV", "Van", "Dry" | Select field with allowed values; bulk fix maps every variant in one step |
| Rate | Dollar signs, commas, per-mile and flat rates mixed | Number field with the usd preset; a select field records the rate basis |
| Hazmat | "Y", "Yes", "X", or blank | checkbox field type |
A working shipments schema
{
"fields": [
{
"label": "Load ID",
"key": "load_id",
"type": "string",
"validators": [{ "validate": "required" }, { "validate": "unique" }]
},
{
"label": "Carrier SCAC",
"key": "scac",
"type": "string",
"validators": [
{ "validate": "regex_match", "regex": "^[A-Z]{2,4}$", "errorMessage": "SCAC codes are 2 to 4 capital letters" }
]
},
{ "label": "Origin zip", "key": "origin_zip", "type": "us-zip-code", "validators": [{ "validate": "required" }] },
{ "label": "Destination zip", "key": "destination_zip", "type": "us-zip-code", "validators": [{ "validate": "required" }] },
{
"label": "Pickup date",
"key": "pickup_date",
"type": ["date", { "outputFormat": "YYYY-MM-DD" }],
"validators": [{ "validate": "required" }]
},
{
"label": "Delivery date",
"key": "delivery_date",
"type": ["date", { "outputFormat": "YYYY-MM-DD" }]
},
{
"label": "Equipment type",
"key": "equipment_type",
"type": "select",
"selectOptions": [
{ "label": "Dry van", "value": "dry_van" },
{ "label": "Reefer", "value": "reefer" },
{ "label": "Flatbed", "value": "flatbed" },
{ "label": "Step deck", "value": "step_deck" }
]
},
{ "label": "Weight (lbs)", "key": "weight_lbs", "type": ["number", { "min": 0 }] },
{ "label": "Rate", "key": "rate", "type": ["number", { "preset": "usd" }] },
{ "label": "Hazmat", "key": "hazmat", "type": "checkbox" }
]
}
The date order check and the unit conversion are row hooks because they read two fields in the same row and run again whenever the user edits it. With mapping memory turned on, the second file in a partner's layout is matched automatically, so the work of mapping each template happens once.
One schema for every partner template
Bambi builds AI-powered scheduling, dispatch, routing, and billing software for non-emergency medical transportation, used by more than 700 fleet owners and operators. It moved 23 broker templates, each one carrying protected health information, from OneSchema to Dromo in two weeks, against the six weeks it had scoped.
Templates like these are where homegrown importers break. Dromo treats each partner's layout as a matching problem rather than new code: AI suggests the column matches, a person confirms them once, and mapping memory handles the next file.
Automate recurring carrier and partner files
Tenders, status files, rate updates, and invoices arrive daily from systems with nobody watching. On the Enterprise plan, the headless data importer takes them over the API or SFTP and runs each one against the same schema. When a partner changes its template or a batch of loads fails validation, the import stops in NEEDS_REVIEW with a review link, so a person on your operations team fixes the mapping in the importer instead of an engineer writing a new transform.
Security for shipment and passenger data
Shipment data includes customer addresses, rates, and contract pricing, and healthcare transportation adds protected health information. Dromo has completed a SOC 2 Type II audit and signs Business Associate Agreements for HIPAA. In Private Mode, the default, files are parsed and validated in the user's browser and the results go straight to your application, so Dromo never receives the rows. On the Enterprise plan, Bring Your Own Storage writes import data to your own bucket, and the full stack can be self-hosted in your cloud. See how Private Mode works.

