Why Dromo?

Financial data import that reconciles the first time

Import transactions, accounts, and ledgers from CSV and Excel with validation on upload. Catch duplicate IDs, bad routing numbers, and mixed dates. SOC 2 Type II.

View docs

The files your customers actually send

A finance lead at a lending company is moving 18 months of history onto your platform. She has a bank export where every amount is positive and a separate "DR/CR" column says which way the money moved. She has a ledger export from her accounting software that shows negatives in parentheses and repeats a subtotal every few hundred rows. And she has a customer list where every account number lost its leading zeros the moment someone opened the file in Excel. One file writes dates month first and the other day first, so 3/4/2025 is a different day depending on where it came from.

Then there are the columns that cannot be wrong. A routing number with two digits swapped still looks like nine digits. A transaction that appears in two overlapping exports gets counted twice. The currency column says "USD" on most rows, "$" on some, and nothing on the rest. If any of it reaches your ledger, someone spends the next week reconciling by hand, and the customer's first impression of your product is a balance that does not match their bank.

Fields and rules that matter in financial data

Field What goes wrong in real files How Dromo catches it
Transaction ID Duplicates when two exports overlap unique validator, or unique_with across date, amount, and account when the source has no ID
Account number Leading zeros stripped, stray spaces String field with regex_match on the expected length; a column hook trims and pads
Routing number Swapped digits still look valid regex_match for nine digits, plus a column hook that runs the ABA checksum
Amount Currency symbols, thousands separators, parentheses for negatives Number field with the usd preset; a column hook converts parentheses to negatives
Debit or credit The sign lives in a separate column A row hook combines the indicator and the amount into one signed value
Transaction date Day-first and month-first formats from different sources Date parsing with a fixed output format, and mapping memory per source layout
Currency "USD", "$", "us dollars", or blank Select field of ISO codes; bulk fix maps the variants in one step
Tax ID SSNs and EINs mixed, with and without dashes ssn field type for individuals; regex_match for nine-digit EINs
Category Free text that differs for every customer Select field with allowed values, remembered for the next upload

A working transactions schema

{
  "fields": [
    {
      "label": "Transaction ID",
      "key": "transaction_id",
      "type": "string",
      "validators": [{ "validate": "required" }, { "validate": "unique" }]
    },
    {
      "label": "Account number",
      "key": "account_number",
      "type": "string",
      "validators": [
        { "validate": "required" },
        { "validate": "regex_match", "regex": "^\\d{4,17}$", "errorMessage": "Account numbers are 4 to 17 digits" }
      ]
    },
    {
      "label": "Routing number",
      "key": "routing_number",
      "type": "string",
      "validators": [
        { "validate": "regex_match", "regex": "^\\d{9}$", "errorMessage": "Routing numbers are 9 digits" }
      ]
    },
    {
      "label": "Transaction date",
      "key": "transaction_date",
      "type": ["date", { "outputFormat": "YYYY-MM-DD" }],
      "validators": [{ "validate": "required" }]
    },
    {
      "label": "Amount",
      "key": "amount",
      "type": ["number", { "preset": "usd" }],
      "validators": [{ "validate": "required" }]
    },
    {
      "label": "Currency",
      "key": "currency",
      "type": "select",
      "selectOptions": [
        { "label": "USD", "value": "USD" },
        { "label": "EUR", "value": "EUR" },
        { "label": "GBP", "value": "GBP" },
        { "label": "CAD", "value": "CAD" }
      ]
    }
  ]
}

The routing checksum and the debit and credit merge are hooks rather than static validators, because they need logic beyond a single pattern. Column hooks can also be async, so the same import can confirm that each account number already exists in your system before the user submits. Schema Studio lets a product manager maintain the field list, the allowed categories, and the error messages from a form, without a deploy.

Security for financial data

Financial files carry account numbers, tax IDs, and balances, and your customers' security teams review every vendor that touches them. Dromo has completed a SOC 2 Type II audit, and the report is available through the Trust Center.

The stronger answer is that Dromo does not need to touch the data at all. In Private Mode, the default, the file is parsed and validated in the user's browser and the results go straight to your application. AI column matching runs in a headers-only mode: Dromo sees column names and the distinct values of select fields, such as currency codes, never account numbers or amounts. 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 for data residency. See how Private Mode works.

Recurring files from banks and partners

Not every file comes from a person. Banks, processors, and lending partners send statements and settlement files on a schedule, often over SFTP, in a layout that drifts a little each quarter. On the Enterprise plan, the headless data importer runs those files through the same schema automatically, over the API or SFTP.

A file that passes comes back as clean JSON. A file with a renamed column or failing rows stops in NEEDS_REVIEW with a review link, which you send to whoever owns that partner relationship, instead of posting bad entries to the ledger and finding out at month end.

Connect it to your ledger

When a user finishes an embedded import, the onResults callback receives JSON in which every date is ISO, every amount is a signed number, and every currency is a known code. Your backend can write it straight to the ledger tables. For imports that must be recorded server-side regardless of what happens in the browser, configure a webhook in the Dromo dashboard and fetch the results from a presigned URL.

For more on what fintech buyers expect from onboarding, see fintech data onboarding: compliance, speed, and accuracy.

What Our Customers Say

G2 High Performer Award 2025 badge for Dromo
4.9 out of 5 stars
5 out of 5 stars
Ryan Chan logo
Ryan Chan
CEO at Upkeep.com
E&Y Entrepreneur of the Year finalist
"We have now rolled out Dromo across our entire customer onboarding experience, and it has made our lives so much easier. Most importantly, our customers love the new experience!"

FAQ

Frequently asked questions

  • Yes. Values are validated as the file loads and again as the user edits, with errors shown inline before anything is submitted. Async column hooks can check values against your own API, such as confirming that an account exists.
  • Not in Private Mode, the default. The file is processed in the user's browser and the results go straight to your application. AI column matching sees only column names and the distinct values of select fields.
  • Yes. The set header step handles title rows, AI matches renamed columns, mapping memory remembers each source's layout, and hooks normalize parentheses and separate debit and credit columns.
  • Yes, on the Enterprise plan. The Headless API and SFTP run recurring files through the same schema and send a review link when a file needs a person.

Ready to Ship a Better Data Import Experience?

AI-powered mapping. Real-time validation. SOC 2 certified. Deploys in minutes.