Yep Platform logo
REST API · Yep Platform Technical documentation for certified integrations

Images

Lookup and management of the images attached to products — single-product lookup, cursor-paginated global inventory, gallery metadata, image roles and explicit store_id support.

REST JSON Bearer Token Read & write New in 2026

Overview

The image API lets you:

  • list every image of a specific product;
  • walk the global image inventory of the catalog;
  • tell enabled and disabled images apart;
  • identify the image, small_image and thumbnail roles;
  • work deterministically with store_id;
  • run an initial load and a full reconciliation using cursor pagination;
  • keep using the existing endpoints to create, update and delete images;
  • remove every image of a product in a single call;
  • remove specific images from several products in a single call.
The GETs are read-only: they do not change the product, the gallery, stock, indexes or the product's update timestamp.

Method map

MethodRoutePurpose
GET/api2/products/imagemLook up a product's images
GET/api2/products/imagensPaginated global inventory
POST/api2/products/imagemCreate an image
PUT/api2/products/imagemUpdate an image
DELETE/api2/products/imagemDelete one image
DELETE/api2/products/imagensDelete all or delete selectively in bulk
PATCH /api2/products/imagem responds 405. Updates use PUT.
200
Max limitPer call, via limit.
100
Default limitWhen limit is omitted.
cursor
Paginationhas_next + next_cursor. No page or offset.
0
Default storestore_id=0 is the administrative/global scope.

OAuth2 permissions

Reading and writing images use different permissions. When configuring the OAuth2 client in the admin panel, grant only what the integration needs.

OperationPermissionIn the admin panel
GET /api2/products/imagem
GET /api2/products/imagens
products/readProducts › View products
POST, PUT and DELETE /api2/products/imagem
DELETE /api2/products/imagens
products/imagesProducts › Manage product images
A client holding only products/read can query and reconcile images but receives 403 when trying to create, update or delete — bulk deletes included.

Look up a product's images New

Read-only operation: returns every image in a product's gallery, including disabled ones, with the roles and label in the context of the requested store.

GET/api2/products/imagemNew

List the images attached to a specific product.

Read-onlyNo queueNo reindexproducts/read
GET /api2/products/imagem?type=sku&product_id=27.9353&store_id=1&limit=100
Authorization: Bearer {access_token}
The example uses store_id=1 because it is a common storefront store. Each project must send the ID of its own store; store_id=0 is the administrative/global scope.

Parameters

type Required
Defines how product_id is interpreted: sku or id, following the same convention as the other image endpoints. The certified example uses sku.
product_id Required
Product identifier according to type.
store_id Optional
Store used as the context for image metadata and roles. Default 0. Sending the integration's storefront store explicitly is recommended.
limit Optional
Maximum number of images per call. Default 100; accepts 1 to 200.
cursor Optional
Continuation cursor when the same product has more images. Send exactly the next_cursor returned by the previous call.

Response example

{
  "success": true,
  "product_id": 115973,
  "sku": "27.9353",
  "store_id": 1,
  "images": [
    {
      "image_id": "690992",
      "file": "/e/s/escova-robinson-taca-soft.jpg_1.jpg",
      "label": "Imagem 1",
      "position": 1,
      "types": [
        "image",
        "small_image",
        "thumbnail"
      ],
      "disabled": false,
      "url": "https://www.exemplo.com.br/media/catalog/product/e/s/escova-robinson-taca-soft.jpg_1.jpg"
    }
  ],
  "has_next": false,
  "next_cursor": null
}

Image fields

FieldTypeDescription
image_idstringStable identifier of the image record in the catalog. Same value used by PUT and DELETE.
filestringRelative path of the file inside the catalog media folder.
labelstring / nullImage label in the context of the requested store.
positionint / nullPosition of the image in the gallery.
typesarrayRoles assigned to the image in the requested context.
disabledbooleanWhether the image is disabled for the gallery in that context.
urlstringPublic URL built for the image file.
In the global inventory each record also includes product_id and sku.

Image roles (types)

