Bulk upsert
POST/v1/products/batch
scope products.write
Up to 1000 products, worked through on a queue. Returns immediately with a batch id — NOTHING is written yet. Poll the batch for per-item results. Each product takes every field of POST /v1/products, images included, so a whole catalogue — pictures and all — is a handful of requests.
Request body#
| Field | Type | Required | Description |
|---|---|---|---|
products | array | required | Up to 1000 products per batch. An empty or missing array is rejected with field_required (400); more than 1000 with batch_too_large (400), which tells you how many you sent. The call returns a batch_id immediately and the work runs behind it — poll GET /v1/products/batch/{batchId} for per-item results. |
products[]. | string | required | As on POST /v1/products: the upsert key, and required for the same reason. It matters most here — a retried batch without it would duplicate every product in it. |
products[]. | string | required | Required for an item that creates a new product. |
products[]. | string | required | Required for an item that creates a new product. |
products[]. | integer | required | Required for an item that creates a new product. |
products[]. | object | required | Required for an item that creates a new product. |
products[]. | integer | required | Minor units. |
products[]. | integer | required | Units available. Required for an item that creates a new product; 0 is accepted. |
products[]. | array | optional | Category attributes, exactly as on POST /v1/products. Items are validated one at a time: a failure marks that item and the rest of the batch still runs, so one bad category attribute does not lose the other 999. |
products[]. | integer | required | The attribute id. |
products[]. | integer | optional | The chosen option, where the attribute has a list. |
Example
{
"products": [
{
"external_id": "ERP-1001",
"title": "Bicicleta MTB Hardtail 29 inch",
"description": "A hardtail mountain bike in very good condition.",
"category_id": 4291,
"price": {
"amount": 249900
},
"stock": 4,
"attributes": [
{
"field_id": 32,
"option_id": 226
},
{
"field_id": 47,
"option_id": 422
}
]
}
]
}Response#
| Field | Type | Description |
|---|---|---|
batch_id | string | The batch handle. Poll GET /v1/products/batch/{batchId} with it. |
status | string | queued — accepted, and nothing written yet. The call returns immediately; the work happens behind it. |
total | integer | How many products were accepted into the batch. |
message | string | A reminder that nothing is written yet, and where the per-item results appear. |
Example
{
"batch_id": "batch_v4lfngtgb6sxqkzwagrqv8c2",
"status": "queued",
"total": 1,
"message": "Accepted. Nothing is written yet — poll GET /v1/products/batch/{id} for per-item results."
}