The files your customers actually send
An agency is moving onto your platform from the management system it has used for a decade. The policy export lists the same carrier as "Northline Mutual", "Northline Mut. Ins.", and "NLM". Premiums carry dollar signs and commas. Effective and expiration dates use two formats, and a few policies expire before they start because someone swapped the columns years ago. Policy numbers are unique per carrier, not across the book, so the same number appears under two different carriers.
The benefits team sends something harder. An employer census for a group quote lists employees and dependents, sometimes on one row and sometimes on several. Coverage tier reads "EE", "EE+SP", "Employee + Spouse", and "Family". Dates of birth decide the rate, so a birth year typed as 2085 is a pricing error, not a typo. And every month, each managing general agent sends a bordereau in its own layout, with a column added or renamed whenever their system changes.
Fields and rules that matter in insurance
| Field | What goes wrong in real files | How Dromo catches it |
|---|---|---|
| Policy number | Repeats across carriers in one book | unique_with on policy number and carrier together |
| Carrier | The same company spelled five ways | Select field of carriers; bulk fix maps every variant in one step |
| Effective and expiration dates | Mixed formats, expiration before effective | Date parsing with a fixed output format; a row hook rejects expiration dates before the effective date |
| Premium | Dollar signs, commas, blanks | Number field with the usd preset, required on active policies |
| Line of business | Abbreviations and internal codes | Select field with allowed values, remembered for the next upload |
| Insured state | Full names, abbreviations, typos | us-state-territory field type |
| Date of birth | Impossible years that change the rate | Date parsing plus a row hook that flags ages outside your rating range |
| Coverage tier | "EE", "EE+SP", "Employee + Spouse", "Family" | Select field with allowed values; bulk fix maps the variants |
| SSN | With and without dashes, nine digits missing one | ssn field type |
| Zip code | Leading zeros lost in Excel | us-zip-code field type |
A working policy schema
{
"fields": [
{
"label": "Policy number",
"key": "policy_number",
"type": "string",
"validators": [
{ "validate": "required" },
{ "validate": "unique_with", "uniqueKey": "carrier_policy", "errorMessage": "This policy number already appears for this carrier" }
]
},
{
"label": "Carrier",
"key": "carrier",
"type": "select",
"selectOptions": [
{ "label": "Northline Mutual", "value": "northline" },
{ "label": "Harbor Casualty", "value": "harbor" },
{ "label": "Summit Specialty", "value": "summit" }
],
"validators": [
{ "validate": "required" },
{ "validate": "unique_with", "uniqueKey": "carrier_policy" }
]
},
{
"label": "Effective date",
"key": "effective_date",
"type": ["date", { "outputFormat": "YYYY-MM-DD" }],
"validators": [{ "validate": "required" }]
},
{
"label": "Expiration date",
"key": "expiration_date",
"type": ["date", { "outputFormat": "YYYY-MM-DD" }],
"validators": [{ "validate": "required" }]
},
{
"label": "Annual premium",
"key": "premium",
"type": ["number", { "preset": "usd" }]
},
{
"label": "Line of business",
"key": "line_of_business",
"type": "select",
"selectOptions": [
{ "label": "Commercial auto", "value": "commercial_auto" },
{ "label": "General liability", "value": "general_liability" },
{ "label": "Workers compensation", "value": "workers_comp" },
{ "label": "Property", "value": "property" }
]
},
{ "label": "Insured state", "key": "insured_state", "type": "us-state-territory" }
]
}
The date order check is a row hook because it compares two fields in the same row and runs again whenever the user edits either one. Schema Studio lets a product manager add a carrier or a line of business from a form, so the list keeps up with the agencies you sign without a deploy.
Security for policyholder and health data
Insurance files are some of the most sensitive data a SaaS product handles: Social Security numbers, birth dates, and in benefits and claims files, protected health information. Dromo has completed a SOC 2 Type II audit and signs Business Associate Agreements for HIPAA. The report is available through the Trust Center.
In Private Mode, the default, the census or policy file is parsed and validated in the user's browser and the results go straight to your application, so Dromo never receives the rows. AI column matching runs in a headers-only mode that shares column names and the distinct values of select fields, such as coverage tiers, never names, SSNs, or birth dates. On the Enterprise plan, Bring Your Own Storage writes import data directly to your own S3, Google Cloud Storage, or Azure bucket, and the full stack can be self-hosted in your cloud. See how Private Mode works.
Automate bordereaux and carrier files
Monthly bordereaux, carrier downloads, and loss runs arrive on a schedule with nobody watching. On the Enterprise plan, the headless data importer takes them over the API or SFTP and runs each one through the same schema your users see in the browser.
When an MGA renames a column or a batch of rows fails validation, the import stops in NEEDS_REVIEW with a review link instead of loading bad premiums into your book. Send the link to whoever manages that partner, fix the file in the importer, and the import completes. One schema covers the agency that uploads by hand and the partner that sends files every month.
Connect it to rating and policy systems
When a user finishes an embedded import, the onResults callback receives JSON in which every carrier is a known value, every date is ISO, and every premium is a number. Your backend can write policies to your system of record or pass a clean census to your rating engine in one step. For imports that must be recorded server-side, configure a webhook in the Dromo dashboard and fetch the results from a presigned URL.