types lists the roles the image plays on the product. Possible values are image (base image), small_image and thumbnail.

"types": [
  "image",
  "small_image",
  "thumbnail"
]

An image can belong to the gallery without playing any of these roles:

"types": []

types=[] is valid

An empty array only means the image is in the gallery with no role assigned in that context. It does not mean the image is missing and must not be treated as an error by the integration.

Disabled images

Read operations include disabled images. This is intentional: the integration can use disabled to correctly reconcile existing images that must not be shown as active.

{
  "image_id": "653867",
  "file": "/p/o/ponta-diamantada_58.jpg",
  "label": "Imagem 1",
  "position": 1,
  "types": [],
  "disabled": true,
  "url": "https://www.exemplo.com.br/media/catalog/product/p/o/ponta-diamantada_58.jpg"
}
Do not assume only active images are returned. If the integration displays active images only, filter by disabled=false on the consumer side.

Store and fallback

store_id=0 is the administrative/global scope. For storefront integrations, send the ID of the store used by the project explicitly — for example store_id=1. Multi-store environments may have store_id=1, store_id=2, store_id=3 and so on.

  • Gallery fields (label, position, disabled) use the requested store context and may inherit values from the global scope when there is no store-specific override.
  • The roles in types also follow the configuration of the requested context.
  • store_id=1 is only a common example — it is not a universal value on the Yep Platform.

Existing product with no images

An existing product with no images returns HTTP 200 with an empty list:

{
  "success": true,
  "product_id": 116022,
  "sku": "25.5979",
  "store_id": 0,
  "images": [],
  "has_next": false,
  "next_cursor": null
}
SituationResponse
Existing product with no images200 + images: []
Product not found404

Global image inventory New

Returns the catalog's image inventory, paginated by cursor. Intended for initial load and full reconciliation.

GET/api2/products/imagensNew

Walk every image in the catalog, one page per call.

Read-onlyCursorproducts/read
GET /api2/products/imagens?store_id=1&limit=100
Authorization: Bearer {access_token}

Parameters

store_id Optional
Context store. Default 0. Sending it explicitly is recommended.
limit Optional
Integer between 1 and 200. Default 100.
cursor Optional
Cursor returned by the previous page in next_cursor. Omit on the first call.

There is no page or offset

This endpoint paginates by cursor only. Requests containing page or offset are treated as invalid and return 400.

Response example

{
  "success": true,
  "store_id": 1,
  "images": [
    {
      "image_id": "160031",
      "product_id": 98622,
      "sku": "25.0886",
      "file": "/b/r/broca-carbide-fg-36.jpg_10.jpg",
      "label": "Imagem 1",
      "position": 1,
      "types": [],
      "disabled": false,
      "url": "https://www.exemplo.com.br/media/catalog/product/b/r/broca-carbide-fg-36.jpg_10.jpg"
    }
  ],
  "has_next": true,
  "next_cursor": "160115"
}

Inventory semantics

The plural endpoint is an inventory of images, not of products. Therefore:

  • a product with several images appears several times — each record is one image;
  • products with no images do not appear in the inventory;
  • disabled images appear with disabled=true;
  • product status and visibility are not used as gallery filters.
To find products without images, cross the inventory with the GET /api2/products listing. The inventory alone does not contain every product.

Cursor pagination

Every listing that can exceed one page returns has_next and next_cursor. The integration advances by passing the received cursor back, without computing anything.

First call GET /api2/products/imagens?store_id=1&limit=100
Response { "has_next": true, "next_cursor": "163608" }
Next call GET /api2/products/imagens?store_id=1&limit=100&cursor=163608

Recommended flow

  1. start without cursor;
  2. process images;
  3. if has_next=true, call again with cursor equal to next_cursor;
  4. repeat;
  5. stop when has_next=false and next_cursor=null.

Avoid

  • Incrementing the cursor manually.
  • Reusing an arbitrary cursor as if it were a page number.
  • Sending page or offset.

The cursor is not a permanent change marker

