Listar y buscar productos

Esta página cubre el catálogo de lectura del dominio Productos: el listado principal con filtros, la búsqueda de texto libre, el conteo, la verificación de existencia por SKU, la resolución de un producto padre a partir del SKU de una variante, los catálogos auxiliares de marcas/tipos y la búsqueda avanzada por POST.

No hay un envelope único en Productos

A diferencia de otros dominios de la API, Productos no responde con una forma de envelope consistente en todos sus endpoints. Cada endpoint de esta página documenta su forma de respuesta real — no asumas {data, meta} en ninguno salvo el caso explícito que se marca abajo.

Permiso requerido en todos los endpoints de esta página: products:read.

Listado principal

Lista los productos del tenant autenticado, con filtros y paginación

qstring

Búsqueda de texto libre. Alias: term, search.

statusstring

Filtra por estado del producto (active, disabled, draft).

bindingStatusstring

Filtra por el estado de vínculo con un canal de venta.

categorystring

Filtra por categoría.

categoryPathstring

Filtra por ruta completa de categoría.

brandsstring

Filtra por una o varias marcas. Alias: brand.

minPricenumber

Precio mínimo.

maxPricenumber

Precio máximo.

inStockboolean

Filtra productos con existencia disponible.

minStocknumber

Existencia mínima requerida.

locationIdstring

Filtra por ubicación de inventario.

availableAtstring

ID de ubicación. Activa el envelope {data, meta} — ver la nota de abajo.

tagsstring

Filtra por etiqueta(s).

channelIdstring

Filtra por un canal de venta específico.

channelTypestring

Filtra por tipo de canal (shopify, amazon, mercadolibre, etc.).

channelIdsstring

Variante de channelId que acepta múltiples IDs.

excludeChannelIdsstring

Excluye productos vinculados a estos canales.

createdAfterstring

Fecha mínima de creación (ISO 8601).

createdBeforestring

Fecha máxima de creación (ISO 8601).

updatedAfterstring

Fecha mínima de última actualización (ISO 8601).

updatedBeforestring

Fecha máxima de última actualización (ISO 8601).

typestring

Filtro heredado sobre el tipo de producto. Ver la nota sobre productType en el modelo de datos.

productTypestring

Filtra por el campo real persistido: physical, digital, service, bundle, supply, material.

includeDisabledboolean

Incluye productos con status disabled en el resultado.

categoriesstring

Variante de category que acepta múltiples valores.

departmentsstring

Filtra por departamento.

productKindsstring

Filtra por uno o varios productKind.

activeboolean

Filtra por productos activos.

hasImagesboolean

Filtra productos con (o sin) imágenes en media[].

hasVariantsboolean

Filtra productos con (o sin) variantes.

skusstring

Filtra por una lista de SKUs específicos.

idsstring

Filtra por una lista de IDs específicos.

includeInventoriesboolean

Adjunta datos de inventario a cada producto del resultado.

extendstring

Lista separada por comas de campos extendidos a incluir. Ver 'El sistema de proyección extend' más abajo.

pagenumber

Número de página. Default: 0.

limitnumber

Resultados por página. Default: 20. Máximo: 500.

200
[
  {
    "id": "65f3a1b2c4d5e6f7a8b9c0e1",
    "sku": "CAM-ROJO-M",
    "status": "active",
    "productType": "physical",
    "title": { "value": "Camisa Roja Talla M", "translations": [] },
    "price": 499.00,
    "compareAtPrice": 599.00,
    "currency": "MXN",
    "taxable": true,
    "brand": "Fenicia Basics",
    "tags": ["playeras", "temporada-verano"],
    "media": [
      {
        "id": "m1",
        "src": "https://cdn.fenicia.io/img/cam-rojo-m.jpg",
        "type": "image",
        "position": 0,
        "alt": { "value": "Camisa roja talla M", "translations": [] }
      }
    ],
    "variants": [],
    "bindings": []
  }
]

Único endpoint del dominio con envelope {data, meta}

Sin el parámetro availableAt, GET /products responde un arreglo plano de productos (comportamiento heredado, mostrado arriba). Cuando envías availableAt=<locationId>, la respuesta cambia de forma a un envelope con paginación:

