Skip to content

Inventario

Los endpoints de inventario te permiten ajustar el stock de tus bodegas, mover existencias entre ellas y consultar el kardex (movimientos históricos de cada variante de producto).

La URL base de producción es https://api-pos.zelta.dev/public/v1 y todas las rutas se expresan relativas a ella. Todas las peticiones deben hacerse sobre HTTPS e incluir tu API key. Consulta para los detalles.

INFO

En los ítems de ajustes y transferencias, los productos se direccionan únicamente por referenceId (tu identificador externo). No se aceptan id interno, SKU ni código de barras. Asegúrate de haber asignado un referenceId a cada variante desde tu integración.

Ajustes de inventario

Un ajuste registra entradas (in) o salidas (out) de stock en una bodega. Úsalo para correcciones de conteo físico, mermas, mercancía dañada o ingresos manuales que no provienen de una compra.

WARNING

El cuerpo de la petición usa los valores in y out en cada ítem, pero la respuesta devuelve incoming y outgoing respectivamente. Téngalo en cuenta al mapear los datos.

Crear un ajuste

http
POST /inventory-adjustments
CampoTipoRequeridoDescripción
warehouseIdstring (cuid2)NoBodega a ajustar. Por defecto, la bodega de la sucursal asociada a la API key.
reasonstring (≤255)NoMotivo del ajuste.
itemsarrayMínimo un ítem.
items[].referenceIdstringIdentificador externo de la variante.
items[].typestringin (entrada) u out (salida).
items[].quantitynumber (>0)Cantidad a ajustar.
items[].notesstring (≤500)NoNota por línea.
bash
curl -X POST "https://api-pos.zelta.dev/public/v1/inventory-adjustments" \
  -H "Authorization: Bearer zpk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Ajuste por conteo físico de enero",
    "items": [
      { "referenceId": "SKU-1001", "type": "in", "quantity": 12, "notes": "Diferencia de inventario" },
      { "referenceId": "SKU-2050", "type": "out", "quantity": 3 }
    ]
  }'

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/inventory-adjustments', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    reason: 'Ajuste por conteo físico de enero',
    items: [
      { referenceId: 'SKU-1001', type: 'in', quantity: 12, notes: 'Diferencia de inventario' },
      { referenceId: 'SKU-2050', type: 'out', quantity: 3 }
    ]
  })
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.post(
    'https://api-pos.zelta.dev/public/v1/inventory-adjustments',
    headers={'Authorization': 'Bearer zpk_live_xxx', 'Content-Type': 'application/json'},
    json={
        'reason': 'Ajuste por conteo físico de enero',
        'items': [
            { 'referenceId': 'SKU-1001', 'type': 'in', 'quantity': 12, 'notes': 'Diferencia de inventario' },
            { 'referenceId': 'SKU-2050', 'type': 'out', 'quantity': 3 }
        ]
    }
)
data = res.json()

Respuesta 201 Created:

json
{
  "id": "kx7p2m9q3v8r1n6t4w0y5z2a",
  "number": "ADJ-000142",
  "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
  "status": "applied",
  "reason": "Ajuste por conteo físico de enero",
  "notes": null,
  "items": [
    {
      "productVariantId": "pv9z2x4c6v8b1n3m5k7j9h2g",
      "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
      "quantity": 12,
      "type": "incoming",
      "notes": "Diferencia de inventario"
    },
    {
      "productVariantId": "pv1a3s5d7f9g2h4j6k8l0z2x",
      "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
      "quantity": 3,
      "type": "outgoing",
      "notes": null
    }
  ],
  "appliedAt": "2026-01-31T18:24:00.000Z",
  "createdAt": "2026-01-31T18:24:00.000Z",
  "updatedAt": "2026-01-31T18:24:00.000Z"
}

El campo status puede ser draft, applied o voided.

Problemas comunes

CódigoHTTPCausa
validation_error400Falta referenceId, type inválido o quantity ≤ 0.
unauthorized401API key ausente o inválida.
not_found404El referenceId o la warehouseId no existen.
insufficient_stock409Una salida (out) deja la existencia por debajo de cero.

Listar ajustes

http
GET /inventory-adjustments

Acepta los parámetros de : start, limit, updatedSince, from, to y metadata.

