Saltar al contenido
Catálogo

Productos

Crea, busca, edita, publica y elimina productos con Admin API, uno a uno o en lote.

Crea el «Polo de algodón» de tu tienda en Lima a S/ 59.90 y adminístralo desde Admin API.

Requisitos

  • Un token de Admin en ECOMIQ_TOKEN. Ver Inicio rápido.
  • Los permisos catalog:create, catalog:read, catalog:update y catalog:delete, según lo que hagas.
  • El permiso operation:read, para seguir lotes con filtros y exportaciones.

Crea un producto

Envía el nombre y el precio. Lo demás es opcional.

curl -X POST https://api.ecomiq.pe/api/v1/catalog/products \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Polo de algodón", "sku": "POL-001", "price": 59.90 }'

La API responde 201 con el producto completo. Guarda su id:

Respuesta
{
  "id": "7204558912004325302",
  "name": "Polo de algodón",
  "slug": "polo-de-algodon",
  "status": "draft",
  "price": 59.9,
  "variants": [
    { "id": "7204558912004325377", "sku": "POL-001", "trackInventory": true }
  ]
}
  • Sin status, el producto nace en draft: no se ve en la tienda.
  • Sin variants, se crea una variante con el SKU y el precio del producto.
  • Sin sku, se genera uno. Sin slug, se arma con el nombre.
  • Para mostrar un precio tachado, envía compareAtPrice, mayor que price.
  • Para tallas o colores, sigue Variantes y precios.

Busca productos

Lista tus productos con filtros. Este ejemplo busca polos en borrador:

curl "https://api.ecomiq.pe/api/v1/catalog/products?search=polo&status=draft&sortBy=name" \
  -H "Authorization: Bearer $ECOMIQ_TOKEN"
Respuesta
{
  "data": [{ "id": "7204558912004325302", "name": "Polo de algodón" }],
  "hasNextPage": false,
  "nextCursor": null,
  "totalCount": null
}

search busca en el nombre, la descripción, los SKU y los códigos de barras. No distingue mayúsculas. Para varios valores, repite el parámetro: status=draft&status=active.

ParámetroQué filtra
status, excludeStatusEstados. Sin ellos, los archivados no salen.
includeArchived=trueSuma los archivados.
categoryIds, brandIdsCategoría o marca del producto. No incluye subcategorías.
tagsEtiquetas que contienen ese texto, sin distinguir mayúsculas.
skusSKU exacto de una variante.
minPrice, maxPricePrecio del producto: el menor de sus variantes activas.
minAvailableUnidades disponibles, sumando sus variantes activas.
  • Ordena con sortBy: createdOn (por defecto), updatedOn, name, price, available, onHand o salesCount. sortDirection es desc por defecto.
  • limit va de 1 a 200. Por defecto, 20.
  • Si hasNextPage es true, repite la llamada con cursor igual a nextCursor. Mantén los mismos filtros y el mismo orden.
  • totalCount llega solo en la primera página y con includeTotalCount=true.
  • Con includeVariants=true, cada producto trae sus variantes.

Para saber cuántos hay sin traerlos, usa /count con los mismos filtros:

curl "https://api.ecomiq.pe/api/v1/catalog/products/count?status=draft" \
  -H "Authorization: Bearer $ECOMIQ_TOKEN"

La respuesta trae total y precision. Cuenta hasta 10 000 productos: si hay más, precision es atLeast y total es un mínimo. Envía exact=true para el número exacto.

Lee el detalle

Pide el producto por su id:

curl https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN"

Así se ve el polo cuando ya tiene tallas, categoría, marca, foto y stock:

Respuesta
{
  "id": "7204558912004325302",
  "name": "Polo de algodón",
  "status": "active",
  "price": 59.9,
  "available": 24,
  "category": { "id": "7204558912004325502", "name": "Polos" },
  "brand": { "id": "7204558912004325510", "name": "Andes" },
  "images": [{ "url": "https://cdn.mitienda.pe/polo.webp", "isPrimary": true }],
  "variants": [
    {
      "id": "7204558912004325377",
      "sku": "POL-001-S",
      "price": 59.9,
      "available": 10,
      "options": [{ "name": "Talla", "key": "talla", "value": "S" }]
    }
  ]
}
  • price es el menor precio entre las variantes activas. available suma sus unidades disponibles.
  • Cada variante trae su precio, su stock y sus options, como la talla. Las eliminadas no aparecen.
  • category y brand llegan en null si el producto no tiene.

Edita un producto

Envía solo los campos que cambias:

curl -X PATCH https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "description": "Algodón pima peruano.", "tags": ["polos", "verano"] }'

La API responde 200 con el producto completo, como en el detalle.

  • Lo que no envías, o envías en null, no cambia.
  • Para vaciar un texto, como description, envía "". Un name vacío se ignora.
  • tags, images y specifications reemplazan la lista actual. Con [], la vacías.
  • Cambiar name no cambia el slug. Si quieres otro, envía slug.
  • Para quitar la marca o la categoría, envía clearBrand o clearCategory en true. Ver Categorías y colecciones.
  • price y compareAtPrice del producto solo cuentan en combos (bundle). Para los demás, cambia el precio de cada variante.

Variantes

