Side by side
POST /v1/imports/* | POST /v1/<entity>/bulk | |
|---|---|---|
| Transport | Multipart CSV | JSON |
| Mode | Async - returns a job_id | Sync - returns results in the response |
| Typical size | Hundreds of thousands to millions of rows | Hundreds to a few thousand rows |
| Per-row error reporting | After the job completes | Immediately, in BulkResponse.results |
| Retry semantics | Retry the upload; fix CSV and re-submit if the job fails | Idempotent per item |
| Rate limit footprint | One request per file | One request per batch |
Use imports/* when…
- You are doing a full-catalog refresh from your ERP or PIM.
- The data already lives in a CSV (or your pipeline can produce one cheaply).
- Wall-clock latency does not matter - you can poll status.
- You want minimal request overhead per row.
POST /v1/imports/productsPOST /v1/imports/transactionsPOST /v1/imports/competitor_pricesPOST /v1/imports/product_store
Use /bulk when…
- You are syncing deltas from your source system on an event-driven schedule.
- You want a single round trip and an immediate per-row outcome.
- You can shape the payload as JSON (the records do not naturally come from a file).
- Batch size is in the hundreds to low thousands.
POST /v1/products/bulkPOST /v1/product_store/bulkPOST /v1/transactions/bulkPOST /v1/competitor_prices/bulk
Use single-record POST /v1/<entity>/{entity_id} when…
- You are reacting to a single change in your source system (one product updated, one transaction posted).
- You want strong per-call status semantics (
201vs422directly). - You need the full response body for the row you just wrote.
A pragmatic pattern
Most production integrations end up using two of the three:- Daily full-catalog
imports/productsto absorb all upstream changes. - Event-driven
products/bulkorPOST /v1/products/{entity_id}for low-latency updates between full syncs.
