Import and Copy Records
Validate a CSV against the destination schema before committing it to the chosen development or live store. A commit skips invalid rows and appends valid ones. Copy to live copies development records and overwrites matching record keys.
Use Invoice intake and custom.invoice from Store Workflow Data. That guide creates INV-104. This fixture uses INV-105 and INV-106. Check for existing invoices first because business fields are not uniqueness constraints.
Which store will receive the CSV?
Section titled “Which store will receive the CSV?”In the app: open Workflows → Invoice intake → Dev → Data tables, select Invoice, and use View data type to inspect fields. Record the row count.
With an assistant: list workflows to find the workflow ID.
cai workflow list --limit 100 --jsonNote the matching data.items[].id as <workflowId>. If it is absent and data.hasMore is true, get the ID from the app or owner. After pinning the workflow once, subsequent CLI commands omit --workflow.
MCP uses workflow_list with limit: 100.
Pin the workflow and inspect its fields, collections, and existing records.
cai use <workflowId> --jsoncai data fields --type custom.invoice --jsoncai data collections --env dev --jsoncai data query --type custom.invoice --env dev --limit 100 --offset 0 --jsonNote data.totalCount. Increase offset by 100 until you have inspected every row. Choose unused invoice IDs.
MCP has no workflow pin. Use data_field_list, data_collection_list, and data_record_query with workflowId on each call.
Use field display names for CSV headers and field IDs for direct writes. Omit reserved headers id, created time, and updated time. Reserved or misspelled headers reject the file with Unknown CSV headers: …. Duplicate headers also reject it before row validation.
Save this CSV as invoices.csv to match the inspected labels and unused IDs.
Invoice ID,Amount,Status,Review needed,Submitted at,Source event IDINV-105,120,ready,false,2026-09-07T14:00:00Z,docs-105INV-106,1500,review,true,2026-09-07T14:00:00Z,docs-106Numbers must be finite. Booleans use true or false. Dates use ISO-8601 text. Omitted columns and empty cells become null. Whitespace-only non-text cells also become null. Text preserves whitespace.
Text, number, and boolean lists use JSON arrays. References use existing record IDs from the destination store. Reference lists use JSON arrays of IDs. Nonblank values of unsupported types, including list.date, produce CSV import does not support field type "…".
You can upload up to 10 MB and 10,000 parsed rows after the header. Blank lines count toward that limit but are excluded from totalRows and import. If a row has the wrong column count, the whole row is invalid. MCP inline CSV is limited to 2 MiB of UTF-8 text.
Which rows will be imported?
Section titled “Which rows will be imported?”In the app: choose Upload records manually → Choose CSV file to validate without writing. Before choosing Import 2 records, inspect the counts and issues. When at least one row is valid, the button permits partial imports.
With an assistant: validate the CSV to get a report of counts and issues.
cai data import --type custom.invoice --file invoices.csv --mode dryRun --env dev --jsonInspect totalRows, validCount, errorCount, warningCount, errors, and warnings. CLI JSON and MCP structured content put the report at data.result. MCP’s text block uses result.
MCP uses data_record_import_validate with workflowId, type, explicit env: "dev", and the CSV text as content instead of a local path.
One row can have multiple errors. CLI/MCP return at most 200 errors and 200 warnings. The app shows 50 combined issues. Counts remain complete, so fix listed problems and validate again.
Missing references produce warnings. Missing single references become null. Missing list items are dropped.
To check errors, change the second amount to not-a-number and validate. Expect two rows, one valid row, and an amount error. Restore 1500 and validate again before committing.
The hosted Build for me assistant can only validate. Its owner commits or copies in the app.
Commit skips invalid rows, then writes all valid rows in one transaction. With zero valid rows, the commit succeeds with importedCount: 0. If the database fails, none of the valid batch is committed. Even with identical invoice IDs, repeating a commit appends the records again.
Commit once and query the destination to inspect the imported records.
cai data import --type custom.invoice --file invoices.csv --mode commit --env dev --jsoncai data query --type custom.invoice --env dev --limit 100 --offset 0 --jsonBefore retrying an uncertain result, check data.result.importedCount and destination values. Without other writers, expect two additional records. Verify amounts and review flags. Import validates types, not the example rule Amount > 1000.
MCP uses data_record_import_commit with the same workflowId, type, explicit env, and content.
What will copying to live change?
Section titled “What will copying to live change?”Publish the matching schema first. Publication activates the workflow and lets enabled live triggers run. It never copies development rows.
If the live collection is missing, the CLI returns NO_LIVE_COLLECTION. Even when only a newly added development schema needs publication, the backend says This workflow has not been published yet. A changed schema produces The live schema for this data type is out of date — publish the workflow first.
Copying includes every undeleted development record of this type. It preserves live-only rows, overwrites matching id keys, and revives deleted matches using development values. Records are not matched by Invoice ID. Workflow restore cannot recover overwritten or deleted records.
Immediately before copying, query both stores to inspect every page.
cai data query --type custom.invoice --env dev --limit 100 --offset 0 --jsoncai data query --type custom.invoice --env live --limit 100 --offset 0 --jsonCheck both data.totalCount values.
In the app: go to Dev → Data tables → Invoice, open the heading menu, choose Copy to live, and confirm.
With an assistant: copy the records to live and query the live store to inspect the result.
cai data copy-to-live --type custom.invoice --jsoncai data query --type custom.invoice --env live --limit 100 --offset 0 --jsonCheck data.result.createdCount, data.result.updatedCount, data.result.totalRecords, and live values. In the app, switch to Live → Data tables. Repeating copy overwrites subsequent live edits on matching records.
MCP’s data_copy_to_live requires workflowId, type, and env: "live". CLI has no environment flag for this command.
To import directly into live, first publish a live version containing the type. Select Live before uploading, or use --env live for validation and commit (MCP: env: "live"). Validate against that destination’s schema and references. Committed rows reach live runs immediately without another publish.
What can I recover afterward?
Section titled “What can I recover afterward?”Workflow restore recovers definitions, not overwritten or deleted records.
Deleting a type deactivates its collection and removes other types’ fields that reference it. Recreating the same key reactivates retained rows but does not recreate those reference fields.
Removing fields hides their stored values. Changing a field’s type does not convert its stored values. Incompatible values read as null. Restore the same field IDs and compatible types to expose retained values. Inspect schema mistakes before importing replacement rows.