Saltar al contenido
Catálogo

Categorías y colecciones

Ordena el catálogo con categorías, marcas, colecciones, atributos y guías de tallas.

Ordena el catálogo de una tienda de ropa en Lima: la categoría Ropa > Polos, la marca «Andes», la colección «Verano», un atributo de material y una guía de tallas para los polos.

Requisitos

  • Un token de Admin con los permisos catalog:create, catalog:read, catalog:update y catalog:delete en ECOMIQ_TOKEN. Ver Inicio rápido.
  • Un producto creado. Ver Variantes y precios.

Crea las categorías

Crea primero Ropa con { "name": "Ropa" }. Luego crea Polos con el id de Ropa en parentId.

curl -X POST https://api.ecomiq.pe/api/v1/catalog/categories \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Polos", "parentId": "7204558912004325501" }'

La API responde 201 con el id. Los pasos siguientes reutilizan call.

  • Sin slug, se genera desde name. No se repite en la tienda, aunque las categorías tengan padres distintos.
  • order ordena las categorías hermanas, de menor a mayor.

Ordena el árbol

GET /v1/catalog/categories/tree devuelve todas las categorías en orden, cada una con sus hijas en children y su ruta en path (ropa/polos).

Para mover o reordenar, envía el árbol con PUT. Si luego creas Casacas, este ejemplo la pone antes que Polos. La API responde 200 con true.

curl -X PUT https://api.ecomiq.pe/api/v1/catalog/categories/tree \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "categories": [{
    "id": "7204558912004325501",
    "children": [{ "id": "7204558912004325503" }, { "id": "7204558912004325502" }]
  }] }'
  • El anidamiento define el padre, y la posición en cada lista define order. Los parentId y order de cada nodo se ignoran.
  • Los nodos del primer nivel quedan en la raíz. Las categorías que no envías no cambian.

PUT reemplaza la categoría

PUT /v1/catalog/categories/{categoryId} también mueve una categoría con otro parentId, pero la reemplaza entera: si omites parentId, order, description, logo, icon, requiresSizeGuide o las comisiones, vuelven a su valor por defecto. Sin slug, se genera otra vez desde name.

Crea la marca

curl -X POST https://api.ecomiq.pe/api/v1/catalog/brands \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Andes", "logo": "https://cdn.mitienda.pe/marcas/andes.png" }'

La API responde 201 con el id.

  • Sin slug, se genera desde name. No se repite en la tienda.
  • logo e icon deben ser URLs absolutas.
  • PUT /v1/catalog/brands/{brandId} reemplaza nombre, slug, imágenes, descripción y orden.

Asigna categoría y marca

Envía categoryId y brandId al actualizar el producto, o al crearlo. Este ejemplo también le pone la etiqueta verano.

curl -X PATCH https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "categoryId": "7204558912004325502", "brandId": "7204558912004325510", "tags": ["verano"] }'
Respuesta 200 (extracto)
{
  "id": "7204558912004325302",
  "tags": ["verano"],
  "category": {
    "id": "7204558912004325502",
    "name": "Polos",
    "path": "ropa/polos"
  },
  "brand": { "id": "7204558912004325510", "name": "Andes" }
}
  • Un producto tiene una sola categoría y una sola marca.
  • Para quitarlas, envía clearCategory: true o clearBrand: true, sin el ID.

Crea una colección automática

Una colección dynamic se llena sola con los productos que cumplen sus reglas. «Verano» junta los polos con la etiqueta verano y fija uno arriba. Con and, el producto debe cumplir todas las reglas; con or, basta una.

verano.json
{
  "name": "Verano",
  "type": "dynamic",
  "status": "active",
  "dynamicOperator": "and",
  "rules": [
    { "field": "categoryId", "operator": "eq", "value": "7204558912004325502" },
    { "field": "tag", "operator": "eq", "value": "verano" }
  ],
  "pins": [{ "productId": "7204558912004325302", "position": 0 }]
}
curl -X POST https://api.ecomiq.pe/api/v1/catalog/collections \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  --data @verano.json

La API responde 201 con el id.

