Cómo se sincroniza con las cajas
Qué ve la API, cuándo llegan tus cambios a las cajas y los límites de esta versión. Léelo antes de integrar.
Posdata funciona sin internet: cada caja (el computador, la tablet o el celular donde se vende) guarda sus datos localmente y los sube a la nube cuando tiene conexión. La API pública trabaja sobre esa nube. Entender esto te evita reportes equivocados.
La API ve lo que las cajas ya subieron
Cuando lees ventas, turnos de caja o movimientos, ves lo que las cajas ya subieron. Si una caja lleva horas sin internet, sus ventas de esas horas todavía no están en la API; aparecerán cuando se reconecte.
Para saber qué tan al día están los datos, consulta GET /me → data_freshness:
last_sync_ates el último cambio que esa caja subió de verdad a la nube, no la última vez que se conectó. Esnullsi la caja nunca ha subido nada.last_device_sync_ates el más reciente de todos.
En el ejemplo, la Caja 02 no sube nada desde las 9:12 (UTC). Puede que no haya vendido, o puede que esté sin internet con ventas pendientes: la API no puede distinguirlo. Antes de cerrar un reporte del día, revisa que las cajas que vendieron hayan subido cambios después de su cierre.
Las ventas traen dos fechas
Cada venta trae dos momentos distintos:
En una caja con internet las dos fechas casi coinciden. Si la caja vendió el sábado sin conexión y subió
el lunes, occurred_at dice sábado y created_at dice lunes.
En las ventas que llegaron a la nube antes del 28 de septiembre de 2026, occurred_at es igual a la hora
de llegada (created_at): la hora de la caja no se guardaba.
Qué usa cada cosa:
occurred_sinceyoccurred_untildeGET /salesfiltran poroccurred_at(la fecha del negocio).created_since,created_untilyupdated_sincefiltran por la llegada a la nube (y la última modificación). Son los filtros para la sincronización incremental: una venta que llega tarde tiene uncreated_atreciente, así que nunca te la saltas. Si sincronizas poroccurred_since, una venta del sábado que sube el lunes cae en un rango que quizás ya procesaste.- El reporte
GET /reports/daily-salessuma las ventas completadas por día calendario de Bogotá (America/Bogota) segúnoccurred_at, con un rango de hasta 92 días. La venta del sábado cuenta el sábado, pero solo aparece en el reporte cuando la caja la sube: un día puede cambiar después de cerrado.
Tus cambios llegan a las cajas por su sincronización normal
Cuando creas algo por la API (un producto, una categoría, un cliente, un movimiento o un conteo de inventario) o editas un producto, una variante, una categoría o un cliente, el cambio queda en la nube de inmediato y las cajas lo reciben por su sincronización normal:
- Cajas en línea: en segundos. Posdata les avisa que hay cambios nuevos.
- Cajas sin conexión: cuando se reconecten.
La API responde en cuanto el cambio está guardado en la nube; no espera a que las cajas lo reciban. Para las cajas, tu integración es un dispositivo más del negocio. En las ediciones gana el cambio más reciente: si alguien edita el mismo cliente desde una caja, se queda el que llegue último.
Productos: se crean y se editan
- Crear:
POST /productscrea productos sin variantes, coninitial_stockopcional. - Editar un producto:
PATCH /products/{id}cambia el nombre, las descripciones, el SKU, la categoría, los precios (base_price,final_price,percent_discount), la clase fiscal y el estado (active,sellable). - Editar una variante:
PATCH /products/{id}/variants/{variantId}cambia su etiqueta, SKU, precios y estado (active). Responde el producto completo, con todas sus variantes.
Una edición nunca toca el inventario: el cambio viaja a las cajas sin stock, y cada caja conserva
el suyo. Por eso tampoco se pueden editar el stock, la unidad (base_unit), la venta por peso
(sold_by_weight) ni el tipo de producto (kind): cambiarían el significado del stock que ya tiene cada
caja. Para cambiar existencias usa movimientos y conteos.
Si cambias base_price sin enviar final_price, final_price toma el mismo valor.
Las cajas deben estar actualizadas
Una caja con una versión vieja de Posdata interpretaría una edición sin stock como «stock en cero». Para
que eso nunca pase, editar productos y variantes solo funciona cuando todos los dispositivos del negocio
tienen la versión de Posdata que lo soporta. Si alguno no la tiene, la respuesta es
409 DEVICES_OUTDATED, no se modifica nada y el error trae la lista de dispositivos que faltan:
Cómo resolverlo:
- Abre esos dispositivos con internet. Posdata se actualiza solo y, un minuto después, el dispositivo reporta la versión nueva. Luego reintenta la edición.
- Si ya no usas alguno, revócalo en cuenta.posdata.so → Dispositivos. Un dispositivo olvidado en un cajón también cuenta.
last_seen_at es la última vez que ese dispositivo se reportó (null si nunca lo hizo) y te ayuda a
reconocer los que ya no se usan. Mientras tanto, crear productos y mover stock sí funciona.
Stock e inventario
El stock se lleva por nivel (bodega, producto, variante): el último conteo físico más los movimientos ocurridos después. Todo el detalle está en Cómo funciona el stock. Lo esencial para sincronizar:
- La nube lleva el stock oficial cuando todas las cajas principales del negocio tienen la versión de
Posdata que lo soporta (el paso es automático). Antes de eso,
stockesnullen productos y variantes, yGET /inventory/levels,POST /inventory/countsy los movimientos de variantes responden409 STOCK_MODE_LEGACY. Mira los dos modos. POST /inventory/movementssuma (in) o resta (out) stock; nunca fija un valor absoluto. Con el stock en la nube, una salida es atómica y nunca compromete las últimas unidades que el negocio reserva para sus cajas (el margen de la API): si no alcanza, responde409 INSUFFICIENT_STOCKy no registra nada.POST /inventory/countsregistra un conteo físico en el instante en que se hizo (counted_at): las ventas posteriores se suman encima, aunque lleguen más tarde.- Una entrada puede declarar su costo (
unit_costenPOST /inventory/movements) y el negocio lleva un costo promedio por producto.GET /inventory/kardexte da el libro de un producto con su saldo corrido yGET /inventory/valuation, el valor del inventario hoy o a una fecha de corte; los costos y valores exigen el permisoinventory:costsy un costo desconocido es siemprenull, nunca0(detalle). - Las ventas en las cajas nunca se rechazan. Si una caja sin internet vende lo que ya se comprometió por
otro canal, el nivel puede quedar negativo: Posdata avisa al negocio para que cuente y envía el webhook
inventory.stock.negative. - El stock que ves incluye solo lo que las cajas ya subieron, igual que las ventas: las ventas de una caja sin internet se aplican cuando se reconecta.
Dinero, impuestos y cantidades
- Dinero: pesos colombianos (COP) en enteros, sin decimales ni centavos.
25900son $25.900. - Precios de productos: tal como los digita el negocio. Lo normal es que incluyan impuestos; si el negocio configuró precios antes de impuestos, vienen así.
- Tarifas de impuesto: porcentaje entero.
19es 19 %, nunca0.19. Los impuestos por unidad (como el de bolsas) traenper_unityrate: null. - Impuestos de una venta: cada línea trae
taxescongelados al momento de vender, y la venta traetax_breakdownagrupado por tributo y tarifa, con el código DIAN (01IVA,04INC…). La propina (tip_amount) nunca es base gravable. Ingreso neto =total - tax - tip_amount. - Cantidades: pueden tener decimales en productos que se venden por peso; se expresan en la unidad base del producto.
- Fechas: ISO 8601 en UTC.
Lo que la API no hace en la versión 1
Para que sepas con qué contar hoy:
- Publica el stock solo cuando la cuenta lo lleva en la nube: mientras alguna caja principal no tenga
la versión de Posdata que lo soporta,
stockesnully los niveles, los conteos y los movimientos de variantes responden409 STOCK_MODE_LEGACY(detalle). - No edita el stock, la unidad, la venta por peso ni el tipo de un producto con
PATCH(el stock cambia solo con movimientos y conteos), y solo edita productos y variantes cuando todos los dispositivos del negocio están actualizados (409 DEVICES_OUTDATED). - No mueve ni cuenta stock de productos con receta: muévelo en sus insumos.
- No aparta stock: no hay reservas con vencimiento. Una salida descuenta de inmediato (o, con el stock en la
nube, responde
409 INSUFFICIENT_STOCKsi no alcanza), y no hay una operación que descuente varias líneas a la vez o ninguna. - El margen de la API es uno por cuenta, no por producto ni por bodega.
- No calcula costos por su cuenta: el costo promedio sale de las entradas con
unit_costy de lo que el negocio registra en la app. El valor del inventario no incluye los productos sin costo ni los niveles negativos (los lista aparte). - No crea ventas, facturas ni pedidos externos, y no emite facturas electrónicas de ventas hechas fuera del POS.
- No sube imágenes, no elimina registros y no crea variantes.
- No publica el PDF ni el XML de los documentos electrónicos.
- No ofrece OAuth para aplicaciones de terceros: cada negocio crea sus propias keys.
- No restringe el acceso por dirección IP.
Si alguna de estas limitaciones te frena, cuéntanos tu caso en Soporte.