Cómo se sincroniza con las cajas
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
Sección titulada «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:
{ "data_freshness": { "last_device_sync_at": "2026-09-28T14:58:12.000Z", "devices": [ { "name": "Caja 01", "kind": "primary", "platform": "windows", "last_sync_at": "2026-09-28T14:58:12.000Z" }, { "name": "Caja 02", "kind": "primary", "platform": "android", "last_sync_at": "2026-09-28T09:12:40.000Z" }, { "name": "Tablet bodega", "kind": "primary", "platform": "android", "last_sync_at": null } ] }}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
Sección titulada «Las ventas traen dos fechas»Cada venta trae dos momentos distintos:
| Campo | Qué es |
|---|---|
occurred_at |
Cuándo se registró la venta en la caja, con el reloj de esa caja. Es la fecha del negocio: úsala para reportes. |
created_at |
Cuándo la venta llegó a la nube. Una caja que vendió sin internet sube sus ventas al reconectarse, y quedan con la hora de subida. |
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.
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
Sección titulada «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 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
Sección titulada «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 mover existencias usa movimientos.
Si cambias base_price sin enviar final_price, final_price toma el mismo valor.
Las cajas deben estar actualizadas
Sección titulada «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:
{ "error": { "code": "DEVICES_OUTDATED", "message": "No se modificó nada: estas cajas todavía no tienen la versión de Posdata que acepta ediciones de productos desde la API: Caja 02. Ábrelas con internet para que se actualicen solas (tarda un minuto en reportarse) o, si ya no las usas, revócalas en cuenta.posdata.so → Dispositivos. Crear productos y mover stock sí funciona mientras tanto.", "devices": [ { "name": "Caja 02", "kind": "primary", "platform": "android", "app_version": "260901-a1b2c3d", "last_seen_at": "2026-09-20T17:42:10.000Z" } ], "request_id": "req_…" }}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: todavía no publicamos un número
Sección titulada «Stock: todavía no publicamos un número»Los productos traen el campo stock, pero hoy siempre es null. Todavía no publicamos un número de
existencias porque no podemos garantizar que coincida con el de las cajas: cada caja lleva su propio
inventario y descuenta sus ventas aunque esté sin internet. Preferimos no darte un número que parece
correcto y no lo es: una tienda en línea podría vender lo que ya no hay. Lo activaremos cuando podamos
garantizarlo y lo anunciaremos en el changelog.
Mientras tanto:
- No infieras el stock (ni de
null, ni sumando lo que ves en la API como si fuera el total real). - Si tu sistema necesita una cifra, lleva tu propio conteo: parte de un inventario inicial que conozcas,
suma y resta tus movimientos (
POST /inventory/movements) y concilia con el historial (GET /inventory/movements), que incluye los movimientos de las ventas que las cajas ya subieron. - Las variantes nunca traen stock.
Stock: solo por movimientos
Sección titulada «Stock: solo por movimientos»Para sumar o restar existencias usa POST /inventory/movements con type: "in" (entrada) o
type: "out" (salida) y una cantidad entera mayor que cero en la unidad base del producto. Nunca se fija el
stock a un valor absoluto.
- Cada caja aplica el movimiento una sola vez, aunque haya vendido sin conexión mientras tanto: un movimiento es una diferencia (sumar 24, restar 3), no un valor que pisa al de la caja.
- La bodega debe ser una que las cajas conocen. Si no envías
warehouse_id, se usa la bodega predeterminada (o la única activa); si no hay una clara, la respuesta es409 NO_WAREHOUSE. - La API no verifica existencias antes de una salida (no conoce el stock real de cada caja).
- Los movimientos creados por la API aparecen en el historial con
origin_type: "api"y, si no envíasreason, con el motivo «Movimiento vía API». - Crear un producto con
initial_stockregistra además un movimiento de entrada. - Puedes leer los movimientos (
GET /inventory/movements), incluidos los de las ventas que las cajas ya subieron. Son el historial de lo que pasó, no una cifra de existencias.
Hay dos casos que la versión 1 rechaza:
- Productos con variantes (
VARIANT_STOCK_UNSUPPORTED): el stock de cada variante viaja entre las cajas como un valor absoluto, no como movimientos. Si la API moviera ese stock mientras una caja vende la misma variante sin conexión, uno de los dos cambios podría perderse. Por ahora, ajústalo desde Posdata. - Productos que se arman con receta (
COMPOSITE_STOCK_UNSUPPORTED): no tienen stock propio; lo tienen sus insumos. Mueve el stock de los insumos.
Dinero, impuestos y cantidades
Sección titulada «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
Sección titulada «Lo que la API no hace en la versión 1»Para que sepas con qué contar hoy:
- No publica el stock: el campo
stockde los productos es siemprenullpor ahora (explicado arriba). Sí mueve stock por movimientos. - No edita el stock, la unidad, la venta por peso ni el tipo de un producto, y solo edita productos y
variantes cuando todos los dispositivos del negocio están actualizados (
409 DEVICES_OUTDATED). - No mueve stock de productos con variantes ni de productos con receta.
- 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.