Conteos de inventario

Un conteo (InventoryCount) registra el proceso de contar físicamente el stock de una ubicación — completo, parcial o cíclico — y aplica la varianza encontrada como ajustes de inventario al completarse. Todos los endpoints de este recurso requieren el permiso inventory:count.

El stock solo se toca al completar, y solo si hubo varianza registrada

Crear, iniciar o cancelar un conteo no mueve stock. El movimiento ocurre exclusivamente en complete, y únicamente para los ítems cuya varianza fue calculada mediante una llamada previa a PUT .../items. Si completas un conteo sin haber registrado cantidades contadas, no se genera ningún ajuste.

Listar conteos

Lista los conteos del tenant, con filtros opcionales

pagenumber

Página, 1-indexada. Default: 1.

limitnumber

Elementos por página. Default: 20.

statusstring

Filtro por estado: draft, in_progress, completed, cancelled.

locationIdstring

Filtro por ubicación.

countTypestring

Filtro por tipo: full, partial, cycle.

200
{
  "counts": [
    { "_id": "671b2c3d4e5f6a7b8c9d0e1f", "name": "Conteo cíclico julio", "locationId": "loc_abc123", "countType": "cycle", "status": "draft" }
  ],
  "pagination": { "page": 1, "limit": 20, "total": 4, "pages": 1 }
}

Consultar un conteo

Consulta un conteo por ID

idstringrequired

ID del conteo.

200
{ "_id": "671b2c3d4e5f6a7b8c9d0e1f", "name": "Conteo cíclico julio", "status": "in_progress" }
404
{ "code": "not-found" }

Reporte de varianza

Detalle de varianza por ítem para un conteo

idstringrequired

ID del conteo.

200
{
  "count": { "_id": "671b2c3d4e5f6a7b8c9d0e1f", "status": "in_progress" },
  "totalItemsCounted": 30,
  "itemsWithVariance": 4,
  "totalVariance": -7,
  "positiveVarianceCount": 1,
  "negativeVarianceCount": 3,
  "items": [
    { "sku": "CAM-ROJO-M", "systemQuantity": 42, "countedQuantity": 40, "variance": -2 }
  ]
}
404
{ "code": "not-found" }

Crear un conteo

Crea un conteo en estado 'draft'

namestringrequired

Nombre descriptivo del conteo.

locationIdstringrequired

Ubicación a contar.

countTypestringrequired

full | partial | cycle.

descriptionstring

Descripción libre.

countItemsarray

Ítems iniciales a contar. Default: [].

includeZeroStockboolean

Incluir SKUs con stock cero.

categoryFilterstring

Filtro por categoría de producto.

skuPatternstring

Filtro por patrón de SKU.

{ "name": "Conteo cíclico julio", "locationId": "loc_abc123", "countType": "cycle" }
201
{ "_id": "671b2c3d4e5f6a7b8c9d0e1f", "name": "Conteo cíclico julio", "locationId": "loc_abc123", "countType": "cycle", "status": "draft", "countItems": [] }
400
{ "code": "bad-request/missing-name" }

Permiso requerido: inventory:count

Registrar cantidades contadas

Registra las cantidades contadas y calcula la varianza por ítem

idstringrequired

ID del conteo.

countItemsarrayrequired

Lista de { sku, systemQuantity, countedQuantity?, ... }.

{
  "countItems": [
    { "sku": "CAM-ROJO-M", "systemQuantity": 42, "countedQuantity": 40 }
  ]
}
200
{
  "_id": "671b2c3d4e5f6a7b8c9d0e1f",
  "countItems": [
    { "sku": "CAM-ROJO-M", "systemQuantity": 42, "countedQuantity": 40, "variance": -2 }
  ]
}
400
{ "code": "bad-request/invalid-items" }

Permiso requerido: inventory:count

La variance (countedQuantity − systemQuantity) se calcula en el servidor por cada ítem. Un ítem sin countedQuantity queda con variance: undefined — y por lo tanto no genera ajuste cuando el conteo se completa.

