API para desarrolladores

Conectá el motor de catálogos AI-ready de Mostrador a tu producto: ERP, marketplace, otra app o tu propio proyecto. Mandanos tu catálogo crudo y te lo dejamos listo para agentes de IA, con búsqueda semántica, feeds y reservas — todo detrás de una sola API key.

Publicá donde quieras. El catálogo ya normalizado y enriquecido (atributos, categoría, título, GTIN) es justo lo que piden los marketplaces. Tomás los datos por esta API y construís la publicación en Mercado Libre u otra plataforma sobre nuestros rieles — vos armás y sos dueño de esa integración.

Autenticación

Toda llamada lleva el header X-API-Key. La key resuelve a tu comercio (tenant) y solo toca los datos de ese tenant. Cada llamada autenticada queda registrada para tu facturación por uso.

curl -H "X-API-Key: TU_API_KEY" https://api.quienlotiene.app/v1/health

Envelope de respuesta

Todas las respuestas son JSON con la misma forma, en éxito y en error:

{
  "ok": true,
  "data": { ... },
  "error": null,
  "request_id": "a1b2c3d4e5f6a7b8"
}

En error, ok es false, data es null y error trae {code, message}.

POST/v1/catalog/sync

Mandame tu catálogo crudo, te lo dejo AI-ready. Acepta JSON {"products":[...]} o un archivo CSV/XLSX (multipart). Full-catalog: los SKU ausentes se dan de baja suave (stock 0).

curl -X POST https://api.quienlotiene.app/v1/catalog/sync \
  -H "X-API-Key: TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"products":[
        {"sku":"FIL-001","name":"Filtro de aceite","price":18900,"stock":5,"brand":"Mann"}
      ]}'

data: {synced, soft_deleted, unchanged, health_score, row_errors}

POST/v1/enrich

Utilidad pura: normaliza y enriquece un producto y devuelve sugerencias (marca/categoría/atributos). No persiste nada.

curl -X POST https://api.quienlotiene.app/v1/enrich \
  -H "X-API-Key: TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product":{"sku":"X-1","name":"FILTRO ACEITE JD","price":18900,"stock":3}}'

data: {product, search_text, suggestions}

GET/v1/products/{sku}

Detalle del producto + su vista canónica (ofertas de toda la red, mejor GTIN, rango de precios) cuando existe un gemelo en la red.

curl -H "X-API-Key: TU_API_KEY" https://api.quienlotiene.app/v1/products/FIL-001

data: {product, canonical:{gtin, price_range, offer_count, offers:[{price, availability}]} | null}

GET/v1/catalog

El catálogo completo del comercio, paginado — para bajarlo en lotes y publicarlo en un marketplace (ej.: Mercado Libre). Cada producto viene AI-ready: título estandarizado, atributos, categoría, GTIN, imagen, precio, stock. Usá updated_since para sync incremental: traés solo lo que cambió desde tu última corrida y mantenés el stock/precio al día sin releer todo.

curl -H "X-API-Key: TU_API_KEY" "https://api.quienlotiene.app/v1/catalog?limit=100&offset=0"
# incremental: solo lo que cambió desde una fecha
curl -H "X-API-Key: TU_API_KEY" "https://api.quienlotiene.app/v1/catalog?updated_since=2026-07-12T10:00:00"

data: {total, count, limit, offset, has_more, products:[{sku, name, standardized_title, brand, category, google_category, price, stock, availability, gtin, mpn, image, attributes, updated_at}]}

GET /v1/catalog/prices — la misma paginación, pero solo sku/price/stock/availability: para un polling frecuente y barato cuando no necesitás la ficha completa.

GET/v1/feed?format=acp|gmc|jsonld

El feed generado para tu tenant, listo para entregar a un agente/surface de compras.

curl -H "X-API-Key: TU_API_KEY" "https://api.quienlotiene.app/v1/feed?format=acp"
curl -H "X-API-Key: TU_API_KEY" "https://api.quienlotiene.app/v1/feed?format=gmc"
curl -H "X-API-Key: TU_API_KEY" "https://api.quienlotiene.app/v1/feed?format=jsonld"

