Add images
POST/v1/products/{id}/images
scope products.write
Two ways, mixable in one call: images as URLs (referenced, nothing downloaded — the way supplier feeds work) and/or files as multipart uploads onto our storage. Position 0 is the primary image. For URLs, sending images with the product itself (POST /v1/products, PUT, or the batch) saves this request entirely — this endpoint is for uploads and for adding to what a listing has.
Request body#
| Field | Type | Required | Description |
|---|---|---|---|
images | array | required | The images to attach, in the order you send them. Each entry may be an object with a url, or the URL string on its own.Not supported An entry whose URL does not parse is SKIPPED silently — the call succeeds and returns how many were attached. Compare that count with what you sent rather than assuming. |
images[]. | string | required | An absolute URL we REFERENCE rather than download: the image is served from your host through our proxy, so it has to stay reachable for as long as the listing is live. Moving or deleting it breaks the listing. |
replace | boolean | optional | Defaults to false, which APPENDS after the images already there. Send true to drop every existing image first — that is how you re-sync a product whose photos changed, and it is not reversible. |
files | file[] | optional | Upload the images themselves instead, as multipart/form-data. replace works the same way. |
Example
{
"images": [
{
"url": "https://cdn.example.com/erp/mtb-front.jpg"
},
{
"url": "https://cdn.example.com/erp/mtb-side.jpg"
}
],
"replace": false
}Response#
| Field | Type | Description |
|---|---|---|
attached_from_urls | integer | How many were attached by link. COMPARE this with how many you sent: a URL that does not parse is skipped silently and the call still succeeds. |
uploaded | integer | How many were uploaded as files. |
images | array | The listing's images AFTER the change, already in display order — so you never need a follow-up read to see the result. |
images[]. | integer | The image id, for reordering and deletion. |
images[]. | integer | Its place, 0 being the main photo. |
images[]. | string|null | Where the file sits in our storage, when we host it. |
images[]. | string|null | The URL we serve it FROM, when you attached it by link. Exactly one of these two is set. |
Example
{
"attached_from_urls": 2,
"uploaded": 0,
"images": [
{
"id": 108876841,
"position": 0,
"path": "files/237224/mtb-front.jpg",
"source_url": null
},
{
"id": 108876840,
"position": 1,
"path": null,
"source_url": "https://cdn.example.com/erp/mtb-side.jpg"
}
]
}