Saltar al contenido
Tienda online

Catálogo

Busca, filtra y pagina productos, y muestra la ficha con sus variantes.

Muestra los polos de algodón de tu tienda de Lima entre S/ 40 y S/ 80, talla M, con stock.

Requisitos

  • El slug o un dominio de la tienda, en x-Store-Domain. No necesitas token.
  • Productos publicados en la tienda.

Lista productos

GET /v1/products devuelve una página del catálogo publicado.

curl "https://storefront.ecomiq.pe/v1/products?pageSize=24&sort=priceAsc&includeFilters=false" \
  -H "x-Store-Domain: mi-tienda"
Respuesta
{
  "totalCount": 58,
  "totalPages": 3,
  "products": [
    {
      "id": "7204558912004322039",
      "name": "Polo de algodón pima",
      "slug": "polo-de-algodon-pima",
      "url": "/products/polo-de-algodon-pima",
      "imageUrl": "https://…/polo.webp",
      "price": 59.9,
      "compareAtPrice": 79.9,
      "isAvailable": true
    }
  ],
  "filters": []
}

Los ejemplos siguientes reutilizan API y headers.

  • price es el de la variante más barata. Si compareAtPrice es mayor, muéstralo tachado.
  • Con isAvailable: false, ninguna variante se puede vender. Muestra «Agotado».
  • Enlaza cada producto a su url. Pide su ficha con slug.
  • Sin panel de filtros, envía includeFilters=false: filters llega vacío.

sort acepta priceAsc, priceDesc, newest, oldest, nameAsc, nameDesc y bestSelling. Sin sort, salen primero los productos editados hace poco. En una sola colección, sin sort, siguen el orden del comercio.

Busca por texto

Envía lo que escribió el comprador en search.

curl -G https://storefront.ecomiq.pe/v1/products \
  -H "x-Store-Domain: mi-tienda" \
  --data-urlencode "search=polo algodón"
  • Busca en nombre, descripción, marca, categoría, etiquetas, SKU, código de barras y especificaciones buscables.
  • Sin sort, ordena por relevancia.
  • Combínalo con los filtros. Los filtros de la respuesta se ajustan a la búsqueda.
  • Para sugerir productos mientras escribe, usa el autocompletado.

Todos los filtros son opcionales y se combinan. Copia los valores del filters de la respuesta.

ParámetroFiltra porGrupo en filters
categoryIdUna categoría, por id. Sin subcategorías.—
categoriesCategorías, por nombre.category
collectionIdUna colección, por id.—
collectionsColecciones, por slug.collection
brandsMarcas, por nombre.brand
tagsEtiquetas.tag
productTypesproduct, service o bundle.productType
sellersVendedores, por slug.—
productIdsProductos, por id. Hasta 100.—
minPrice, maxPricePrecio, en la moneda de la tienda.price
inStocktrue: con stock. false: agotados.availability
filtersOpciones y especificaciones.option:…, attribute:…
curl -G https://storefront.ecomiq.pe/v1/products \
  -H "x-Store-Domain: mi-tienda" \
  --data-urlencode "categories=Polos" \
  -d "minPrice=40" -d "maxPrice=80" -d "inStock=true"
  • Para varios valores, repite el parámetro: brands=Andina&brands=Kuna. Basta con que coincida uno.
  • Un producto entra si el rango de precios de sus variantes se cruza con el tuyo.
  • Con productIds, el orden no es el que enviaste. Ordena tú la lista.

Arma los filtros

Sin includeFilters=false, la respuesta trae filters: un grupo por filtro, con sus valores y conteos.

Respuesta
{
  "filters": [
    {
      "id": "price",
      "label": "Price",
      "type": "price_range",
      "min": 29.9,
      "max": 149.9,
      "selectedMin": 40,
      "selectedMax": 80
    },
    {
      "id": "option:Talla",
      "label": "Talla",
      "type": "list",
      "values": [
        { "value": "M", "count": 12, "label": "M", "selected": true },
        { "value": "L", "count": 10, "label": "L", "selected": false }
      ]
    }
  ]
}

Cuando el comprador marca un valor, envíalo en el parámetro de su grupo. En availability, in_stock es inStock=true y out_of_stock, inStock=false.

En filters, une el id del grupo, : y el value. Para talla M y algodón, envía filters=option:Talla:M y filters=attribute:Material:Algodón.

  • option son opciones de variante. attribute, especificaciones del producto.
  • Elige un solo valor por opción. Con dos, responde 400.
  • Varias opciones deben coincidir en la misma variante. Con inStock=true, esa variante además tiene stock.
  • De un attribute puedes enviar varios valores. Basta con que coincida uno.
  • Envía hasta 100 filters, de hasta 250 caracteres cada uno.
  • label llega en inglés en los grupos fijos. Muestra tu texto según id.
  • Si el label de un valor es null, muestra value.
  • En price, min y max ignoran tu rango. selectedMin y selectedMax son el tuyo.
  • Los conteos aplican todos tus filtros. Al marcar una marca, brand solo trae esa.
  • Solo salen las opciones y especificaciones que el comercio marcó como filtrables.

