Las Ubicaciones viven en https://api.fenicia.io/locations/* — un base path y un servicio distintos de /inventory/*. Tienen su propio namespace de permisos (locations:*), su propia convención de paginación y su propia forma de respuesta. No asumas que las reglas documentadas para /inventory/* aplican aquí.
Una Ubicación (Location) es un almacén, tienda física, centro de fulfillment de un marketplace (FBA, Mercado Full) u otro punto donde se guarda o gestiona stock. Un Place es una zona dentro de una ubicación — un anaquel, una zona de recepción, una zona de dañados — que a su vez puede desglosarse en placements (pasillo, isla, cabecera, bin, rack, etc.), la posición física exacta dentro de esa zona.
shopify-fullfillment (con doble "ll") es el valor literal del enum en producción — no es un error de esta documentación. No lo "corrijas" a shopify-fulfillment en tu integración; el valor exacto es el que ves aquí.
Valores de capabilities:pos, pick-up, fulfillment, inventory, one-way-sync, two-way-sync.
id, code, type (enum, ver abajo), name, description?, active (default true),maxCapacity?, pickPriority?, availableForSale?,placements?: [{ code, type (enum, ver abajo), label? }]
Valores de type (zona):on-shelf, backstock, receiving, returns, damaged, mezzanine, showcase, cold-storage, custom.
Valores de type (placement, posición dentro de la zona):aisle, island, endcap, shelf, bin, rack, bay, pallet, display, counter, custom.
GET /locations pagina 0-indexado con limit por defecto 10 (no 20). Su respuesta es { locations, totalCount, page, limit } — nota totalCount, no total como en el resto del dominio de inventario.
Este endpoint devuelve 400 (no 404) con code: "bad-request/not-found" cuando el servicio no puede resolver el conteo. Es una combinación código/status inusual — documentada tal cual se comporta hoy, no "corregida".
Obtiene una ubicación por ID o por locationCode (lookup unificado). Requiere locations:read.
idstringrequired
ID de MongoDB o locationCode — ambos se resuelven en el mismo path param.
200
{ "location": { "id": "loc_cedis_cdmx", "name": "CEDIS Ciudad de México", "type": "warehouse" } }
404
{ "code": "not-found", "message": "Location not found" }
Único endpoint del dominio que usa code:'not-found' en un 404
Dentro de lambda-locations, soloGET /locations/{id} usa el código literal not-found en un 404. Todos los demás 404 de este dominio (ver tabla más abajo) usan bad-request/not-found — un código con prefijo bad-request/ sobre un status 404. Documentado literal, no es un typo de esta guía.
capabilitiesno se valida contra el catálogo al crear ni al actualizar — solo type se verifica contra su enum. Un valor de capabilities que no exista en el catálogo se acepta en silencio. (Observación de código: no se confirmó con una prueba negativa independiente; es la ausencia de una verificación de catálogo para capabilities en el controlador, análoga a la que sí existe para type.)
{ "code": "bad-request/system-location", "message": "Cannot remove default flag from a system location" }
Escritura en dos pasos, sin transacción
Internamente, marcar una ubicación como predeterminada primero limpia isDefault en todas las demás ubicaciones del tenant (updateMany) y luego marca la ubicación objetivo — son dos escrituras separadas, sin una sesión/transacción de Mongo que las envuelva. En teoría, una falla entre ambos pasos podría dejar al tenant sin ninguna ubicación predeterminada. Esta es una observación de la forma del código, no un incidente confirmado en producción.
{ "code": "bad-request/system-location", "message": "Cannot delete a system location" }
Sin chequeo de integridad referencial
Eliminar una ubicación no verifica si todavía existen registros de Inventory que la referencian como locationId. Es posible dejar registros de inventario huérfanos apuntando a una ubicación eliminada.
El id de la zona lo genera el servidor (UUID). La unicidad de code dentro de una ubicación se verifica en memoria al momento de crear, no con un índice único de base de datos.