bash
curl "https://api-pos.zelta.dev/public/v1/inventory-adjustments?limit=30&metadata=true" \
  -H "Authorization: Bearer zpk_live_xxx"

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/inventory-adjustments?limit=30&metadata=true', {
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}` }
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.get(
    'https://api-pos.zelta.dev/public/v1/inventory-adjustments',
    headers={'Authorization': 'Bearer zpk_live_xxx'},
    params={'limit': 30, 'metadata': 'true'}
)
data = res.json()

Respuesta 200 OK:

json
{
  "data": [
    {
      "id": "kx7p2m9q3v8r1n6t4w0y5z2a",
      "number": "ADJ-000142",
      "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
      "status": "applied",
      "reason": "Ajuste por conteo físico de enero",
      "notes": null,
      "appliedAt": "2026-01-31T18:24:00.000Z",
      "createdAt": "2026-01-31T18:24:00.000Z",
      "updatedAt": "2026-01-31T18:24:00.000Z"
    }
  ],
  "metadata": { "total": 142 }
}

Obtener un ajuste

http
GET /inventory-adjustments/{id}
CampoTipoRequeridoDescripción
idstring (cuid2)Identificador del ajuste.

Devuelve el objeto del ajuste directamente (sin envoltorio), con la misma estructura que la respuesta de creación. Si no existe, responde 404 not_found.

Transferencias entre bodegas

Una transferencia mueve stock de una bodega a otra. En Zelta POS la transferencia se envía y se recibe de inmediato, por lo que el stock se descuenta del origen y se acredita en el destino en la misma operación.

Crear una transferencia

http
POST /warehouse-transfers
CampoTipoRequeridoDescripción
fromWarehouseIdstring (cuid2)Bodega de origen.
toWarehouseIdstring (cuid2)Bodega de destino.
notesstring (≤500)NoNota general de la transferencia.
itemsarrayMínimo un ítem.
items[].referenceIdstringIdentificador externo de la variante.
items[].quantitynumber (>0)Cantidad a transferir.
items[].notesstringNoNota por línea.
bash
curl -X POST "https://api-pos.zelta.dev/public/v1/warehouse-transfers" \
  -H "Authorization: Bearer zpk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "fromWarehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
    "toWarehouseId": "wh5d2f8g1h4j7k0l3z6x9c2v",
    "notes": "Reabastecimiento sucursal centro",
    "items": [
      { "referenceId": "SKU-1001", "quantity": 6 }
    ]
  }'

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/warehouse-transfers', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fromWarehouseId: 'wh3b8n5k2j7h9g4f1d6s0a8q',
    toWarehouseId: 'wh5d2f8g1h4j7k0l3z6x9c2v',
    notes: 'Reabastecimiento sucursal centro',
    items: [
      { referenceId: 'SKU-1001', quantity: 6 }
    ]
  })
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.post(
    'https://api-pos.zelta.dev/public/v1/warehouse-transfers',
    headers={'Authorization': 'Bearer zpk_live_xxx', 'Content-Type': 'application/json'},
    json={
        'fromWarehouseId': 'wh3b8n5k2j7h9g4f1d6s0a8q',
        'toWarehouseId': 'wh5d2f8g1h4j7k0l3z6x9c2v',
        'notes': 'Reabastecimiento sucursal centro',
        'items': [
            { 'referenceId': 'SKU-1001', 'quantity': 6 }
        ]
    }
)
data = res.json()

Respuesta 201 Created:

json
{
  "id": "tr8h3k6m9p2q5v8r1n4t7w0y",
  "number": "TRF-000087",
  "fromWarehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
  "toWarehouseId": "wh5d2f8g1h4j7k0l3z6x9c2v",
  "status": "received",
  "notes": "Reabastecimiento sucursal centro",
  "items": [
    {
      "productVariantId": "pv9z2x4c6v8b1n3m5k7j9h2g",
      "quantity": 6,
      "notes": null
    }
  ],
  "createdAt": "2026-01-31T19:02:00.000Z",
  "updatedAt": "2026-01-31T19:02:00.000Z"
}

El campo status puede ser draft, sent, received o cancelled.

Problemas comunes

CódigoHTTPCausa
validation_error400Falta fromWarehouseId, toWarehouseId, referenceId o quantity ≤ 0.
unauthorized401API key ausente o inválida.
not_found404Una bodega o referenceId no existe.
insufficient_stock409La bodega de origen no tiene existencias suficientes.

Listar transferencias

http
GET /warehouse-transfers

Acepta los parámetros de . Devuelve { "data": [...] } y, con ?metadata=true, agrega { "metadata": { "total": N } }.

Obtener una transferencia

http
GET /warehouse-transfers/{id}
CampoTipoRequeridoDescripción
idstring (cuid2)Identificador de la transferencia.

Devuelve el objeto de la transferencia directamente. Si no existe, responde 404 not_found.

Kardex (stock ledger)

El kardex es un registro de solo lectura de todos los movimientos de existencias. Cada entrada refleja el saldo antes y después del movimiento y su origen (compra, venta, ajuste o transferencia).

Consultar el kardex

http
GET /stock-ledger

Acepta los parámetros de : start, limit, updatedSince, from, to y metadata.

bash
curl "https://api-pos.zelta.dev/public/v1/stock-ledger?from=2026-01-01&to=2026-01-31" \
  -H "Authorization: Bearer zpk_live_xxx"

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/stock-ledger?from=2026-01-01&to=2026-01-31', {
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}` }
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.get(
    'https://api-pos.zelta.dev/public/v1/stock-ledger',
    headers={'Authorization': 'Bearer zpk_live_xxx'},
    params={'from': '2026-01-01', 'to': '2026-01-31'}
)
data = res.json()

Respuesta 200 OK:

json
{
  "data": [
    {
      "id": "le2k5m8p1q4v7r0n3t6w9y2z",
      "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
      "productVariantStockId": "ps4f7g0h3j6k9l2z5x8c1v4b",
      "type": "incoming",
      "origin": "adjustment",
      "originId": "kx7p2m9q3v8r1n6t4w0y5z2a",
      "previousQty": 40,
      "qty": 12,
      "newQty": 52,
      "reason": "Diferencia de inventario",
      "createdAt": "2026-01-31T18:24:00.000Z"
    }
  ]
}

Para cada entrada, type es incoming u outgoing, y origin puede ser purchase, sale, adjustment, transfer o null. Los campos productVariantStockId, origin, originId y reason pueden ser null.

Siguientes pasos

  • — registra entradas de stock desde facturas de proveedor.
  • — consulta existencias por variante.
  • — descubre las bodegas y sucursales disponibles.
  • — paginación, sincronización y códigos de error.

Documentación oficial de Zelta