{
  "data": [
    { "id": "65f3a1b2c4d5e6f7a8b9c0e1", "sku": "CAM-ROJO-M", "...": "..." }
  ],
  "meta": {
    "pagination": {
      "page": 0,
      "limit": 20,
      "total": 143,
      "totalPages": 8,
      "hasMore": true
    }
  }
}

Este es el único endpoint de todo el dominio Productos que usa este envelope. Ningún otro — ni el resto del catálogo, ni collections, ni categories, ni las rutas bulk — lo replica. No construyas tu cliente asumiendo que este contrato es general.

Búsqueda de texto libre

Búsqueda de texto libre sobre el catálogo

qstring

Término de búsqueda. Alias: query.

limitnumber

Resultados por página. Default: 20.

pagenumber

Número de página. Default: 0.

200Envelope exacto no verificado línea por línea — ver Callout debajo.
[
  {
    "id": "65f3a1b2c4d5e6f7a8b9c0e1",
    "sku": "CAM-ROJO-M",
    "title": { "value": "Camisa Roja Talla M", "translations": [] },
    "price": 499.00,
    "currency": "MXN"
  }
]

Shape de respuesta no verificado campo a campo

Este endpoint delega directamente en ProductsService.search de la librería. La auditoría confirmó los parámetros de entrada, pero no verificó línea por línea el envelope exacto de salida (arreglo plano vs. objeto envolvente). Los productos que devuelve tienen el shape real de Product (ver modelo de datos); confirma la forma exacta del contenedor contra una respuesta real antes de depender de ella.

Conteo

Cuenta los productos que cumplen los filtros indicados

200
{ "count": 143 }

Acepta el mismo conjunto de filtros que el listado principal (q, status, category, brands, minPrice, maxPrice, tags, channelId, etc.); no aplica page/limit porque no pagina resultados. Cuando envías un término de búsqueda (term), la respuesta incluye además la estrategia de búsqueda usada:

{ "count": 27, "searchStrategy": "text" }

Tip

El valor exacto de searchStrategy no fue enumerado exhaustivamente en la auditoría — trátalo como informativo, no como un enum cerrado para tu lógica de negocio.

Productos por ubicación

Dos endpoints devuelven productos filtrados por ubicación de inventario, con distinto propósito y tamaño de payload.

Productos con inventario en una ubicación específica

locationIdstringrequired

ID de la ubicación. Requerido.

limitnumber

Resultados por página. Default: 20.

pagenumber

Número de página. Default: 0.

termstring

Filtro de texto adicional.

200Resultado de getProductsByLocation — shape exacto no verificado línea por línea, ver Callout debajo.
[
  { "id": "65f3a1b2c4d5e6f7a8b9c0e1", "sku": "CAM-ROJO-M", "price": 499.00 }
]
400Sin campo code, a diferencia del resto del dominio.
{ "error": "Missing required query parameter: locationId" }

Error 400 sin código, y shape de respuesta no verificado

Si omites locationId, este endpoint responde 400 con {"error": "Missing required query parameter: locationId"}sin un campo code, a diferencia de la convención del resto del dominio. El shape exacto de la respuesta exitosa (resultado de getProductsByLocation) tampoco fue verificado línea por línea en la auditoría; confírmalo contra una respuesta real.

Vista minimizada de productos con inventario en una ubicación (payload reducido, pensado para listas grandes)

locationIdstringrequired

ID de la ubicación. Requerido.

pagenumber

Número de página. Default: 0.

limitnumber

Resultados por página. Default: 20. Máximo: 100.

termstring

Filtro de texto adicional.

200
{
  "products": [
    { "sku": "CAM-ROJO-M", "title": "Camisa Roja Talla M", "price": 499.00 }
  ],
  "total": 128
}
400
{
  "code": "bad-request/missing-param",
  "message": "Missing required query parameter: locationId",
  "parameter": "locationId"
}

Composición exacta de cada producto no enumerada

La respuesta confirmada envuelve en {products, total} — con payload minimizado (~500 bytes por producto, contra ~3 KB del producto completo). La auditoría no enumeró el listado completo y definitivo de campos que trae cada item; el ejemplo de arriba es ilustrativo con campos que sí existen en el modelo real, no una copia exacta verificada del código.

