KicketKicket
Mi cuenta
Guía · Conciliación▾
  • Inicio
  • Primeros pasos
  • Autenticación
  • Paginación y sincronización
  • Errores
  • Límites de uso
  • Webhooks
  • Conciliación
  • Modelo de datos
  • Referencia
  • Descargas
  • Cambios

API de Kicket · v1

  • Inicio
  • Primeros pasos
  • Autenticación
  • Paginación y sincronización
  • Errores
  • Límites de uso
  • Webhooks
  • Conciliación
  • Modelo de datos
  • Referencia
  • Descargas
  • Cambios

Conciliación

Las cuentas que cierran siempre, y cómo llegar desde tus ventas al mismo número que ve el dueño en Analítica.

Lo que cierra en cada venta

Todas las cuentas cierran al centavo. Pasá los importes a centavos enteros (Math.round(x * 100)) antes de sumar.

CuentaEn la venta de ejemplo
Σ line_total de los renglones con voided: false = total2520 + 540 + 0 + 6750 + 0 + 0 = 9810
line_total = unit_price × quantity − discount, en cada renglónCafé con leche: 2800 × 1 − 280 = 2520
subtotal − discount_total = total10900 − 1090 = 9810
Σ discounts[].amount = discount_total1090
Σ amount de los pagos que no están canceled = total5000 + 4810 = 9810
  • total es con IVA y neto de descuentos, y no incluye el costo de servicio, la propina ni el envío (van aparte: service_fee, tip_total, delivery_fee). Lo que de verdad pasó por cada medio, con esos extras, está en charged_amount del pago.
  • Los renglones anulados (voided: true) traen su valor propio para que sepas qué se sacó, pero no suman.
  • Un descuento de la venta se reparte entre los renglones con plata, en proporción. Si el reparto deja una diferencia de centavos, aparece como un descuento other llamado «Redondeo» (puede ser negativo).
  • La cuenta de los pagos vale para las ventas CLOSED y REFUNDED, con dos excepciones: una ronda de mesa OPEN todavía no tiene pagos, y una mesa VIP a la que le faltó crédito y no se cobró la diferencia tiene Σ amount menor que el total (es la verdad: falta plata).
  • En una CANCELED depende de qué pasó con la plata: si quedó en la caja, los pagos salen approved y suman el total; si nunca se cobró (una venta duplicada o cargada por error), salen canceled y no suman nada.
  • Con una devolución parcial, cada pago dice lo que se cobró por su medio (charged_amount), lo que volvió por ese medio (refunded_amount) y lo que quedó (amount): la plata devuelta en efectivo sale del pago en efectivo, no de la tarjeta.

La jornada: business_date

Cada venta tiene su business_date: la jornada comercial a la que pertenece, que va de las 06:00 a las 06:00 del día siguiente en el huso de su sucursal. Una venta del domingo a las 02:30 es de la jornada del sábado. Es el mismo corte que usan los reportes de Kicket, y se calcula por la hora en que se abrió la venta.

Para traer una jornada entera: GET /sales?business_date=2026-10-27.

El reporte diario

GET /reports/daily-sales?business_date=… devuelve, por sucursal, el número contra el que se concilia: el mismo que muestra Analítica › Reportes › Ventas para esa jornada. No es un cálculo aparte: sale de las mismas funciones que la pantalla, así que si el dueño ve un número, la API dice el mismo.

Respuesta
{
  "object": "list",
  "data": [
    {
      "object": "daily_sales_report",
      "branch_id": "65f1c0a2b7e4d91a3c5e7f10",
      "business_date": "2026-10-27",
      "currency": "ARS",
      "sales_count": 214,
      "total": 1284650,
      "canceled_count": 3,
      "canceled_total": 15600
    }
  ],
  "has_more": false,
  "next_cursor": null
}
CampoQué es
totalLa plata de la jornada: la de Analítica y la de Caja.
sales_countLas ventas de la jornada como las cuenta Analítica.
canceled_countLas anuladas de la jornada.
canceled_totalLo que sumaban las anuladas (no suma al total).

Cómo cuadrar /sales contra el reporte

Sumá, sobre las ventas de esa sucursal y esa jornada:

  • sólo las OPEN y CLOSED (las anuladas van aparte, en canceled_total);
  • de cada una, su total menos lo que pagaron los créditos ticket_credit y table_credit (sin bajar de cero). Esa plata ya se contó al vender la entrada o la mesa VIP, y Analítica no la cuenta dos veces. El crédito de empresa, la cuenta corriente y la seña sí suman: son ventas del día.

El resultado tiene que dar el total del reporte, al centavo.

Conciliar una jornada
import { llamar } from './kicket.mjs'

const centavos = (n) => Math.round(n * 100)

// La plata de una jornada como la cuenta Analítica, sumada desde /sales, contra /reports/daily-sales.
export async function conciliar(branchId, jornada) {
  let suma = 0
  let cursor = null
  do {
    const params = new URLSearchParams({ branch_id: branchId, business_date: jornada, status: 'OPEN,CLOSED', limit: '500' })
    if (cursor) params.set('cursor', cursor)
    const pagina = await llamar(`/sales?${params}`)
    for (const v of pagina.data) {
      // Lo que pagó el crédito de una entrada o de una mesa VIP ya se contó al venderlas: no suma acá.
      const enOtroLado = v.payments
        .filter((p) => (p.kind === 'ticket_credit' || p.kind === 'table_credit') && p.status !== 'canceled')
        .reduce((s, p) => s + centavos(p.amount), 0)
      suma += Math.max(0, centavos(v.total) - enOtroLado)
    }
    cursor = pagina.next_cursor
  } while (cursor)

  const reporte = await llamar(`/reports/daily-sales?business_date=${jornada}&branch_id=${branchId}`)
  const esperado = centavos(reporte.data[0].total)
  return { suma: suma / 100, reporte: esperado / 100, diferencia: (suma - esperado) / 100 }
}

Por qué sales_count puede no coincidir con la cantidad de ventas

Las cortesías y el consumo del personal salen en /sales como ventas CLOSED con total 0, pero Analítica no las cuenta como ventas. No cambian la plata; sólo la cantidad.

Conciliá jornadas cerradas. Mientras la jornada está en curso, los números se mueven, y los listados no muestran lo modificado en el último minuto (ver la ventana de asentamiento). Si una venta se corrige después, cambia su updated_at y la sincronización incremental te la trae de nuevo.

Por medio de pago y por caja

Cada pago trae su method_id (la clave estable del medio, la misma en todas las sucursales) y su kind: payment es plata que entró; los demás son créditos que cubren parte del total. Para cuadrar contra el cierre de una caja, usá GET /cash-sessions: cada caja cerrada trae lo esperado por medio de pago, el efectivo contado y la diferencia. Las ventas de la caja traen su cash_session_id.

Un cobro de mesa sale repartido en un pago por ronda: para cruzarlo con el posnet, agrupá los pagos por el check_id de su venta y por method_id. La propina de una mesa va en el tip_total de cada ronda.

En la venta de ejemplo, la propina de 1000 está sólo en tip_total: la caja la registra aparte y no sabe por qué medio entró, así que ningún pago la trae. Por eso, en la caja y en la mesa, charged_amount y amount coinciden; se separan en lo online (la pasarela cobra servicio, propina y envío) y después de una devolución parcial. Para cruzar con la terminal, si la propina entró por tarjeta, sumala aparte. Los dos pagos llevan el mismo created_at: la hora del cobro de la venta.

AnteriorWebhooksSiguienteModelo de datos