Four endpoint families related by a common thread: they all operate on many products at once and can all end in partial success. This covers the recording and rollback of bulk operations, the visual rules editor (Flow Editor), AI-assisted transformations, and product categorization for a marketplace.
207 Multi-Status appears across several of these endpoints
POST /products/marketplace-categories, the synchronous branch of CSV import, POST /products/bulk/flow/execute, and POST /products/bulk/ai/transform can respond with 207 Multi-Status when some elements of the operation succeeded and others failed. If your client only distinguishes "2xx = all good," you will treat a partially-failed result as total success — always check the per-element detail of the response.
Every bulk operation that modifies products (CSV, Flow Editor, AI) gets recorded as a "bulk operation" — that's what builds the history and enables rollback.
Lists the tenant's bulk operations history.
pagenumber
Page number.
limitnumber
Items per page.
typestring
Filters by operation type (csv-import, flow, ai-transform, etc.).
This endpoint requires two permissions at once, not just one
Unlike most read endpoints in this API, GET /products/bulk/operations and GET /products/bulk/operations/{id} require bothproducts:readandproducts:update simultaneously — a read-only API key cannot list the bulk operations history. This is a confirmed RBAC inconsistency in the code, not necessarily the intentional design; we document the actual behavior. The rollback endpoint (below), by contrast, requires only products:update.
It was confirmed that the response carries the full operation plus the canRollback field. The rest of the fields in the example (id, type, status) are indicative based on the rest of the bulk operations family — confirm them against your own response.
{ "code": "rollback-failed", "message": "This operation can no longer be rolled back" }
Required permission:products:update
Tip
Check canRollback on GET /products/bulk/operations/{id} before attempting the rollback — an operation may stop being reversible (for example, if a later operation already modified the same SKUs).
The Flow Editor lets you define bulk edit rules without writing code (a structured FlowDefinition). The three endpoints follow the validate → preview (dry-run) → execute pattern.
It was confirmed that this endpoint can respond 200 (total success) or 207 (partial). The exact names of the body fields (totalProcessed, succeeded, failed, errors) were not verified line by line — use them as a guide and confirm them against your own execution. The operation gets recorded and is queryable/reversible via the bulk operations log described above.
Applies a natural language prompt over a set of products to transform specific fields (for example, rewriting descriptions or generating marketplace bullet points).
{ "code": "budget-exceeded", "message": "Daily AI token budget exceeded for this tenant" }
Required permission:products:update
Result shape indicative
The top-level wrapper (200/207 depending on partial success) is confirmed; the exact names of fields like results[], changedFields were not verified line by line — treat them as indicative.
The AI budget is daily and per tenant
Before your prompt gets processed, the server validates against a daily tenant token budget. If you've already exhausted it, the request fails with 429 budget-exceeded without even attempting the transformation — check GET /products/bulk/ai/budget before launching a large batch.
The { history: TokenUsage[] } wrapper was confirmed; the exact fields of each TokenUsage (here date, tokensUsed, requestCount) were not verified line by line.
Assigns the category of a specific marketplace (MercadoLibre, T1/Sears/Sanborns, Amazon, Walmart, etc.) to a batch of SKUs. The result is saved as a product metafield — it doesn't create a new field in the data model.
Assigns a marketplace category to a batch of SKUs for a specific channel.
skusstring[]required
SKUs to categorize. Maximum 100 per request.
channelIdstringrequired
ID of the target channel/marketplace.
category.idstringrequired
Category ID in the marketplace. Maximum 100 characters.
{ "code": "too-many-skus", "message": "skus exceeds the maximum of 100" }
Required permission:products:update
Where the result is stored
The assigned category is persisted in product.metafields[], under namespace: 'mkt_category' and key: '{channelType}:{siteId}' — it isn't a top-level product field. The siteId depends on the channel type: MercadoLibre uses site_id (default MLM), T1/Sears/Sanborns use salesChannel/marketplace (default SR), Amazon uses marketplace_id (default MX), and Walmart uses country (default MX).