Catálogo de productos
Empuja y mantén tu catálogo por SKU desde tu propio sistema (ERP, PIM, tienda).
Endpoints
| Endpoint | Qué hace |
|---|---|
GET /v1/products | Lista paginada (limit ≤ 200, offset, q de búsqueda, status). Scope catalog:read. |
GET /v1/products/{id} | Detalle de un producto, incluido su source_data. Scope catalog:read. |
POST /v1/products | Upsert masivo por SKU, hasta 500 por request. Scope catalog:write. |
PATCH /v1/products/{id} | Edición parcial de sku, name, brand o category. Scope catalog:write. |
DELETE /v1/products/{id} | Borrado suave (204). Conserva el historial; se oculta de listas y export. Scope catalog:write. |
GET /v1/products/{id}/revisions | Qué ha cambiado en la ficha: versiones, con qué cambió en cada una. Scope catalog:read. |
Upsert masivo por SKU
El POST es idempotente por (organización, SKU): re-enviar el mismo lote deja el catálogo igual, y un SKU previamente borrado se revive. La respuesta desglosa cuántos se crearon, actualizaron u omitieron.
POST /v1/products
{
"products": [
{
"sku": "CAMISA-001",
"name": "Camisa de lino",
"brand": "Acme",
"category": "Ropa/Camisas",
"source_data": { "color": "azul", "talla": "M" }
}
]
}
{ "total": 1, "created": 1, "updated": 0, "skipped": 0 }source_data
source_data es tuyo: un objeto JSON libre con los atributos extra de tu producto (color, talla, material, especificaciones…). El motor de generación lo usa como contexto para escribir mejores descripciones — entre más rico, mejor el resultado.
Editar y borrar
PATCH edita campos sueltos sin tocar el resto. El status del producto NO se edita por API (lo maneja el ciclo de generación). Si el SKU nuevo ya existe en otro producto, responde 409.
DELETE es un borrado suave: el producto desaparece de listas y del export pero su historial se conserva, y un upsert posterior con el mismo SKU lo revive. Repetir el DELETE responde 404.
Historial de una ficha
Si sincronizas con tu tienda, esto te dice qué mirar sin volver a descargar la ficha entera: cada versión trae qué cambió respecto a la anterior — campos, atributos (por código e idioma), categorías y familia. De los datos importados se reportan los nombres de las columnas que cambiaron, nunca su contenido.
GET /v1/products/7f3a…/revisions
{
"revisions": [
{
"version": 7,
"reason": "import",
"created_at": "2026-09-12T05:03:11Z",
"changes": {
"base": { "name": ["Crema hidratante", "Crema hidratante 50 ml"] },
"values": { "tamano": { "": [["1.7 OZ"], ["50 ml"]] } },
"source_data": { "changed": ["precio"] }
}
}
],
"total": 7,
"limit": 20
}Se pagina hacia atrás: limit (1–50, por defecto 20) y before_version, al que le pasas la versión más baja que recibiste. changes llega vacío en la primera versión de un producto, que no tiene con qué compararse; y si un cambio es enorme, llega recortado con _truncated y conteos.