Errores comunes de /products/inventory-view: 400 bad-request/missing-param, 400 bad-request/invalid-param, 500 inventory-view/error.

Verificar existencia de un SKU

Verifica si existe un producto con el SKU indicado

skustringrequired

SKU a verificar.

200
{ "exist": true }

Responde 400 si el path param sku viene vacío.

Producto padre por SKU de variante

Resuelve el producto padre completo a partir del SKU de una de sus variantes

skustringrequired

SKU de la variante (no del producto padre).

404
{
  "code": "not-found",
  "message": "No product found containing variant with SKU: CAM-ROJO-M-AZUL"
}

La respuesta exitosa es el Product padre completo — mismo shape que GET /products/{id}, no una vista reducida.

Marcas y tipos

Dos catálogos auxiliares para poblar filtros en tu UI, ambos devuelven un arreglo simple de strings:

Lista todas las marcas distintas usadas en el catálogo del tenant

200
["Fenicia Basics", "Nike", "Adidas"]

Lista todos los productKind distintos usados en el catálogo del tenant

200
["playera", "pantalon", "calzado"]

Búsqueda avanzada (POST)

Para filtros complejos que no caben cómodamente en query string, o para pedir explícitamente el nivel de detalle de cada producto devuelto.

Búsqueda avanzada por cuerpo JSON, con control explícito de proyección

filtersobject

Objeto de filtros estructurado. Uno de filters o query, nunca ambos.

querystring

Término de búsqueda libre, alternativo a filters. Uno de filters o query, nunca ambos.

pagenumber

Número de página.

limitnumber

Resultados por página.

includeInventoriesboolean

Adjunta datos de inventario a cada producto.

inStockboolean

Filtra solo productos con existencia.

projectionstring

'default' o 'full' — controla el conjunto de campos que trae cada producto.

{
  "filters": { "status": "active", "category": "playeras" },
  "page": 0,
  "limit": 50,
  "projection": "default"
}
200
{
  "products": [
    { "id": "65f3a1b2c4d5e6f7a8b9c0e1", "sku": "CAM-ROJO-M", "price": 499.00 }
  ],
  "total": 27,
  "page": 0,
  "limit": 50
}
400
{
  "code": "bad-request/ambiguous-param",
  "message": "Body must contain `query` OR `filters`, not both",
  "parameter": "query|filters"
}

Permiso requerido: products:read

filters y query son mutuamente excluyentes

Enviar filters y query en el mismo request responde 400 con bad-request/ambiguous-param. Envía exactamente uno de los dos.

Errores: 400 bad-request/missing-param, 400 bad-request/ambiguous-param, 500 internal-error/missing-count.

El sistema de proyección ?extend=

Varios endpoints de Productos (este listado y GET /products/{id}) aceptan extend como una lista separada por comas de campos adicionales a incluir en la respuesta, de un conjunto cerrado:

variants, options, description, bindings, metadata, inventory, dimensions, seo, all

all incluye todos los campos extendidos disponibles. Los detalles de qué hace extend=inventory/extend=all específicamente (adjuntar inventario por variante y ubicación) se documentan en Consultar un producto, donde el parámetro tiene su efecto más completo.

Paginación

page inicia en 0. El limit por defecto y el máximo permitido varían por endpoint:

Endpointlimit por defectolimit máximo
GET /products20500
GET /products/search20— (no confirmado)
GET /products/inventory20— (no confirmado)
GET /products/inventory-view20100

Errores

CódigoStatusDescripción
bad-request/missing-param400Falta un parámetro requerido (por ejemplo locationId en /products/inventory-view, o filters/query en /products/query).
bad-request/ambiguous-param400/products/query recibió filters y query a la vez.
bad-request/invalid-param400Un parámetro tiene un valor con formato incorrecto.
not-found404No existe un producto que resuelva el SKU indicado.
internal-error/missing-count500Error interno calculando el total de resultados.
inventory-view/error500Error interno en /products/inventory-view.

Los códigos de autenticación (token inválido, permiso faltante) son los mismos en toda la plataforma — consulta el catálogo completo de errores.

Aislamiento por tenant

Todos los endpoints de esta página filtran exclusivamente por el tenant autenticado. No existe forma de listar o buscar productos de otro tenant.

Siguientes pasos