The cursor exists only to continue the current sweep. It does not represent an update date, a product version, an immutable snapshot or an incremental change feed. Do not store the last cursor indefinitely hoping to discover images changed days later: an old image whose metadata changed does not get a new image_id.

For a new full reconciliation: start again without cursor → walk every page again → stop when has_next=false.

Integration recommendations

Initial loadGET /api2/products/imagens?store_id={STORE_ID}&limit=100 and follow every next_cursor to the end.
Periodic reconciliationStart again without cursor and repeat the full inventory sweep.
Single lookupGET /api2/products/imagem?type=sku&product_id={SKU}&store_id={STORE_ID}&limit=100 for a known SKU.

Summary

Initial load / reconciliation: GET /api2/products/imagens with next_cursor pagination.
Single product lookup: GET /api2/products/imagem.

HTTP responses of the lookups

SituationStatus
Successful lookup200
Existing product with no images200
Invalid parameter400
Missing authentication or invalid token401
No permission403
Product not found (single endpoint)404
Internal failure500

Inputs that return 400

  • limit=0, limit=201 or limit=abc
  • page=2 or offset=10
  • invalid cursor
  • invalid store_id

Read-only, no side effects

GET /api2/products/imagem and GET /api2/products/imagens do not update the product, do not change updated_at, do not change the gallery, do not enqueue work, do not reindex and do not change stock or price.

The returned url is built from the media record. The lookup does not verify that the remote file physically exists.

Write operations

Creating, updating and deleting a single image remain available on the singular route, distinguished by HTTP method. They require the products/images permission. The GETs do not replace these operations. To remove several images at once, see full deletion and selective bulk deletion.

POST/api2/products/imagem

Upload a base64-encoded image.

JSONproducts/images
{
  "type": "sku",
  "product_id": "novo_produto",
  "position": 1,
  "label": "Image",
  "file_name": "my_image.png",
  "file_mime_type": "image/png",
  "file_content": "iVBORw0KGgoAAAANS...",
  "types": ["image"]
}
Required: product_id, file_content, file_mime_type, label and position. type accepts sku or id (default id). file_name is optional — when omitted a unique name is generated. Success responds 201 with the created image_id.
PUT/api2/products/imagem

Update image metadata.

JSONproducts/images
{
  "type": "sku",
  "product_id": "produtoteste",
  "image_id": "70449",
  "position": 999,
  "label": "Updated image",
  "types": ["image"]
}
Required: product_id and image_id. Optional: label, position, types and exclude (1 disables the image in the gallery; default 0). Success responds 200.
DELETE/api2/products/imagem

Delete a product image.

JSONproducts/images
{
  "type": "sku",
  "product_id": "produtoteste",
  "image_id": "70449"
}
Required: product_id and image_id. Success responds 200. Still the recommended way to remove one image per call.

Updates use PUT, not PATCH

Unlike /api2/products, the image route accepts PUT for updates. A PATCH /api2/products/imagem request responds 405 (method not allowed). Earlier versions of this documentation showed PATCH by mistake.

The image_id used by PUT and DELETE is the same one returned by the lookups on this page and by the upload POST.

Delete every image of a product New

Removes the entire global gallery of a single product in one request.

DELETE/api2/products/imagensNew

Clear a product's whole gallery (delete_all mode).

JSONGlobalproducts/images
DELETE /api2/products/imagens
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "type": "sku",
  "product_id": "PRODUTO-001",
  "delete_all": true
}

Identification by ID is also accepted:

{
  "type": "id",
  "product_id": 12345,
  "delete_all": true
}

Parameters

type Required
Defines how product_id is interpreted: sku or id.
product_id Required
Product identifier according to type.
delete_all Required
Must be the JSON boolean true, strictly. The values "true", 1, false, null or a missing field are rejected.
  • store_id is not accepted: the cleanup is global for the product's gallery.
  • delete_all and items are mutually exclusive modes in the same request.

Response example

{
  "success": true,
  "product_id": 12345,
  "sku": "PRODUTO-001",
  "deleted_count": 3
}

A product that already has no images responds 200 with deleted_count: 0:

{
  "success": true,
  "product_id": 12345,
  "sku": "PRODUTO-001",
  "deleted_count": 0
}
SituationResponse
Gallery removed200 + deleted_count with the number removed
Existing product with no images200 + deleted_count: 0
Product not found404
The operation removes the product's gallery associations. It must not be understood as a physical cleanup of the /media directory.

No blind retry after a new upload

Each delete_all=true call expresses the intent to clear the current gallery. If the integration has already started uploading new images, do not resend an old delete_all call: it would also remove the images just uploaded.

Delete specific images in bulk New

Removes specific images from one or several products in a single call. SKU and ID identification can be mixed in the same batch.

DELETE/api2/products/imagensNew

Delete a list of image_ids per product (items mode).

JSONBatchGlobalproducts/images
{
  "items": [
    {
      "type": "sku",
      "product_id": "PRODUTO-001",
      "image_ids": ["10001", "10002"]
    },
    {
      "type": "id",
      "product_id": 12346,
      "image_ids": ["10003"]
    }
  ]
}
50
Products per requestMaximum entries in items.
500
image_ids per requestMaximum unique IDs across all items.

Payload rules

  • items must be a non-empty array.
  • Each item requires type, product_id and image_ids.
  • type accepts only sku or id.
  • image_ids must be a non-empty array.
  • Each existing image_id must belong to the product given in the same item.
  • The same product cannot appear twice, even if one entry uses SKU and the other uses ID.
  • The same image_id cannot be repeated in the batch.
  • store_id is not accepted: the deletion is global.
  • items and delete_all cannot be sent together.

Response example

{
  "success": true,
  "products_processed": 2,
  "requested_count": 3,
  "deleted_count": 2,
  "already_absent_count": 1,
  "results": [
    {
      "product_id": 12345,
      "sku": "PRODUTO-001",
      "requested_count": 2,
      "deleted_count": 2,
      "already_absent_count": 0
    },
    {
      "product_id": 12346,
      "sku": "PRODUTO-002",
      "requested_count": 1,
      "deleted_count": 0,
      "already_absent_count": 1
    }
  ]
}

Response fields

FieldDescription
products_processedNumber of products in the batch.
requested_countNumber of image_ids requested, in total and per product.
deleted_countNumber of images actually removed by this call.
already_absent_countNumber of image_ids that no longer existed. Not an error.
resultsPer-product breakdown, with resolved product_id and sku.

Idempotent for already removed IDs

Resending the same batch does not fail: IDs already removed are counted in already_absent_count and deleted_count stays at 0. When the API returns success, every requested image_id is absent from its product at the end of the operation.

Bulk delete guarantees

Validation before deleting

The batch is validated before any deletion is applied. Missing products, wrong ownership, duplicates or an invalid payload never cause a partial deletion of the other items: the whole request is rejected and no image is removed.

Batch errorStatusEffect
image_id belongs to another product400Nothing deleted
Repeated product or image_id400Nothing deleted
Invalid payload400Nothing deleted
Any product not found404Nothing deleted

Duplicate images and roles

Two gallery associations can point to the same file. If only one image_id is removed and another association of the same product still uses the same file, the image, small_image and thumbnail roles remain valid.

Roles are cleared only when the last association of that file no longer exists on the product.

Operational recommendations

For gallery reconciliation:

  1. query the images or the inventory;
  2. group the deletions by product;
  3. build batches of up to 50 products and 500 image_ids;
  4. send one batch;
  5. wait for the response;
  6. only then send the next one.
Avoid running several heavy batches in parallel without need.

Reads per store, deletes global

Lookups keep using the integration's store_id, for example store_id=1. Bulk DELETEs are global and do not take store_id.

HTTP responses of write operations

SituationStatus
Deletion completed200
Product already without images (delete_all)200
IDs already absent in the batch200
Invalid payload400
Wrong ownership400
Repeated product or image_id400
Missing authentication or invalid token401
Missing the products/images permission403
Product not found404
Incompatible method, such as PATCH /api2/products/imagem405
Internal failure500