Para incluirRegla
Varias marcas{ "field": "brand", "operator": "in", "value": "<id>,<id>" }
Menos de S/ 100{ "field": "price", "operator": "lt", "value": "100" }
Un texto en el nombre{ "field": "title", "operator": "contains", "value": "pima" }
  • value siempre es texto. Con in y notIn, separa hasta 100 valores con comas.
  • categoryId compara la categoría del producto, sin sus subcategorías.
  • includeProductIds suma productos. excludeProductIds los saca, aunque cumplan las reglas o estén fijados.

La colección se llena en segundo plano, y solo mientras está active y dentro de validFrom y validTo. Sus productos, con sortOrder e isPinned, salen en GET /v1/catalog/collections/{collectionId}/products.

Para editar, envía todo

PUT /v1/catalog/collections/{collectionId} reemplaza la colección. Sin type, queda static y pierde sus reglas y productos. Sin status, vuelve a draft.

Crea una colección manual

Una colección static tiene solo los productos que eliges. Créala y envía la lista. El PUT responde 204.

curl -X POST https://api.ecomiq.pe/api/v1/catalog/collections \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Regalos", "type": "static", "status": "active" }'

curl -X PUT https://api.ecomiq.pe/api/v1/catalog/collections/7204558912004325521/products \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "productIds": ["7204558912004325302", "7204558912004325303"] }'

Define un atributo

Un atributo (especificación) describe el producto, como su material. Con type: "select", solo acepta sus values: cada uno tiene un value, que lo identifica, y un name, que se muestra.

curl -X POST https://api.ecomiq.pe/api/v1/catalog/specifications \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Material", "key": "material", "type": "select",
    "values": [{ "value": "algodon-pima", "name": "Algodón pima" }, { "value": "lino", "name": "Lino" }]
  }'

La API responde 201 con el id. El producto guarda su valor en specifications, con la key del atributo:

curl -X PATCH https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302 \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "specifications": [{ "key": "material", "name": "Material", "value": "algodon-pima" }] }'
  • key acepta letras, números, - y _. Se guarda en minúsculas y no se repite en la tienda.
  • specifications reemplaza la lista del producto. Una key que no existe crea un atributo de texto nuevo.
  • Si el valor no es una opción del atributo, la API responde 409.

Para editar, envía todo

PUT /v1/catalog/specifications/{id} reemplaza el atributo. Envía siempre type: sin él, la API asume input. En values, manda las opciones que quedan con su id y las nuevas sin id. La que falta se borra; si está en uso, la API responde 409.

Exige el atributo en una categoría

Asocia Material a Polos y márcalo obligatorio. La API responde 204. La lista reemplaza la anterior, y GET en la misma ruta la devuelve.

curl -X PUT https://api.ecomiq.pe/api/v1/catalog/categories/7204558912004325502/specifications \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "specifications": [{ "specificationId": "7204558912004325530", "isRequired": true }] }'
  • Admite hasta 100 atributos activos, con level product o all.
  • Un producto de Polos en active u outOfStock necesita ese valor, o la API responde 409 al guardarlo. Solo cuenta su categoría directa.
  • Solo la categoría exige atributos: un producto sin categoría no tiene obligatorios.

Crea la guía de tallas

Una guía es una tabla de medidas por talla. Asígnala al crearla con assignments.

guia-polos.json
{
  "name": "Polos unisex",
  "status": "active",
  "rows": [
    {
      "label": "S",
      "sizeKey": "S",
      "order": 0,
      "measurements": [
        {
          "key": "pecho",
          "name": "Pecho",
          "min": 86,
          "max": 91,
          "value": null,
          "description": null
        }
      ]
    },
    {
      "label": "M",
      "sizeKey": "M",
      "order": 1,
      "measurements": [
        {
          "key": "pecho",
          "name": "Pecho",
          "min": 92,
          "max": 97,
          "value": null,
          "description": null
        }
      ]
    }
  ],
  "assignments": [
    { "targetType": "category", "targetId": "7204558912004325502" }
  ]
}
curl -X POST https://api.ecomiq.pe/api/v1/catalog/size-guides \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  --data @guia-polos.json

