Operaciones y eventos
Leer el historial de transacciones: qué eventos existen, qué campos trae cada operación y cómo filtrarlos
Todo lo que pasa con una tarjeta queda registrado como una operación: un sello acreditado, una visita, un canje, una instalación. GET /api/v2/operations es el endpoint que te devuelve ese historial, y es el que vas a usar para conciliar tu sistema con Dardo.
curl "https://api.dardo.ai/api/v2/operations?itemsPerPage=100" \
-H "X-API-Key: TU_CLAVE_API"Filtros disponibles
| Parámetro | Tipo | Para qué |
|---|---|---|
templateId | integer | Operaciones de una plantilla de tarjeta puntual |
customerId | uuid | Todo el historial de un cliente |
cardId | string | Historial de una tarjeta, por su número de serie |
startDate | fecha | Desde cuándo |
endDate | fecha | Hasta cuándo |
page | integer | Página. Default 1, mínimo 1 |
itemsPerPage | integer | Default 30, rango 1–1000 |
Traer el último mes de un cliente:
curl "https://api.dardo.ai/api/v2/operations?customerId=UUID_DEL_CLIENTE&startDate=2026-08-01&endDate=2026-08-31" \
-H "X-API-Key: TU_CLAVE_API"El catálogo de eventos
Cada operación trae dos campos que dicen qué pasó: eventId (número) y eventName (texto).
eventId | eventName | Qué pasó |
|---|---|---|
1 | Stamps earned | Se acreditaron sellos |
2 | Rewards redeemed | El cliente canjeó un premio |
3 | Rewards earned | El cliente alcanzó un premio y quedó disponible para canjear |
5 | Card installed | El cliente instaló la tarjeta en su teléfono |
6 | Card deleted from device | El cliente borró la tarjeta de su teléfono |
16 | Feedback sent | El cliente dejó una opinión |
24 | Points earned | Se acreditaron puntos |
29 | Shared card | El cliente compartió su tarjeta |
42 | Visit logged | Se registró una visita |
Esta tabla son los eventos observados en cuentas reales, no una lista cerrada publicada por la API. Un programa que use mecánicas distintas puede registrar eventos que no están acá. Si te aparece un eventId que no figura, escribinos a soporte@dardo.ai con el número y lo sumamos.
Ramificá por eventId, no por eventName
Dos de los eventName llegan con un espacio al final: "Stamps earned " y "Rewards redeemed ". Son, justamente, los dos eventos centrales de un programa de lealtad.
op.eventName === "Stamps earned" // false, aunque el evento SEA ese
op.eventId === 1 // correctoUna comparación por igualdad contra el texto falla en silencio: no tira error, simplemente no entra nunca en ese if. Es de los errores más caros de encontrar porque todo parece funcionar.
eventId es numérico y estable. Usalo para la lógica, y dejá eventName para mostrar en pantalla o loguear. Si por lo que sea necesitás comparar el texto, aplicale .trim() primero.
Los campos de una operación
| Campo | Tipo | Qué es |
|---|---|---|
id | integer | Identificador de la operación |
companyId | integer | La cuenta |
templateId | integer | La plantilla de tarjeta |
customerId | uuid | El cliente |
customer | objeto | Datos del cliente, embebidos. Incluye sus segments |
cardId | string | Número de serie de la tarjeta |
cardDevice | string | Dónde tiene instalada la tarjeta: Apple Wallet, Google Pay, PWA |
eventId | integer | Qué pasó. Ramificá por acá |
eventName | string | Descripción del evento, para mostrar |
managerId | integer | null | Qué persona del equipo la registró |
locationId | integer | null | En qué sucursal |
amount | number | La magnitud del evento: cuántos sellos, cuántos puntos |
purchaseSum | number | El monto de la compra asociada |
balance | number | Saldo de la tarjeta después de la operación |
source | string | Por dónde entró la operación |
comment | string | null | Nota libre, si la operación la incluyó |
createdAt | string | Fecha y hora, ISO 8601 con offset |
updatedAt | string | Última modificación |
amount y purchaseSum son cosas distintas
amount es la magnitud del evento: si se acreditaron 2 sellos, es 2. purchaseSum es la plata de la compra que originó esa acreditación.
Una venta de $36.900 que otorga un sello se registra con amount: 1 y purchaseSum: 36900. Para facturación o conciliación querés purchaseSum; para saber cuántos sellos se movieron, amount.
purchaseSum se expresa en unidades de la moneda de la cuenta, no en centavos. Esto es distinto del objeto Check de Punto de venta, donde los montos sí van en centavos. Si tu integración usa las dos cosas, no mezcles las unidades.
source: por dónde entró la operación
| Valor | Origen |
|---|---|
scanner | La app de escáner, en el mostrador |
api | Un llamado a la API — acá es donde va a aparecer tu integración |
workflow | Una automatización |
auto | El sistema, sin intervención |
webapp | El panel web |
"" | Sin origen registrado. Es un valor posible: contemplá la cadena vacía |
Filtrar por source del lado del cliente es la forma de separar lo que registró tu integración de lo que hizo el personal en el local.
managerId y locationId vienen vacíos seguido
Los dos son null en la mayoría de las operaciones: solo se completan cuando la operación la registró una persona del equipo desde una sucursal. Una acreditación hecha por API no los trae.
Si necesitás saber en qué sucursal ocurrió una venta que cargás vos, leé la advertencia sobre sucursales en Punto de venta.
Para resolver el nombre de una sucursal a partir de su locationId, cruzá contra Ubicaciones.
Paginar el historial
La respuesta trae un meta con el total:
{
"data": [ ... ],
"meta": { "totalItems": 36012, "itemsPerPage": 100, "currentPage": 1 }
}No hay totalPages ni hasMore: se calculan.
const ultimaPagina = Math.ceil(meta.totalItems / meta.itemsPerPage);Un historial grande se pagina en muchos pedidos, y mientras los recorrés pueden entrar operaciones nuevas que corren las filas. Para conciliar, acotá siempre con startDate y endDate sobre un período ya cerrado en vez de recorrer el historial completo. Más detalle en Límites y paginación.