POST /api/v1/products/bulk-import to import products into your organization. Send a products array, upload a JSON or CSV file, or reference CSV with csvText / documentId. The endpoint returns HTTP 202 and a bulk_... job ID; processing continues asynchronously. Imported drafts go through the same AI Review workflow as the app.
Each import supports at most 1,000 selected products, for both standard and enterprise lanes. This limit applies to JSON, CSV, and document-based imports. Split larger selections into separate imports.
Interactive reference: API docs
Authentication
Send an OmniCommerce API key or OAuth client token with thecatalog:write scope:
organizationId in the request body or multipart form fields.
Session-authenticated requests (browser cookie) must include organizationId in the request body or multipart form fields.
Import 200 JSON products
Send between 1 and 1,000 products per request, with a maximum JSON request size of 8 MiB. A 200-product batch is supported. Send HTTP(S) image URLs; upload image files separately instead of embedding image bytes. Save a request such as this toimport.json (extend products to include your complete batch):
fieldMapping must be omitted. sku is required; other supported fields are title, gtin, brand, description, price, currency, compareAtPrice, salePrice, costPerItem, inventory, images, category, categoryName, weight (grams), and dimensions (centimeters). currency applies to all price and cost fields on that row. It defaults to SGD for compatibility with existing CSV imports; specify it explicitly for other currencies. Target countries do not convert the supplied prices.
Each object is a flat import row. REST imports preserve rows as independent products; they do not guess variant families or pause for the app’s variant-grouping confirmation. Nested variants and unknown fields are rejected rather than silently discarded. Descriptions are limited to 10,000 characters and galleries to 30 HTTP(S) URLs per product. See the API reference for complete field limits.
For larger catalogs, split by both product count and encoded byte size. Submit a few batches concurrently, retain each returned job ID, and poll every job. A 413 response means the payload needs to be split. Do not automatically resubmit a request whose result is unknown: first check whether an import was accepted.
Upload a JSON file instead
A JSON file may contain an array of products or{ "products": [...] }. Supply workflow and target settings as multipart fields; other properties inside the file wrapper are not workflow settings.
Upload a CSV file
.csv files up to 2MB.
Send inline CSV or a stored CSV document
"organizationId": "org_1" to the JSON body or multipart form.
You can also pass documentId instead of csvText when the CSV is already stored in the organization’s document library.
Accepted response
Poll job status
data payload includes row counts (pending, enriching, applied, failed, skipped), progress fields, and the underlying import status. Once review creation finishes, it also includes:
completed means source rows have been imported into draft products. It does not mean AI proposals have been approved or marketplace listings published. Open each reviewUrls entry to review copy, images, and marketplace taxonomy. Check failed, skipped, and reviewWarnings even when the import is completed; a partial import is not success for every row.
Workflow options
Set top-leveltitle to name the Review job (up to 120 characters). The assistant’s bulk_product_import tool accepts the same title, so an AOP can supply a fixed name or bind a [[ review_name ]] input. Omit it to use the default timestamped Review name.
JSON and CSV share the app’s organization defaults. Explicit workflow values override them: enableRichDescription, sourceImagesAutomatically, autoAssignMarketplaceTaxonomy, enableBackgroundRemoval, enableMannequinRemoval, skipImageTagging, skipZeroInventoryProducts, excludedImageTags, enabledBuiltInImageTags, and customImageTags ({ "name", "description" } objects).
Annotation settings use top-level imageAnnotationTemplateId, imageAnnotationGalleryTemplateId, and imageAnnotationScope (primary or all_gallery). Templates must belong to the organization. All supported marketplace identifiers use the same import and review flow; taxonomy depends on the connected stores selected for the import.
The legacy workflow.skipBackgroundRemoval is still accepted; explicit enableBackgroundRemoval takes precedence. skipEnrichment and enrich: false remain restricted to super admins. Bulk import does not queue ACO generation. Generate a profile from the product after import. disableAcoGeneration is accepted and does not turn generation on.
Cancel an in-flight import (optional)
Multipart form fields
Job ID format
Developer bulk imports return IDs with thebulk_ prefix, for example bulk_7f4f5f0d-2f0a-4f0a-9a2f-8d2f0a7f4f5f. Use the same job polling and cancellation endpoints as single-product prod_... jobs and Look look_... jobs.
Errors
400- invalid JSON, missing product source, invalid field mapping, or product validation failure401- missing or invalid Bearer token403- token missingcatalog:writeor wrong organization413- JSON request, multipart body, or uploaded file too large
Image exclusion results
Image preparation evaluates every configuredcustomImageTags condition explicitly. Matching names are stored exactly in normalized snake case and applied before image cleanup and review selection. Reserved image classifications use a fixed vocabulary, including brand_card, size_chart, spec_sheet, store_info, and model_worn; descriptive content tags can still vary. A logo on an actual product is not a brand_card. model_worn covers real people wearing or holding an item, including lifestyle photos; use mannequin separately for body forms.
GET /api/v1/products/{productId} returns excludedImages alongside the kept images. Each exclusion includes url, sourceUrl, original zero-based position, imageTags, matchedExcludedTags, and a reason: excluded_tag, size_chart, gallery_limit, non_product_asset, or mirror_unavailable. Exclusion evidence is saved when import images are applied or an image review is approved. Older imports without a saved audit return an empty array; rerun image preparation to generate evidence. Failed classification must be retried before filtered images can be applied. Explicitly setting skipImageTagging skips both classification and tag-based exclusions.