La API responde 201 con el id.

  • Solo se aplican las guías active. Sin status, queda en draft.
  • Necesita rows o imageUrl. Cada fila y medida lleva todos sus campos, aunque sea con null.
  • Sin gender, measurementType ni unit, valen unisex, body y cm. Si otra guía activa con ese gender y measurementType ya está en el mismo producto o categoría, la API responde 409.

Para editar, envía todo

PUT /v1/catalog/size-guides/{sizeGuideId} reemplaza los datos y las filas, y conserva las asignaciones. Sin status, la guía vuelve a draft y deja de aplicarse.

Asigna la guía

Gana la asignación más cercana: la del producto, luego la de su categoría y luego la de una categoría padre con includeChildrenCategories: true. Entre guías del mismo nivel, gana la de mayor priority.

# Guía propia de un producto. Responde 204. Con null, se la quitas.
curl -X PUT https://api.ecomiq.pe/api/v1/catalog/products/7204558912004325302/size-guide \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "sizeGuideId": "7204558912004325540" }'

# Una categoría y sus hijas. Responde 201 con el id de la asignación.
curl -X POST https://api.ecomiq.pe/api/v1/catalog/size-guides/7204558912004325540/assignments \
  -H "Authorization: Bearer $ECOMIQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "targetType": "category", "targetId": "7204558912004325501", "includeChildrenCategories": true }'

GET /v1/catalog/products/{productId}/size-guide responde 200 con la guía que aplica, o 204 si no hay ninguna. Para quitar una asignación, usa DELETE /v1/catalog/size-guides/{sizeGuideId}/assignments/{assignmentId}.

Elimina lo que no usas

Cada DELETE responde 204.

RecursoRutaSe borra si
Categoría/v1/catalog/categories/{categoryId}No tiene subcategorías ni productos.
Marca/v1/catalog/brands/{brandId}Ningún producto la usa.
Atributo/v1/catalog/specifications/{id}Ninguna categoría, producto ni variante lo usa.
Colección/v1/catalog/collections/{collectionId}Siempre. Los productos no cambian.
Guía de tallas/v1/catalog/size-guides/{sizeGuideId}Siempre. Sale de los productos que la usaban.

GET /v1/catalog/specifications/{id}/usage dice cuántos productos y variantes usan un atributo, y en qué categorías está.

Importa y exporta

Categorías, marcas, colecciones y guías de tallas también van por archivo, en /imports y /exports. Responden 202 con una operación: síguela como en Importación de productos. Al terminar una exportación, resultUrl trae el archivo.

Errores

codeEstadoQué hacer
Common.Validation400Revisa errors: falta un campo o tiene otro formato.
Category.SlugExists, Brand.SlugExists, Collection.SlugExists, Collection.Exists, SizeGuide.SlugExists409Otro recurso usa ese slug o name: cámbialo.
Category.ParentNotFound404El parentId no existe en la tienda.
Category.CircularReference, Categories.InvalidHierarchy400Una categoría no puede quedar dentro de sí misma.
Category.HasSubcategories, Category.HasProducts, Brand.HasProducts409Mueve las subcategorías o los productos antes de borrar.
Product.CategoryNotFound, Product.BrandNotFound404Revisa el ID de la categoría o la marca.
Collection.InvalidType400Solo las colecciones static reciben productos a mano.
Specification.AlreadyExists409Otro atributo usa esa key o alias.
Specification.ValueInUse409Cambia ese valor en los productos antes de quitarlo.
Specification.HasCategorySpecifications, Specification.InUseByProducts, Specification.InUseByVariants409Quita el atributo de categorías, productos y variantes antes de borrarlo.
Category.Specifications400Un atributo se repite, no existe, está inactivo o no es para productos.
SizeGuideAssignment.Conflict409Ya hay una guía compatible en ese producto o categoría.
SizeGuide.Inactive400Activa la guía antes de asignarla a un producto.
Common.Conflict409Lee detail: falta un atributo obligatorio o un valor no vale.

Siguientes pasos

Última actualización:

En esta página