Pagina los resultados

Avanza page y conserva los mismos filtros y sort.

curl "https://storefront.ecomiq.pe/v1/products?categories=Polos&page=2&pageSize=24" \
  -H "x-Store-Domain: mi-tienda"
  • page empieza en 1 y llega hasta 100. Fuera de ese rango, responde 400.
  • pageSize vale 24 si no lo envías. El máximo es 100.
  • Después de totalPages, products llega vacío.
  • Con más de 100 páginas, no llegas al final. Sube pageSize o pide que filtre.

Muestra un producto

GET /v1/products/{slug} devuelve la ficha completa. Usa el slug del listado.

curl https://storefront.ecomiq.pe/v1/products/polo-de-algodon-pima \
  -H "x-Store-Domain: mi-tienda"
Respuesta
{
  "id": "7204558912004322039",
  "name": "Polo de algodón pima",
  "price": 59.9,
  "compareAtPrice": 79.9,
  "isAvailable": true,
  "images": [{ "url": "https://…/polo.webp", "order": 1, "type": "image" }],
  "specifications": [{ "name": "Material", "value": "Algodón" }],
  "variants": [
    {
      "id": "7204558912004323197",
      "price": 59.9,
      "compareAtPrice": 79.9,
      "quantity": 4,
      "isAvailable": true,
      "options": [
        { "key": "talla", "name": "Talla", "value": "M" },
        { "key": "color", "name": "Color", "value": "Azul", "color": "#1F3A93" }
      ]
    },
    {
      "id": "7204558912004323198",
      "isAvailable": false,
      "options": [
        { "key": "talla", "name": "Talla", "value": "L" },
        { "key": "color", "name": "Color", "value": "Azul" }
      ]
    }
  ]
}
  • La ficha aplica las listas de precios vigentes. Si difiere del listado, vale la ficha.
  • price y compareAtPrice son los de la variante más barata.
  • Ordena images por order. type es image o video: los videos van entre las fotos, donde los puso el comerciante.
  • metafields trae solo los metacampos que la tienda marcó para mostrar, con name listo para mostrar y value.
  • brandSlug lleva a la página de la marca; es null si el producto no tiene marca o la marca está inactiva.
  • specifications es la ficha técnica. sizeGuide es la guía de tallas, o null.
  • priceTiers trae precios por cantidad: unitPrice desde minQuantity.
  • Si el producto no existe o no está publicado, responde 404.

Con el previewKey del enlace de vista previa del admin, ves un producto sin publicar. Llega con isPreview: true: no lo guardes en caché ni lo indexes.

Elige la variante

Arma un selector por cada key de variants[].options: name es el título y cada value, un botón. Luego busca la variante que coincide en todas.

const groups = new Map();
for (const variant of product.variants) {
  for (const option of variant.options) {
    const group = groups.get(option.key) ?? { name: option.name, values: [] };
    if (!group.values.includes(option.value)) group.values.push(option.value);
    groups.set(option.key, group);
  }
}

const selected = { talla: "M", color: "Azul" };
const variant = product.variants.find((item) =>
  item.options.every((option) => selected[option.key] === option.value),
);
const canBuy = variant !== undefined && variant.isAvailable !== false;
  • Si ninguna variante coincide, esa combinación no existe. Desactívala.
  • Con isAvailable: false, la variante está agotada. Desactiva la compra.
  • Mira isAvailable, no quantity. Sin control de stock o con venta sin stock, se vende con quantity en 0.
  • Muestra price, compareAtPrice e images de la variante. Sin images, usa las del producto.
  • color trae el hex para la muestra de color.
  • Al abrir la ficha, elige la primera variante disponible.

Agrega al carrito

Envía el id de la variante como variantId a POST /v1/carts/{cartToken}/items. El carrito vuelve a validar el stock. Si no alcanza, responde 400 con Catalog.InsufficientStock. Sigue en Carrito.

Muestra una marca

GET /v1/brands/{slug} devuelve la marca activa con su logo (imageUrl), su description, los textos para buscadores (metaTitle y metaDescription) y productCount. Si la marca no existe o está inactiva, responde 404. Para listar sus productos, filtra el catálogo con su nombre en brands. Con GraphQL, brand(slug:) trae la marca y products(input:) sus productos en la misma consulta.

GET /v1/sitemap incluye /brands/{slug} para cada marca activa con productos visibles. Si tu tienda arma su propio sitemap, publica esas URLs solo si tiene la página de la marca.

Errores

codeEstadoQué hacer
Common.Validation400Revisa errors: page, pageSize, filters o sort no son válidos, o un parámetro tiene otro tipo.
Common.BadRequest400Falta x-Store-Domain.
Common.NotFound404La tienda o la colección de collectionId no existe o está inactiva.
Product.NotFound404El producto no existe, no está publicado o previewKey no sirve.
Common.Unauthorized401La tienda es privada. Pide la contraseña.
Common.ServiceUnavailable503El buscador no responde. Reintenta en unos segundos.

Siguientes pasos

Última actualización:

En esta página