Tip

Puedes llamar este endpoint varias veces conforme avanza el conteo físico; cada llamada recalcula la varianza de los ítems incluidos en esa petición.

Iniciar

Marca el conteo como en progreso

idstringrequired

ID del conteo.

No requiere cuerpo — el handler no lee event.body en absoluto.

{}
200
{ "_id": "671b2c3d4e5f6a7b8c9d0e1f", "status": "in_progress", "startedAt": "2026-07-01T09:00:00.000Z" }
404
{ "code": "not-found" }

Completar (mueve el stock)

Cierra el conteo y crea ajustes automáticos para los ítems con varianza

idstringrequired

ID del conteo.

No requiere cuerpo — el handler no lee event.body en absoluto.

{}
200
{ "_id": "671b2c3d4e5f6a7b8c9d0e1f", "status": "completed" }
404
{ "code": "not-found" }

Permiso requerido: inventory:count

Por cada ítem del conteo cuya variance sea distinta de 0 y distinta de undefined, el sistema:

  1. Crea automáticamente un InventoryAdjustment (reason: 'count_correction', status: 'approved', sourceType: 'count', sourceId = ID del conteo).
  2. Escribe el stock directamente, en la misma operación.

'complete' NO emite el evento 'Inventory Updated'

Igual que la recepción de transferencias, complete mueve el stock por una ruta que bypasea la escritura estándar de stock — por lo tanto no dispara Inventory Updated ni la verificación de stock bajo, a pesar de que internamente sí crea registros de InventoryAdjustment. Un consumidor que solo escucha Inventory Updated no se enterará de los cambios de stock producidos por un conteo completado.

Sin guarda de transición de estado

start, complete y cancel no verifican el estado actual antes de aplicarse — igual que en transferencias, es un findOneAndUpdate incondicional. Completar un conteo dos veces vuelve a evaluar la varianza de sus countItems y puede generar ajustes duplicados si no controlas el estado desde tu integración.

Cancelar

Marca el conteo como cancelado

idstringrequired

ID del conteo.

cancellationReasonstring

Motivo (o el campo alterno `reason`). Default: 'Cancelled by user'.

{ "cancellationReason": "Conteo iniciado por error" }
200
{ "_id": "671b2c3d4e5f6a7b8c9d0e1f", "status": "cancelled" }
404
{ "code": "not-found" }

Ejemplo — ciclo completo

# 1. Crear
curl -X POST 'https://api.fenicia.io/inventory/counts' \
  -H 'Authorization: Bearer fkapi_tu_api_key' \
  -H 'Content-Type: application/json' \
  -d '{"name": "Conteo cíclico julio", "locationId": "loc_abc123", "countType": "cycle"}'
 
# 2. Registrar cantidades contadas
curl -X PUT 'https://api.fenicia.io/inventory/counts/671b2c3d4e5f6a7b8c9d0e1f/items' \
  -H 'Authorization: Bearer fkapi_tu_api_key' \
  -H 'Content-Type: application/json' \
  -d '{"countItems": [{"sku": "CAM-ROJO-M", "systemQuantity": 42, "countedQuantity": 40}]}'
 
# 3. Completar (aplica la varianza como ajuste)
curl -X POST 'https://api.fenicia.io/inventory/counts/671b2c3d4e5f6a7b8c9d0e1f/complete' \
  -H 'Authorization: Bearer fkapi_tu_api_key'

Errores

CódigoStatusDescripción
bad-request/missing-tenant401No se pudo resolver el tenant de la API key.
bad-request/missing-name400Falta name al crear.
bad-request/missing-location400Falta locationId al crear.
bad-request/missing-type400Falta countType al crear.
bad-request/invalid-items400countItems mal formado al registrar cantidades.
not-found404No existe un conteo con ese ID.
internal-error500Error interno.

Siguientes pasos