Skip to content

Compras

Una compra (factura de proveedor o bill) registra la mercancía que ingresa de un proveedor. Al crearla, Zelta POS aumenta el stock de la bodega indicada y genera la cuenta por pagar correspondiente.

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 .

INFO

En los ítems de una compra, los productos se direccionan únicamente por referenceId (tu identificador externo). No se aceptan id interno, SKU ni código de barras.

Registrar una compra

http
POST /bills
CampoTipoRequeridoDescripción
providerIdstring (cuid2)NoProveedor asociado a la compra.
warehouseIdstring (cuid2)NoBodega donde ingresa el stock. Por defecto, la bodega de la sucursal de la API key.
datestring (ISO date)NoFecha de la compra.
dueDatestring (ISO date)NoFecha de vencimiento del pago.
notestring (≤1000)NoNota de la compra.
itemsarrayMínimo un ítem.
items[].referenceIdstringIdentificador externo de la variante.
items[].quantitynumber (>0)Cantidad comprada.
items[].pricenumber (≥0)Costo de compra unitario.

TIP

No se envía impuesto por línea: el ITBMS se calcula a partir de la tasa configurada en el catálogo de impuestos de cada producto.

bash
curl -X POST "https://api-pos.zelta.dev/public/v1/bills" \
  -H "Authorization: Bearer zpk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "providerId": "pr8h3k6m9p2q5v8r1n4t7w0y",
    "date": "2026-01-15",
    "dueDate": "2026-02-15",
    "note": "Pedido de reposición mensual",
    "items": [
      { "referenceId": "SKU-1001", "quantity": 24, "price": 8.50 },
      { "referenceId": "SKU-2050", "quantity": 10, "price": 15.00 }
    ]
  }'

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/bills', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    providerId: 'pr8h3k6m9p2q5v8r1n4t7w0y',
    date: '2026-01-15',
    dueDate: '2026-02-15',
    note: 'Pedido de reposición mensual',
    items: [
      { referenceId: 'SKU-1001', quantity: 24, price: 8.50 },
      { referenceId: 'SKU-2050', quantity: 10, price: 15.00 }
    ]
  })
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.post(
    'https://api-pos.zelta.dev/public/v1/bills',
    headers={'Authorization': 'Bearer zpk_live_xxx', 'Content-Type': 'application/json'},
    json={
        'providerId': 'pr8h3k6m9p2q5v8r1n4t7w0y',
        'date': '2026-01-15',
        'dueDate': '2026-02-15',
        'note': 'Pedido de reposición mensual',
        'items': [
            { 'referenceId': 'SKU-1001', 'quantity': 24, 'price': 8.50 },
            { 'referenceId': 'SKU-2050', 'quantity': 10, 'price': 15.00 }
        ]
    }
)
data = res.json()

Respuesta 201 Created:

json
{
  "id": "bl2k5m8p1q4v7r0n3t6w9y2z",
  "number": "BILL-000231",
  "providerId": "pr8h3k6m9p2q5v8r1n4t7w0y",
  "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
  "status": "completed",
  "paymentStatus": "unpaid",
  "subtotal": 354.00,
  "taxes": 24.78,
  "total": 378.78,
  "amountPaid": 0,
  "balance": 378.78,
  "note": "Pedido de reposición mensual",
  "date": "2026-01-15",
  "dueDate": "2026-02-15",
  "items": [
    {
      "productVariantId": "pv9z2x4c6v8b1n3m5k7j9h2g",
      "quantity": 24,
      "unitPrice": 8.50,
      "taxRate": 7,
      "total": 218.28
    },
    {
      "productVariantId": "pv1a3s5d7f9g2h4j6k8l0z2x",
      "quantity": 10,
      "unitPrice": 15.00,
      "taxRate": 7,
      "total": 160.50
    }
  ],
  "createdAt": "2026-01-15T14:10:00.000Z",
  "updatedAt": "2026-01-15T14:10:00.000Z"
}

