Catálogo e inventario por API

Los endpoints para leer y escribir el stock, los proveedores, las bodegas, los conteos y los traslados, y para leer el semáforo y el trabajo del día.

En esta página
  1. Stock por SKU
  2. Importar el stock desde un archivo
  3. El semáforo y el trabajo del día
  4. Proveedores
  5. Bodegas
  6. Conteos físicos
  7. Traslados entre bodegas
  8. Otros recursos del inventario

Todas estas rutas están bajo /inventory. Las lecturas funcionan con una llave de lectura; las escrituras necesitan una de escritura. Si la llave está limitada a algunas bodegas, solo ve y toca esas bodegas.

Stock por SKU

Método y rutaQué haceLlave
GET /inventory/stock/pageLista paginada del stock. Parámetros: limit, offset, q (búsqueda), warehouse.lectura
GET /inventory/stockTodo el stock de una vez (sin paginar).lectura
GET /inventory/stock/lookupBusca registros de stock.lectura
GET /inventory/stock/{sku}Un registro.lectura
GET /inventory/stock/{sku}/historyLa historia del stock de un SKU.lectura
PUT /inventory/stock/{sku}Crea o reemplaza el registro. current_stock es obligatorio.escritura
PATCH /inventory/stock/{sku}Cambia algunos campos de un registro que ya existe. Nunca crea uno.escritura
DELETE /inventory/stock/{sku}Borra el registro de stock.escritura
PATCH /inventory/stock/{sku}/product-typeCambia el tipo de producto (terminado, componente…).escritura
GET / PUT / DELETE /inventory/stock/{sku}/suppliers[/{supplier_id}]Los proveedores vinculados a un SKU.lectura / escritura
curl "https://app.stockai.es/api/v1/inventory/stock/page?limit=50&offset=0&warehouse=principal&q=SKU-0" \
  -H "Authorization: Bearer $STOCKAI_KEY"
# Create or replace a SKU's record (current_stock is required)
curl -X PUT https://app.stockai.es/api/v1/inventory/stock/SKU-001 \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"current_stock":120,"min_stock":20,"lead_time_days":7,"unit_cost":2.5,
       "moq":12,"supplier":"Distribuidora Andina","warehouse":"principal"}'

# Change one field of a record that already exists (never creates one)
curl -X PATCH https://app.stockai.es/api/v1/inventory/stock/SKU-001 \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"current_stock":118}'

Campos que acepta PUT/PATCH: display_name, current_stock, min_stock, lead_time_days, unit_cost, moq, supplier, notes, sale_price, category, family, brand, unit_of_measure, barcode, warehouse. La respuesta es el registro completo:

{
  "sku": "SKU-001", "display_name": "SKU-001", "warehouse": "principal",
  "current_stock": 120.0, "min_stock": 0.0, "lead_time_days": 7,
  "unit_cost": 2.5, "moq": 12.0, "supplier": "Distribuidora Andina",
  "product_type": "finished_good", "service_level": 0.95,
  "lead_time_set_by": "user", "unit_cost_set_by": "user", "moq_set_by": "user",
  "updated_at": "2026-10-01T08:00:00+00:00"
}

Los campos *_set_by dicen quién fijó cada valor (user, file, supplier_rule…). Lo que escribes por la API cuenta como dato tuyo.

Importar el stock desde un archivo

# 1. Preview: what was detected and what would be written. Writes nothing.
curl -X POST https://app.stockai.es/api/v1/inventory/bulk/preview \
  -H "Authorization: Bearer $STOCKAI_KEY" -F "file=@stock.csv"

# 2. Import. Optional fields: mapping (JSON text), warehouse, thousands_dot, only_fill_missing
curl -X POST https://app.stockai.es/api/v1/inventory/bulk \
  -H "Authorization: Bearer $STOCKAI_KEY" -F "file=@stock.csv" -F "warehouse=principal"

/inventory/bulk/preview no toca ninguna fila: te dice qué columnas detectó (detected_mapping), qué columnas no usó y qué escribiría. Si un perfil de sincronización es dueño de alguno de esos campos, lo avisa en synced_overwrites. GET /inventory/template.csv descarga la plantilla con los encabezados que se reconocen.

El semáforo y el trabajo del día

GET /inventory/status
El semáforo por SKU: señal, cobertura, punto de reorden y cantidad recomendada. Parámetros opcionales: session_id (sin él, la sesión activa), signal, supplier, abc, by_warehouse, q, skus, without_forecast, service_level, sort, order, limit, offset.
GET /inventory/morning-briefing
El trabajo del día: riesgos, recomendaciones con su motivo, cambios de demanda e indicadores. Parámetros: session_id, service_level.
GET /inventory/dashboard-summary
Los números del panel.
GET /inventory/optimize
Compras y traslados sugeridos por el optimizador, por SKU y bodega (session_id, horizon_days).
GET /inventory/setup-gaps
SKUs a los que les falta configuración (costo, tiempo de entrega…).
GET /inventory/dead-capital, /margin-erosion, /supplier-cost-inflation, /forecast-money
Capital inmovilizado, margen que se erosiona, inflación de costos y proyección de ingresos, costo y margen.
curl "https://app.stockai.es/api/v1/inventory/status?signal=PEDIR_YA&supplier=Andina" \
  -H "Authorization: Bearer $STOCKAI_KEY"
{
  "period": "daily", "coverage_unit": "day",
  "items": [{
    "sku": "SKU-002", "signal": "PEDIR_YA",
    "current_stock": 42.0, "reorder_point": 5919.28, "recommended_qty": 5878.0,
    "coverage_days": 0.1,
    "lead_time_days": 7, "lead_time_source": "user",
    "unit_cost": 5.2,    "unit_cost_source": "user",
    "moq": 25.0,         "moq_source": "user",
    "supplier": "Granos del Valle",
    "explanation_code": "inventory_explain_reorder",
    "explanation_params": { "signal": "PEDIR_YA", "daily_demand": 757.97, "coverage_days": 0.1,
                            "current_stock": 42.0, "reorder_point": 5919.28,
                            "lead_time_days": 7, "lead_time_source": "user" },
    ...
  }]
}
signalSignificado
PEDIR_YAPide ya: el stock no cubre el tiempo de entrega.
PEDIR_PRONTOPide pronto.
OKCubierto.
SOBRESTOCKHay más de lo necesario.
SIN_DATOSNo hay stock registrado: no sabemos, que no es lo mismo que «está bien».

