Ingest
Registers an uploaded file for asynchronous ingest and returns accepted file_path.
Request parameters:
- file_path: required storage path to uploaded file; must include a valid UTF-8 file name.
- prev_file_path: optional explicit previous file path from the same store for differential ingest.
- data_origin: optional label for the complete feed schema of one logical source.
- data_stream: optional subset inside data_origin scope (for example prices, stock, fitment).
- row_reconcile_policy: policy controlling how rows missing from current file are reconciled against previous file.
- ignore_data_columns_header_diff: optional boolean that keeps differential ingest active when only data-column headers changed.
- missing_row_defaults: optional flat object of file field names to scalar default values used only with reset_missing_row_defaults.
CSV sellable columns:
- AssembledInto: optional parent sellable reference for assembly hierarchy.
- Non-empty value is treated as a parent sellable identity and may be either a SKU or UUID.
- file-ingestor translates it into the existing assembly grouping ingest request used by data-ingestor.
- The parent sellable must already exist or be defined earlier in the same file.
- Explicit null clears the current assembly link for that sellable.
- Clearing a middle node also clears assembly links for descendants in the detached sub-assembly chain.
- Empty or omitted value leaves the current assembly link unchanged.
Differential ingest:
- If prev_file_path is provided, data-ingestor resolves that file at insert time and persists the exact previous file id used later by file-ingestor.
- If data_origin is provided, data-ingestor resolves the previous file at insert time and persists the exact previous file id used later by file-ingestor.
- If data_origin is omitted and prev_file_path is not provided request runs as ordinary ingest.
- Differential key requirements for CSV. The header should contain either:
- Sku column, or
- full composite key columns: Brand, PartNumber, CrossReferenceBrand, CrossReferencePartNumbers.
- If a differential ingest is attempted and current CSV header contains both key strategies, file-ingestor records a header issue and marks file processing with an error.
- If a differential ingest is attempted and current CSV header contains neither key strategy, file-ingestor records a header issue and marks file processing with an error.
- Each row in file should have a unique not empty value in the key column.
- Differential ingest processes new/changed rows and reconciles missing previous rows by policy:
- delete_prev_except_current (default): remove missing rows.
- delete_origin_except_source: valid only for origin-only ingests. Request must provide data_origin and must not provide data_stream. Cannot be combined with ignore_data_columns_header_diff. file-ingestor disables row diffing for the current file, ingests current rows as ordinary ingest, then data-ingestor deletes rows in the same (store_id, data_origin) not written by current source feed.
- keep_all: keep missing rows unchanged. Cannot be combined with ignore_data_columns_header_diff because skipping row comparison would otherwise degrade to ordinary ingest and defeat the purpose of differential reconciliation.
- reset_missing_row_defaults: update missing SKU rows with the field values provided in missing_row_defaults instead of deleting them. Requires missing_row_defaults and currently supports only Sku-based differential ingest. If differential ingest resolves to composite-key mode, file processing fails instead of partially reconciling rows. missing_row_defaults must be a flat object whose values are string, number, boolean, or null. Example: current file columns: Sku, PartNumber, Brand, RetailPrice, Stock:<store_address_uuid>, Backorderable:<store_address_uuid> missing_row_defaults: {"RetailPrice": null, "Stock:<store_address_uuid>": 0, "Backorderable:<store_address_uuid>": false} Result for a missing row from the previous file: Sku, PartNumber, and Brand remain unchanged because they are not included in missing_row_defaults. RetailPrice is reset to null, Stock:<store_address_uuid> is reset to 0, and Backorderable:<store_address_uuid> is reset to false.
- When ignore_data_columns_header_diff=true:
- request must provide either prev_file_path or data_origin,
- current and previous file headers must still contain exactly one identity strategy: Sku or the full composite key,
- current and previous headers must use the same identity strategy,
- header differences outside identity columns do not disable differential ingest,
- row byte comparison is skipped when headers differ, so matching keys are treated as changed rows,
- file-ingestor still removes matching keys from the previous-file index and applies reconcile policy to the remaining missing rows,
- if the previous header cannot be read, processing fails instead of falling back to ordinary ingest.
- Whenever file-import reconciliation deletes a parent sellable in data-ingestor, sub-assemblies linked through assembly groupings are deleted recursively as part of the same removal flow.
- count_items_deleted counts only sellable rows deleted by reconciliation policies. Ordinary ingest remove rows in the file do not change the counter. Cascaded sub-assembly deletions performed by data-ingestor do not change the counter. Cleanup of related uploads, tags, inventories, and groupings does not increase count_items_deleted.
Origin and stream model:
- Each origin is a complete feed schema: Origin = IdentityColumns ∪ DataColumns.
- A stream is a subset of that origin schema.
- Every stream must contain all identity columns.
- Every stream must contain a subset of data columns.
- For streams of the same origin:
- identity columns may overlap,
- data columns must be pairwise disjoint,
- each data column belongs to exactly one stream.
- Identity columns can overlap because every stream needs the same keys to identify and match rows.
- Data columns must be disjoint because a stream is the unique diff history for its data columns.
- Short rule: streams share keys, but not payload.
Simple examples:
- Valid split:
- Origin = {id1, id2, data1, data2, data3, data4}
- Stream prices = {id1, id2, data1, data2}
- Stream stock = {id1, id2, data3, data4}
- Valid because the identity columns are shared and the data columns do not overlap.
- Invalid split:
- Stream prices = {id1, id2, data1, data2}
- Stream stock = {id1, id2, data2, data3}
- Invalid because data2 appears in more than one stream.
Fallback to ordinary ingest:
- If no previous file is resolved, ingest runs as ordinary ingest.
- If previous file is resolved but previous CSV header cannot be read, ingest falls back to ordinary ingest.
- If previous file is resolved but current and previous CSV headers do not match byte-for-byte, ingest falls back to ordinary ingest.
- If the latest same-origin ingest overall has the opposite scope shape (data_stream = null vs non-null relative to current), ingest falls back to ordinary ingest.
- With ignore_data_columns_header_diff=true, those ordinary-ingest fallbacks are disabled for previous-file resolution and previous-header readability. Processing fails instead.
Automatic previous-file discovery details (when prev_file_path is not provided):
- Discovery runs only within the same store_id.
- If data_origin is omitted, scope-based candidate selection is skipped.
- Candidates are scanned from newest to oldest by created_at.
- Exhausted failed candidates are skipped before any opposite-scope or same-stream decision.
- If the first non-exhausted same-origin candidate has opposite scope shape (data_stream = null vs non-null relative to current), current file runs as ordinary ingest only if that candidate has completed file_ingestor. If that newer same-origin candidate is still pending, file-imports.insert fails with 422 prev_file_ingest_not_completed instead of skipping it and searching older same-scope history.
- If current file has data_origin and no data_stream, eligible same-scope candidates are previous origin-only files with equal data_origin.
- If current file has data_origin + data_stream, eligible same-scope candidates are previous files with equal data_origin and equal data_stream. A different stream does not count as a diff baseline for the current stream.
- A discovered previous file used for differential ingest must have completed file_ingestor stage.
- If the newest non-exhausted same-origin candidate is still waiting to be processed, file-imports.insert fails with 422 prev_file_ingest_not_completed.
- If no usable candidate remains after exhausted candidates are skipped, insert persists no previous file and ingest runs as ordinary ingest.
- With ignore_data_columns_header_diff=true, if no usable candidate remains after skipping candidates with unreadable headers, insert fails with 422 ignore_data_columns_header_diff_requires_previous_file instead of falling back to ordinary ingest.
Explicit previous-file behavior:
- If prev_file_path is provided, it must resolve to a file from the same store.
- The resolved explicit file must have completed file_ingestor stage.
- If the explicit file exists but has not completed file_ingestor, file-imports.insert fails with 422 prev_file_ingest_not_completed.
Example API calls (major no-fallback cases):
- No prev file + no origin -> ordinary ingest.
- Request: POST /api/v1/file-imports.insert
- Body: {"file_path":"imports/store_<store_id>/2026_03/current.csv"}
- Previous file match: none, because both prev_file_path and data_origin are omitted.
- Explicit prev file -> differential ingest.
- Request: POST /api/v1/file-imports.insert
- Body: {"file_path":"imports/store_<store_id>/2026_03/current.csv","prev_file_path":"imports/store_<store_id>/2026_03/prev.csv"}
- Previous file match: exactly prev_file_path (same store), scope discovery is bypassed.
- data_origin + data_stream -> differential ingest.
- Request: POST /api/v1/file-imports.insert
- Body: {"file_path":"imports/store_<store_id>/2026_03/current.csv","data_origin":"supplier_a","data_stream":"prices"}
- Previous file match: newest file in same store with equal data_origin and equal data_stream (prices) that has completed file_ingestor, unless a newer completed same-origin file has opposite scope shape.
Diff vs ordinary ingest cases:
- Diff is used:
- explicit prev_file_path resolves a same-store previous file,
- current file is origin-only and the latest same-origin ingest overall is also origin-only,
- current file is origin+stream, the latest same-origin ingest overall also has stream scope, and a same-stream baseline exists.
- Ordinary ingest is used:
- no prev_file_path and no scope baseline is found,
- newest completed same-origin candidate has opposite scope shape (data_stream = null vs non-null relative to current),
- previous file exists but previous header cannot be read,
- previous file exists but headers do not match byte-for-byte,
- row_reconcile_policy=delete_origin_except_source intentionally disables row diffing for valid origin-only requests.
- Insert is rejected before processing starts when:
- explicit prev_file_path exists but has not completed file_ingestor,
- newest non-exhausted same-origin candidate is still waiting to be processed, even if it has opposite scope shape.
- Differential ingest is attempted but processing fails instead of falling back when current CSV header contains:
- both Sku and full composite key columns, or
- neither Sku nor full composite key columns.
Scope mismatch examples:
- prev has data_origin = A and data_stream = prices, current has data_origin = A and data_stream = null. Result: ordinary ingest when that latest same-origin ingest has already completed file_ingestor. Current origin-only file does not skip that newer stream ingest and search older origin-only history.
- prev has data_origin = A and data_stream = null, current has data_origin = A and data_stream = prices. Result: ordinary ingest when that latest same-origin ingest has already completed file_ingestor. The first stream file after a full-origin file has no valid stream baseline.
Reingest behavior for row data_origin:
- Reingesting the same rows without data_origin sets ingested rows data_origin to null in products data.
- Reingesting the same rows with a different data_origin overwrites products rows with the new data_origin value.
- Because previous-file lookup is scope-based, changing or omitting data_origin may stop differential linkage to files from other scopes unless prev_file_path is explicitly provided.
Validation rules:
- invalid file_path (no file name or non-UTF-8 file name) returns 422.
- data_stream without data_origin returns 422.
- data_origin with prev_file_path is mutually exclusive and returns 422.
- row_reconcile_policy=delete_origin_except_source without data_origin returns 422.
- row_reconcile_policy=delete_origin_except_source with data_stream returns 422.
- ignore_data_columns_header_diff=true without prev_file_path and without data_origin returns 422.
- ignore_data_columns_header_diff=true with row_reconcile_policy=keep_all returns 422.
- ignore_data_columns_header_diff=true with row_reconcile_policy=delete_origin_except_source returns 422.
- prev_file_path must reference an existing file from the same store if not found returns 404.
- prev_file_path that resolves to a file which has not completed file_ingestor returns 422.
- the newest non-exhausted same-origin previous file candidate that is still waiting to be processed returns 422.
- Differential CSV key validation is performed during file processing (not in this insert request): when differential ingest is attempted, current CSV header must contain exactly one strategy: Sku or full composite key (Brand, PartNumber, CrossReferenceBrand, CrossReferencePartNumbers). If both or neither are present, file-ingestor logs a header issue and marks the file with processing error stats.
Notes:
- data_origin/data_stream are caller-provided scope identifiers.
- data_source is system-derived from ingest source metadata and is not a request field.
- duplicate file_path for the same store is treated as an internal error path (current behavior).
post/api/v1/file-imports.insert
Request
- Base URL: https://api.partly.com (the document declares no server; this is the origin it was published from)
- URL: https://api.partly.com/api/v1/file-imports.insert
- Auth: none declared. Required headers: authorization
Headers
authorizationstring required
UTF-8 encoded string
Request body
Response
200 OK
Changes
No recorded changes to this operation across all 1 revision of this API.