El campo status puede ser draft, pending o completed. El paymentStatus puede ser unpaid, partial o paid. Los campos providerId, warehouseId, note, date y dueDate pueden ser null.

Problemas comunes

CódigoHTTPCausa
validation_error400Falta referenceId, quantity ≤ 0 o price negativo.
unauthorized401API key ausente o inválida.
not_found404El providerId, la warehouseId o un referenceId no existen.

Listar compras

http
GET /bills

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

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

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/bills?from=2026-01-01&to=2026-01-31&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/bills',
    headers={'Authorization': 'Bearer zpk_live_xxx'},
    params={'from': '2026-01-01', 'to': '2026-01-31', 'metadata': 'true'}
)
data = res.json()

Respuesta 200 OK:

json
{
  "data": [
    {
      "id": "bl2k5m8p1q4v7r0n3t6w9y2z",
      "number": "BILL-000231",
      "providerId": "pr8h3k6m9p2q5v8r1n4t7w0y",
      "warehouseId": "wh3b8n5k2j7h9g4f1d6s0a8q",
      "status": "completed",
      "paymentStatus": "unpaid",
      "subtotal": 354.00,
      "taxes": 24.78,
      "total": 378.78,
      "amountPaid": 0,
      "balance": 378.78,
      "date": "2026-01-15",
      "dueDate": "2026-02-15"
    }
  ],
  "metadata": { "total": 231 }
}

Obtener una compra

http
GET /bills/{id}
CampoTipoRequeridoDescripción
idstring (cuid2)Identificador de la compra.

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

Actualizar una compra

Solo se pueden editar los campos de cabecera. Las líneas de la compra no se modifican vía PUT. Si necesitas corregir ítems, anula la compra y vuelve a registrarla.

http
PUT /bills/{id}
CampoTipoRequeridoDescripción
providerIdstring (cuid2) o nullNoCambia o elimina el proveedor.
notestring o nullNoActualiza la nota.
datestring (ISO date) o nullNoActualiza la fecha.
dueDatestring (ISO date) o nullNoActualiza el vencimiento.

WARNING

Debes enviar al menos uno de los campos anteriores. Una petición con el cuerpo vacío devuelve validation_error.

bash
curl -X PUT "https://api-pos.zelta.dev/public/v1/bills/bl2k5m8p1q4v7r0n3t6w9y2z" \
  -H "Authorization: Bearer zpk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "dueDate": "2026-03-01", "note": "Plazo extendido por acuerdo" }'

Ejemplo JS

javascript
const res = await fetch('https://api-pos.zelta.dev/public/v1/bills/bl2k5m8p1q4v7r0n3t6w9y2z', {
  method: 'PUT',
  headers: { 'Authorization': `Bearer ${process.env.ZELTA_POS_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ dueDate: '2026-03-01', note: 'Plazo extendido por acuerdo' })
});
const data = await res.json();

Ejemplo Py

python
import requests
res = requests.put(
    'https://api-pos.zelta.dev/public/v1/bills/bl2k5m8p1q4v7r0n3t6w9y2z',
    headers={'Authorization': 'Bearer zpk_live_xxx', 'Content-Type': 'application/json'},
    json={ 'dueDate': '2026-03-01', 'note': 'Plazo extendido por acuerdo' }
)
data = res.json()

Respuesta 200 OK: devuelve el objeto de la compra actualizado. Si no existe, responde 404 not_found.

Problemas comunes

CódigoHTTPCausa
validation_error400Cuerpo vacío o tipos inválidos.
unauthorized401API key ausente o inválida.
not_found404La compra o el providerId no existen.

Siguientes pasos

  • — consulta cómo la compra impacta el kardex y el stock.
  • — registra abonos sobre la cuenta por pagar.
  • — registra egresos que no aumentan inventario.
  • — descubre proveedores, bodegas e impuestos.

Documentación oficial de Zelta