En variants, envía solo las variantes que cambias:

  • Con variantId, actualizas esa variante. Lo que omites conserva su valor.
  • Sin variantId, creas una nueva.
  • Con variantId y deleted: true, la eliminas.
  • Las variantes que no envías no cambian. Con [], no cambia nada.
  • Para quitar el precio de comparación o el costo, envía clearCompareAtPrice: true o clearCostPrice: true. Aquí null no borra nada, y el indicador junto con un precio se rechaza.
  • Para detectar cambios concurrentes, envía expectedVersion en el producto y en cada variante.
  • Un combo solo admite actualizar su variante existente. Sus componentes se cambian en items.

Cambia el estado

Publica el polo con status:

curl -X PATCH https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "status": "active" }'

El polo controla stock y aún no tiene unidades. Por eso la respuesta trae "status": "outOfStock". Cuando cargas stock en Inventario, pasa solo a active.

statusEn la tienda
draftNo se ve. Es el estado al crear.
activeSe ve y se vende.
outOfStockSe ve, pero no se puede comprar. Se asigna solo.
inactiveNo se ve.
archivedNo se ve. Tampoco sale en la lista sin includeArchived=true.
  • Si envías outOfStock, se ignora. discontinued no se puede fijar por la API.
  • Al archivar, sus variantes pasan a inactive. Si lo reactivas, actívalas con PATCH /v1/catalog/variants/{variantId}.

Elimina un producto

curl -X DELETE https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN"

La API responde 204. El producto y sus variantes se eliminan: su GET pasa a responder 404.

  • Los pedidos no cambian: cada línea guarda su copia del nombre, el SKU y el precio.
  • Sus SKU quedan libres para otro producto.
  • No se puede deshacer. Si solo quieres sacarlo de la tienda, archívalo.

Actúa en lote

Cambia muchos productos con POST /v1/catalog/products/batch/...:

  • status: cambia el estado.
  • tags: agrega o quita etiquetas con addTags y removeTags, hasta 100.
  • collections: los agrega o quita de colecciones manuales, con addCollectionIds y removeCollectionIds.
  • prices: cambia precios. Ver Variantes y precios.
  • delete: elimina.

Elige los productos con ids o con filters, nunca con ambos:

  • Con ids, hasta 100. La API responde 200 con el resultado de cada uno. En prices, usa items, también hasta 100.
  • Con filters, sin tope. Son los filtros de la lista, en JSON. La API responde 202 con una operación: síguela como en Importación de productos.

Este ejemplo archiva dos productos:

curl -X POST https://api.ecomiq.pe/api/v1/catalog/products/batch/status \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["7204558912004325302", "7204558912004325303"], "status": "archived" }'
Respuesta
{
  "results": [
    {
      "index": 0,
      "id": "7204558912004325302",
      "status": "updated",
      "errors": []
    },
    {
      "index": 1,
      "id": "7204558912004325303",
      "status": "failed",
      "errors": [
        { "field": null, "code": "Product.NotFound", "message": "Not found." }
      ]
    }
  ]
}
  • index es la posición en ids. status es updated, deleted o failed.
  • Cada producto se guarda por separado: si uno falla, los demás se aplican.
  • Un producto con más de 1000 variantes falla con resource_too_large al cambiar estado o eliminar.

Un filtro vacío elige todo

Con "filters": {}, el cambio alcanza a todos los productos no archivados.

Para eliminar con filters, envía expectedCount: cuántos productos esperas borrar. Si no coincide, no se borra nada. Obtén ese número con /count y exact=true:

Cuerpo de /batch/delete
{ "filters": { "status": ["archived"] }, "expectedCount": 24 }
curl -X POST https://api.ecomiq.pe/api/v1/catalog/products/exports \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "format": "csv", "status": ["active"] }'

La API responde 202 con una operación. Cuando termine, resultUrl trae el archivo. format es csv o xlsx; sin él, sale en xlsx. Los filtros son los mismos de la lista.

Cada fila representa una variante. Sus opciones aparecen en pares Opción N nombre y Opción N valor, con tantos pares como necesite el producto con más opciones de la selección y con el orden de cada producto. Las celdas de variantes sin opciones quedan vacías. Si ningún producto tiene opciones, no hay columnas de opción. La plantilla vacía ("template": true) incluye tres pares; puedes agregar más.

Puedes volver a importar el archivo para editar el catálogo. Cambiar solo una opción conserva las omitidas. Consulta Importación de productos para los encabezados aceptados y las validaciones de cada par.

Errores

codeEstadoQué hacer
Common.Validation400Revisa errors: falta un campo o tiene otro formato.
Catalog.Products.PlanLimitReached400Llegaste al máximo de tu plan: elimina productos o cambia de plan.
Products.BatchDeleteCountMismatch400El catálogo cambió: cuenta otra vez y reenvía expectedCount.
Common.Forbidden403Agrega a tu app el permiso que falta.
Product.NotFound404El producto no existe en la tienda o ya se eliminó.
Product.BrandNotFound, Product.CategoryNotFound404Revisa el ID de la marca o la categoría.
Product.VariantNotFound404Un variantId de variants no es de este producto.
Product.AlreadyExists, Product.SlugExists409Otro producto usa ese slug: cámbialo.
Product.VariantSkuExists409Otra variante ya usa ese SKU: cámbialo.

Siguientes pasos

Última actualización:

En esta página