data: acp{format, count, products, rejected}; gmc{format, feed(xml), rejected}; jsonld{format, feed(ItemList)}.

POST/v1/reserve

Crea una reserva (el flujo por defecto). Devuelve id de orden, estado y, si el comercio tiene pagos activos, un link de pago.

curl -X POST https://api.quienlotiene.app/v1/reserve \
  -H "X-API-Key: TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sku":"FIL-001","quantity":1}'

data: {order_id, status, total, currency, expires_note, payment_link?}

Listings — dónde está publicado cada producto

Llevá el estado de tus publicaciones por marketplace (Mercado Libre, Amazon, Tiendanube, el que sea — es texto libre). Consultá antes de publicar para no duplicar, y reportá después de publicar para llevar el estado.

GET/v1/products/{sku}/listings
curl -H "X-API-Key: TU_API_KEY" https://api.quienlotiene.app/v1/products/FIL-001/listings
PUT/v1/products/{sku}/listings/{marketplace}
curl -X PUT https://api.quienlotiene.app/v1/products/FIL-001/listings/mercadolibre \
  -H "X-API-Key: TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_id":"MLA123456789","external_url":"https://articulo.mercadolibre.com.ar/MLA-123","status":"active"}'
GET/v1/listings?marketplace=mercadolibre

Vista completa (opcionalmente filtrada) para un dashboard de sincronización propio.

Webhooks — push en vez de polling

¿Webhook o polling? Elegí según tu infraestructura. Un webhook necesita que vos tengas un servidor público, con HTTPS y siempre prendido, escuchando la llamada — es la contraparte de lo que a nosotros nos costó armar para probar WhatsApp (túnel + certificado). Si no tenés eso hoy, no hace falta: usá GET /v1/catalog/prices?updated_since= cada 1-2 minutos — mismo resultado, cero infraestructura de tu lado. El webhook queda para cuando corras un servidor propio y quieras latencia instantánea.

Suscribite a cambios de stock y precio en tiempo real: en vez de preguntar cada X minutos, te avisamos apenas algo cambia. Cada entrega es un POST firmado con HMAC-SHA256 (header X-Webhook-Signature, calculada con el secret que te damos al crear el webhook — verificalo en tu endpoint antes de confiar en el payload).

POST/v1/webhooks
curl -X POST https://api.quienlotiene.app/v1/webhooks \
  -H "X-API-Key: TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://tu-servidor.com/hook","events":["stock_changed","price_changed"]}'

data: {id, url, events, secret} — el secret se muestra UNA sola vez, guardalo.

GET/v1/webhooks · POST/v1/webhooks/{id}/test · DELETE/v1/webhooks/{id}

Listá tus webhooks, mandate un evento de prueba para verificar tu endpoint, o dá de baja uno. El payload de ejemplo: {"event":"stock_changed","sku":"FIL-001","name":"...","price":18900.0,"stock":2,"ts":"..."}.

GET/v1/health

Salud del catálogo (0-100 por completitud de campos) y frescura del último sync.

curl -H "X-API-Key: TU_API_KEY" https://api.quienlotiene.app/v1/health

data: {health_score, freshness, incomplete_count, duplicate_count}

Errores

CódigoCuándo
400Entrada inválida (p. ej. format desconocido).
401Falta la API key o es inválida/revocada.
404El recurso no existe en tu tenant.
409Conflicto de negocio (sin stock, cantidad mínima, etc.).
422Validación: el cuerpo no cumple el schema (detalle por campo).
429Rate limit: por IP (global) o por tu clave (120 req/min por defecto — no se factura la llamada frenada).

Sandbox — probala en 3 pasos

1. Registrate en el portal y creá tu comercio.   2. Copiá tu API key desde el panel.   3. Corré cualquier curl de esta página contra https://api.quienlotiene.app — empezá con GET /v1/health, después subí tu catálogo con POST /v1/catalog/sync y buscá con POST /v1/search.

El schema completo y ejecutable está en /docs (OpenAPI).