import.completed / import.failed); you can also poll.
It’s part of the developer plan. A batch can touch several resources, so the key needs create and
update access on each one the files you declare will write — or full access.
The shape of it
1. Get the templates
Each file has an exact set of columns. Fetch the catalog so you build them correctly:header (keep the columns in order, don’t rename them) and the
type and rules for every column.
A few conventions across all files:
- IDs and references are UUIDs. Keep them consistent across files — an order item’s
ordermust match an order’sid. - Money is integer minor units:
4500means 45.00. - Dates are ISO-8601, e.g.
2024-01-15T09:00:00Z. - Booleans are lowercase
true/false. - JSON cells must be valid JSON.
2. Create the job
Tell us which files you’re sending:import_id and an upload target per file:
3. Upload each file
PUT each CSV straight to its url. This goes to storage, not through the API, so large files are
fine. Don’t add your API key to this request — the URL is already authorized.
4. Submit
202 immediately. From here, watch for the webhook.
What you get back
Check a job anytime withGET /imports/:id. The status moves through validating →
importing → completed, or stops at invalid (validation found problems) or failed.
On success, the summary has per-file counts:
invalid and nothing is written. A job that passes validation can
still finish completed with a few skipped_rows — rows the commit could not write, such as a
recipe naming a material that doesn’t exist. They come back in the same errors list, with their
row numbers. GET /imports/:id/errors returns
each problem with the file, row and column:
Good to know
- Re-running is safe. Rows are matched by the id you supply, so submitting the same data again updates rather than duplicates. That makes import a fine way to keep data in sync, not just a one-time load.
- Categories and tags are by name. For products,
categoryandtagsare plain names — we create them if they don’t exist yet. - Statuses must already exist. Fields like a product’s
statusor an order’spayment_statushave to be values your workspace already uses; we won’t invent them. - Submitting twice at once returns
409while a job is still running — wait for it to finish.

