CureData, front to back.
A validation workbench in a single page. Upload a file, compose a ruleset, get a report. This page is the reference.
Feed it a file.
CSV is the common case. XLSX works (first sheet, row 1 = headers). JSON is supported as an array of objects. You can also start with a blank schema and type headers directly.
Email,Amount,StartDate,EndDate,State alice@example.com,12.50,2024-01-10,2024-01-12,CA bob@example.com,0,2024-02-01,2024-02-01,WA ,19.99,2024-03-05,2024-03-06,TX
- Header row required.
- Delimiter auto-detects. Quotes + embedded newlines supported.
- Prefer ISO dates (
YYYY-MM-DD). - Numbers should be plain decimal — no currency symbols.
- tipUpload first, then Use detected headers to build a starter schema.
Columns carry rules.
A schema is a named collection of columns. Each column carries 0..n rules. Order does not matter — the engine evaluates in an optimized pass.
{
name: "StartDate",
rules: [
{ type: "type", expected: "date" },
{ type: "noFutureDate" }
]
}{
name: "EndDate",
rules: [
{ type: "type", expected: "date" },
{ type: "dateOrder", otherField: "StartDate", op: ">=" }
]
}How rulesets find your columns.
When you apply a saved ruleset to a new upload, the header_match_strategy controls how strictly names must line up.
| Strategy | Match rule | Example | When |
|---|---|---|---|
| exact | Names match exactly | NPI ⇄ NPI | Internal feeds with stable headers. |
| ci | Case-insensitive | NPI ⇄ npi, Npi | Vendors who only vary casing. |
| fuzzy | Loose match | ProviderNPI ⇄ NPI Number | External files with inconsistent naming. |
One-click presets.
Sample orders.
- 01orderId→requiredtype:stringlength 8–36unique_in_file
- 02email→requiredtype:stringemail
- 03phone→type:stringphoneUS
- 04amount→type:numberrange ≥ 0precision 2
- 05order_date→type:datenoFutureDate
- 06ship_date→type:datedateOrder ≥ order_date
- 07status→enum: Pending · Processing · Shipped · Delivered · Cancelled
- 08ifThen→IF status=Cancelled THEN ship_date blank
- 09state / zip→stateCodeUSzipUS
The full catalog.
Core rules ship built-in. Add as many as needed per column. regex and enum repeat. Cross-field rules like dateOrder and ifThen reference other columns.
| Rule | What it checks | Parameters | Good | Bad |
|---|---|---|---|---|
| required | Value is present (not empty, not null). | — | "ORD-123" | (empty) |
| type:string | Value parses as a string. | expected = string | "hello" | 42 |
| type:number | Value parses as a number. | expected = number | 19.99 | "N/A" |
| type:date | Value parses as a date. | expected = date | 2024-05-01 | "not-a-date" |
| type:boolean | Boolean-ish (true/false, yes/no). | expected = boolean | true | "maybe" |
| length | Text length within bounds. | min, max | length 12 | length 2 |
| enum | Value in the allowed set. | values: [Pending, Processing, Shipped, Delivered, Cancelled] | "Shipped" | "Unknown" |
| regex | Matches a regular expression. | pattern, flags, name | "ORD-202501-0042" | "ORD-Jan-42" |
| range | Number is ≥ min and ≤ max. | min, max, inclusive=true | 0 ≤ amount ≤ 100k | -4 |
| precision | Number has at most N decimals. | scale: 2 | 19.99 | 19.9999 |
| dateOrder | Date compares correctly to another column. | otherField, op: >, ≥, =, ≤, < | ship ≥ order | ship < order |
| noFutureDate | Date is ≤ today. | — | yesterday | next week |
| notExpired | Date is ≥ today. | — | next month | last year |
| ifThen | Conditional rule. IF A THEN B must hold. | if:{…} → then:{…} | IF Cancelled THEN ship blank | Cancelled + ship set |
| Basic email shape. | — | "user@example.com" | "name@@example" | |
| phoneUS | 10-digit US phone, common formats. | — | "(415) 555-0123" | "555-12-1234" |
| stateCodeUS | 2-letter US state postal code. | — | "CA" | "California" |
| zipUS | ##### or #####-####. | — | "94107-1234" | "9410A" |
| Luhn | Passes Luhn checksum. | — | "79927398713" | "79927398710" |
Grammar.
- === equal
- != not equal
- > ≥ ≤ < dates & numbers
- exists present
- blank must be empty
- string length, regex, enum
- number range, precision
- date ISO recommended (YYYY-MM-DD)
- boolean true/false, 1/0, yes/no
Validation context.
Phase 1 runs client-only. A minimal ctx object is passed to custom rules.
const ctx = { now: new Date() }Issues out as CSV.
The workbench exports a CSV of issues. Columns: rowIndex, column, code, message, value.
rowIndex,column,code,message,value 12,Email,required,"Value is required","" 42,Amount,range,"Must be between 0 and 1000","-12"
Troubleshooting.
Can I add multiple regex or enums on a column? +
Yes — regex and enum repeat per column.
Does column order matter? +
No. The engine evaluates in an order-independent optimized pass.
What about cross-row validations? +
Today, unique_in_file covers duplicates. More dataset-level rules ship via packs.
My build shows a Vue/SFC token error. +
This page uses pure templates and computeds — no JSX/TSX — so it compiles cleanly under Nuxt 4 + Vite. If you see one, report it via /contact.