Productos y stock
El recurso Productos y stock te permite consultar el catálogo de variantes de producto y gestionar las existencias por bodega.
Todas las rutas son relativas a la URL base de producción:
https://api-pos.zelta.dev/public/v1INFO
Los productos se crean y editan desde el dashboard de Zelta POS. La API pública gestiona la consulta del catálogo y la gestión de stock; no crea ni elimina productos.
Direccionamiento de ítems
Los ítems se referencian por id (cuid2 interno, tiene precedencia) o por referenceId (la referencia externa que maneja tu integración, máx. 120 caracteres). El SKU o el código de barras no se aceptan por API.
Listar el catálogo
GET /itemsDevuelve la lista de variantes en un envoltorio { "data": [ ... ] }. Soporta los parámetros de paginación y sincronización incremental (start, limit, updatedSince, from/to, metadata, ver ) y, además:
| Parámetro | Tipo | Descripción |
|---|---|---|
referenceId | string | Busca un ítem específico por su referencia externa. |
fields | string | Con fields=inventory incluye el stock por bodega en cada ítem. |
curl "https://api-pos.zelta.dev/public/v1/items?fields=inventory&limit=30" \
-H "Authorization: Bearer zpk_live_xxx"Ejemplo JS
const res = await fetch('https://api-pos.zelta.dev/public/v1/items?fields=inventory&limit=30', {
headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}` }
});
const data = await res.json();Ejemplo Py
import requests
res = requests.get(
'https://api-pos.zelta.dev/public/v1/items',
headers={'Authorization': 'Bearer zpk_live_xxx'},
params={'fields': 'inventory', 'limit': 30}
)
data = res.json()Respuesta
{
"data": [
{
"id": "itm_9k8j7h6g5f4d3s2a",
"referenceId": "SKU-CAFE-500",
"name": "Café tostado 500 g",
"price": "5.00",
"inventory": {
"warehouses": [
{ "warehouseId": "wh_1a2b3c4d5e6f7g8h", "availableQty": "120", "stockedQty": "130" }
]
}
}
]
}| Campo | Tipo | Descripción |
|---|---|---|
id | string | ID de la variante de producto. |
referenceId | string | null | Referencia externa del integrador. |
name | string | Nombre de la variante. |
price | string | null | Precio de catálogo. |
inventory | object | Solo con fields=inventory. Contiene warehouses[]. |
El objeto inventory.warehouses[] incluye, por bodega, warehouseId, availableQty (disponible) y stockedQty (en existencia).
Consultar stock de un ítem
GET /items/{ref}/stockDevuelve el detalle de stock de un ítem. El parámetro {ref} admite tanto el id como el referenceId. Responde 404 si el ítem no existe. Acepta el query opcional warehouseId para filtrar por una bodega.
curl "https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock?warehouseId=wh_1a2b3c4d5e6f7g8h" \
-H "Authorization: Bearer zpk_live_xxx"Ejemplo JS
const res = await fetch('https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock?warehouseId=wh_1a2b3c4d5e6f7g8h', {
headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}` }
});
const data = await res.json();Ejemplo Py
import requests
res = requests.get(
'https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock',
headers={'Authorization': 'Bearer zpk_live_xxx'},
params={'warehouseId': 'wh_1a2b3c4d5e6f7g8h'}
)
data = res.json()Respuesta
{
"referenceId": "SKU-CAFE-500",
"productVariantId": "itm_9k8j7h6g5f4d3s2a",
"warehouseId": "wh_1a2b3c4d5e6f7g8h",
"stockedQty": "130",
"reservedQty": "10",
"availableQty": "120",
"minQty": "20"
}| Campo | Tipo | Descripción |
|---|---|---|
referenceId | string | null | Referencia externa del integrador. |
productVariantId | string | ID de la variante de producto. |
warehouseId | string | Bodega consultada. |
stockedQty | string | Cantidad en existencia. |
reservedQty | string | Cantidad reservada. |
availableQty | string | Cantidad disponible (existencia menos reservas). |
minQty | string | Cantidad mínima configurada. |
Fijar el stock de un ítem
PUT /items/{ref}/stockFija el stock absoluto del ítem en la bodega indicada. El parámetro {ref} admite id o referenceId. Responde 404 si el ítem no existe.
Campos del cuerpo
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
warehouseId | string (cuid2) | No | Bodega donde se fija el stock. |
quantity | number | Sí | Cantidad absoluta objetivo. Debe ser ≥ 0. |
TIP
Este endpoint fija una cantidad absoluta: internamente crea un ajuste de balance para que la existencia llegue exactamente a la cantidad enviada. No es un incremento ni un decremento.
curl -X PUT "https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock" \
-H "Authorization: Bearer zpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"warehouseId": "wh_1a2b3c4d5e6f7g8h",
"quantity": 150
}'Ejemplo JS
const res = await fetch('https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
warehouseId: 'wh_1a2b3c4d5e6f7g8h',
quantity: 150
})
});
const data = await res.json();Ejemplo Py
import requests
res = requests.put(
'https://api-pos.zelta.dev/public/v1/items/SKU-CAFE-500/stock',
headers={'Authorization': 'Bearer zpk_live_xxx', 'Content-Type': 'application/json'},
json={
'warehouseId': 'wh_1a2b3c4d5e6f7g8h',
'quantity': 150
}
)
data = res.json()Respuesta
{
"referenceId": "SKU-CAFE-500",
"productVariantId": "itm_9k8j7h6g5f4d3s2a",
"warehouseId": "wh_1a2b3c4d5e6f7g8h",
"stockedQty": "150",
"reservedQty": "10",
"availableQty": "140",
"minQty": "20"
}Problemas comunes
| Código | HTTP | Causa probable |
|---|---|---|
validation_error | 400 | Falta quantity, es negativa, o el warehouseId no es válido. |
unauthorized | 401 | API key ausente o inválida. |
forbidden | 403 | La key no tiene acceso al recurso solicitado. |
not_found | 404 | El {ref} del ítem o el warehouseId no existen. |
rate_limited | 429 | Se superó el límite de peticiones. |
internal_error | 500 | Error interno del servidor. |
Siguientes pasos
- — descubre los
idde tus bodegas. - — registra ventas que descuentan stock.
- — paginación y sincronización incremental.