@@ -14,6 +14,7 @@ If you want copyable success / failure / header-invalid response shapes, see
1414
1515The most important public result objects are:
1616
17+ - ` ImportPreflightResult `
1718- ` ImportResult `
1819- ` CellErrorMap `
1920- ` RowIssueMap `
@@ -302,6 +303,100 @@ response = {
302303}
303304```
304305
306+ ## ` ImportPreflightResult `
307+
308+ ` ImportPreflightResult ` is the high-level summary of one lightweight structural
309+ preflight run.
310+
311+ Useful fields include:
312+
313+ - ` status `
314+ Overall status such as ` VALID ` , ` HEADER_INVALID ` , ` SHEET_MISSING ` , or
315+ ` STRUCTURE_INVALID ` .
316+ - ` sheet_name `
317+ The configured worksheet name used for preflight.
318+ - ` sheet_exists `
319+ Whether the configured worksheet was found.
320+ - ` has_merged_header `
321+ Whether the header block was detected as merged when readable.
322+ - ` estimated_row_count `
323+ Estimated number of data rows for a later import run.
324+ - ` structural_issue_codes `
325+ Stable machine-readable codes for non-header structural failures.
326+
327+ Typical usage:
328+
329+ ``` python
330+ result = alchemy.preflight_import(' employees.xlsx' )
331+
332+ if result.is_valid:
333+ ...
334+ ```
335+
336+ Use preflight when you need a quick structural gate before the real import.
337+
338+ Practical cases:
339+
340+ - reject uploads that are missing the target sheet
341+ - stop early when headers do not match the schema
342+ - show a lightweight “looks importable” response before running row validation
343+
344+ Do not treat preflight as a replacement for ` import_data(...) ` .
345+
346+ Preflight does not do:
347+
348+ - row-level validation
349+ - create / update execution
350+ - cell or row error collection
351+ - result workbook generation
352+
353+ Useful helpers:
354+
355+ - ` is_valid `
356+ - ` is_header_invalid `
357+ - ` is_sheet_missing `
358+ - ` is_structure_invalid `
359+ - ` to_api_payload() `
360+
361+ Example payload:
362+
363+ ``` json
364+ {
365+ "status" : " HEADER_INVALID" ,
366+ "is_valid" : false ,
367+ "is_header_invalid" : true ,
368+ "is_sheet_missing" : false ,
369+ "is_structure_invalid" : false ,
370+ "sheet" : {
371+ "name" : " Sheet1" ,
372+ "exists" : true ,
373+ "has_merged_header" : false
374+ },
375+ "summary" : {
376+ "estimated_row_count" : 3 ,
377+ "structural_issue_codes" : []
378+ },
379+ "header_issues" : {
380+ "is_required_missing" : true ,
381+ "missing_required" : [" Age" ],
382+ "missing_primary" : [],
383+ "unrecognized" : [" Unexpected Column" ],
384+ "duplicated" : []
385+ }
386+ }
387+ ```
388+
389+ Simple workflow:
390+
391+ ``` python
392+ preflight = alchemy.preflight_import(' employees.xlsx' )
393+
394+ if not preflight.is_valid:
395+ return {' preflight' : preflight.to_api_payload()}
396+
397+ result = await alchemy.import_data(' employees.xlsx' , ' employees-result.xlsx' )
398+ ```
399+
305400This gives you:
306401
307402- a stable top-level import summary
0 commit comments