Los campos lead_time_source, unit_cost_source y moq_source dicen de dónde salió cada supuesto: user (lo escribiste), file (vino en tu archivo), supplier_rule (una regla de proveedor), learned (aprendido de tus recepciones; solo en tiempo de entrega) o default (StockAI lo supuso). Maneja los cinco. El porqué de cada recomendación viene estructurado en explanation_code + explanation_params: decide por eso, no por el texto explanation.

Proveedores

Método y rutaQué hace
GET /inventory/suppliers, GET /inventory/suppliers/pageLista (completa, o paginada con limit, offset, q).
POST /inventory/suppliersCrea un proveedor. Solo name es obligatorio.
PATCH /inventory/suppliers/{id}Cambia sus datos.
DELETE /inventory/suppliers/{id} / POST .../{id}/reactivateLo desactiva / lo reactiva (no se borra).
POST /inventory/suppliers/import/preview, POST /inventory/suppliers/importImportar desde un archivo (plantilla en GET /inventory/suppliers/import/template).
GET /inventory/suppliers/scorecard, /lead-time-alerts, /contact-healthCumplimiento, proveedores que tardan más de lo habitual y datos de contacto que faltan.
POST /inventory/suppliers/{id}/price-breaks, GET /inventory/price-breaksDescuentos por volumen.
curl -X POST https://app.stockai.es/api/v1/inventory/suppliers \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"name":"Distribuidora Andina","email":"ventas@andina.example",
       "lead_time_days":7,"payment_terms":"30 dias","payment_terms_days":30,
       "erp_code":"PRV-0042"}'

Campos: name, email, phone, whatsapp, lead_time_days, lead_time_std, review_period_days, payment_terms, payment_terms_days, notes y erp_code. El erp_code es el código del proveedor en tu ERP: es lo que el feed de órdenes usa para emparejar documentos.

Bodegas

  • GET /inventory/warehouses lista las bodegas (id, name, is_default…). POST crea una y PATCH /inventory/warehouses/{name} la cambia. El número de bodegas tiene un tope por plan.
  • GET / PUT / DELETE /inventory/warehouses/lanes: las rutas de traslado entre bodegas.

Conteos físicos

# Open a count for one warehouse
curl -X POST https://app.stockai.es/api/v1/inventory/stock-counts \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"warehouse":"principal","notes":"Monthly count"}'

# Record what was counted, line by line
curl -X PUT https://app.stockai.es/api/v1/inventory/stock-counts/$COUNT_ID/lines \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"sku":"SKU-001","quantity":117,"mode":"set"}'
# mode "add" (default) accumulates, e.g. one scan = one unit; "set" replaces the counted total.
# client_ref (optional): an id per scan, so a retried request is ignored.

# See the differences, then apply them to the stock
curl https://app.stockai.es/api/v1/inventory/stock-counts/$COUNT_ID/preview -H "Authorization: Bearer $STOCKAI_KEY"
curl -X POST https://app.stockai.es/api/v1/inventory/stock-counts/$COUNT_ID/apply -H "Authorization: Bearer $STOCKAI_KEY"

Un conteo se abre (POST), se llenan sus líneas (PUT .../lines, DELETE .../lines/{sku}), se revisa (GET .../preview) y se aplica (POST .../apply) o se cierra / cancela (.../close, .../cancel). Aplicar ajusta el stock a lo contado.

Traslados entre bodegas

curl -X POST https://app.stockai.es/api/v1/inventory/transfers \
  -H "Authorization: Bearer $STOCKAI_KEY" -H "Content-Type: application/json" \
  -d '{"from_warehouse":"principal","to_warehouse":"norte",
       "items":[{"sku":"SKU-001","qty":10}],"notes":"Weekly rebalancing"}'

Después: POST /inventory/transfers/{id}/receive cuando llega, .../close para cerrarlo y .../cancel para anularlo. GET /inventory/transfers los lista.

Otros recursos del inventario

Eventos de demanda
/inventory/events y su catálogo: temporadas y fechas que mueven la demanda, con sus multiplicadores.
Listas de materiales
/inventory/bom/{parent_sku}: componentes de un producto armado; GET /inventory/production-requirements explota la demanda en componentes.
Mermas
GET / POST /inventory/shrinkage y sus motivos.
Dinero
/inventory/cash-calendar, /inventory/roi, /inventory/roi/monthly.
Informe
GET /inventory/report/pdf descarga el informe de inventario en PDF.