> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pos.terominds.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Catálogo de eventos

> Envelope y detalle de cada evento que Tero POS envía al ERP, con ejemplos JSON.

## Envelope

Todos los eventos usan el mismo sobre, tanto en [webhooks](https://docs.pos.terominds.com/api/webhooks.md) como en el [pull](https://docs.pos.terominds.com/api/eventos.md):

```json theme={null}
{
  "event_id": "uuid (idempotente)",
  "seq": 18234,
  "tenant_id": "uuid",
  "type": "sale.created",
  "occurred_at": "2026-10-21T19:00:00.000Z",
  "source": { "pos_id": "uuid|null", "location_id": "uuid|null" },
  "data": {}
}
```

* **Montos en pesos enteros** (como en la base). Los costos van en **centavos** (`unit_cost_cents`).
* Los timestamps del POS en milisegundos se exponen también como `*_at_millis`.
* `seq` es monótono **por empresa**. `event_id` es único y sirve para deduplicar.

## `sale.created`

Venta confirmada (cobrada, fiada o consumo). Se emite una sola vez; una resubida idempotente de la tablet no lo duplica.

```json theme={null}
{
  "type": "sale.created",
  "data": {
    "sale_id": "uuid",
    "pos_id": "uuid",
    "location_id": "uuid",
    "employee_id": "uuid|null",
    "created_at_millis": 1792600000000,
    "sale_kind": "sale",
    "consumo_beneficiary": null,
    "consumo_note": null,
    "subtotal_pesos": 12000,
    "discount_pesos": 1200,
    "discount_percent": 10,
    "discount_source": "preset",
    "discount_type": "percentage",
    "discount_value": 10,
    "total_pesos": 10800,
    "payment_method": "EFECTIVO",
    "cash_tendered_pesos": 11000,
    "change_pesos": 200,
    "fiscal_requested": true,
    "lines": [
      {
        "line_index": 0,
        "product_id": "uuid|null",
        "custom_title": null,
        "unit_price_pesos": 6000,
        "quantity": 2,
        "unit_cost_cents": 350000
      }
    ],
    "payments": [
      {
        "line_index": 0,
        "payment_method": "EFECTIVO",
        "amount_pesos": 10800,
        "cash_tendered_pesos": 11000,
        "change_pesos": 200,
        "rail_attempt_id": null
      }
    ]
  }
}
```

> [!NOTE]
>
> El descuento es a nivel de orden. El ERP lo prorratea por importe de línea. `sale_kind` puede ser `sale`, `fiado` o `consumo`; en `consumo` no hay cobro (solo egreso de stock).

## `sale.voided`

Anulación total de una venta.

```json theme={null}
{
  "type": "sale.voided",
  "data": {
    "sale_id": "uuid",
    "cancelled_at_millis": 1792600500000,
    "cancelled_by_employee_id": "uuid|null"
  }
}
```

## `fiscal_document.issued`

Comprobante autorizado por ARCA. Cubre **facturas y notas de crédito**: se distinguen por `kind`. No existe un evento separado `credit_note.issued`.

```json theme={null}
{
  "type": "fiscal_document.issued",
  "data": {
    "fiscal_invoice_id": "uuid",
    "sale_id": "uuid",
    "location_id": "uuid",
    "pos_id": "uuid|null",
    "kind": "invoice",
    "reverses_invoice_id": null,
    "punto_venta": 3,
    "cbte_tipo": 6,
    "cbte_nro": 1542,
    "cae": "75123456789012",
    "cae_vto": "20261031",
    "doc_tipo": 99,
    "doc_nro": 0,
    "imp_total": 10800,
    "imp_neto": 8926,
    "imp_iva": 1874,
    "created_at": "2026-10-21T19:00:00.000Z"
  }
}
```

Para una nota de crédito: `kind` = `credit_note`, `reverses_invoice_id` apunta a la factura revertida y `cbte_tipo` es 8 (NC B) o 13 (NC C).

## `fiscal_document.failed`

Fallo de facturación persistido. `will_retry` indica si el backend POS reintentará el CAE con backoff.

```json theme={null}
{
  "type": "fiscal_document.failed",
  "data": {
    "sale_id": "uuid",
    "location_id": "uuid",
    "pos_id": "uuid|null",
    "kind": "invoice",
    "error": "afip_rejected",
    "detail": "fetch failed",
    "afip_observations": [],
    "attempt_count": 2,
    "will_retry": true,
    "attempted_at": "2026-10-21T19:05:00.000Z"
  }
}
```

Errores no reintentables (por ejemplo `punto_venta_missing` o fiscal deshabilitado) llegan con `will_retry: false` y no se vuelven a intentar. Cuando el reintento tiene éxito, llega `fiscal_document.issued`.

## `caja.closed`

Cierre de caja. `totals_by_payment_method` es **derivado**: suma `sale_payments` de ventas no anuladas con el mismo POS dentro de la ventana `opened_at..closed_at`.

```json theme={null}
{
  "type": "caja.closed",
  "data": {
    "session_id": "uuid",
    "pos_id": "uuid",
    "location_id": "uuid",
    "opened_at_millis": 1792590000000,
    "closed_at_millis": 1792620000000,
    "opened_by_employee_id": "uuid",
    "closed_by_employee_id": "uuid",
    "opening_counted_pesos": 5000,
    "cash_sales_count": 40,
    "cash_sales_total_pesos": 80000,
    "movements_in_pesos": 0,
    "movements_out_pesos": 2000,
    "expected_closing_pesos": 83000,
    "closing_counted_pesos": 82500,
    "closing_variance_pesos": -500,
    "closing_withdraw_pesos": 77500,
    "closing_leave_pesos": 5000,
    "mp_card_total_pesos": null,
    "tero_card_total_pesos": null,
    "mp_card_difference_pesos": null,
    "mp_reconciliation_reason": null,
    "totals_by_payment_method": [
      { "payment_method": "EFECTIVO", "amount_pesos": 80000 },
      { "payment_method": "MERCADOPAGO", "amount_pesos": 12000 }
    ],
    "movements": [
      {
        "id": "uuid",
        "direction": "out",
        "amount_pesos": 2000,
        "reason_code": "provider",
        "note": "Proveedor de bebidas",
        "created_at_millis": 1792605000000
      }
    ]
  }
}
```

> [!NOTE]
>
> La diferencia de arqueo (`closing_variance_pesos`) es solo de efectivo. La caja es por dispositivo: dos tablets en la misma sucursal pueden tener cierres distintos.

## `stock.changed`

Todo cambio de stock aplicado, con el saldo resultante. Los movimientos que origina el ERP llegan con `reason` prefijado `erp_`.

```json theme={null}
{
  "type": "stock.changed",
  "data": {
    "location_id": "uuid",
    "product_id": "uuid",
    "delta": -2,
    "reason": "sale",
    "sale_id": "uuid|null",
    "transfer_id": "uuid|null",
    "pos_id": "uuid|null",
    "stock_quantity_after": 18,
    "applied_at_millis": 1792600000000
  }
}
```

`reason` puede ser `sale`, `sale_cancel`, `manual_adjust`, `transfer_out`, `transfer_in`, `transfer_void`, `admin_set`, `erp_receipt`, `erp_transfer_in`, `erp_transfer_out`, `erp_adjustment`, `erp_return_to_supplier` o `erp_other`.

## `stock_transfer.updated`

Transferencia entre sucursales creada o con cambio de estado.

```json theme={null}
{
  "type": "stock_transfer.updated",
  "data": {
    "transfer_id": "uuid",
    "from_location_id": "uuid",
    "to_location_id": "uuid",
    "status": "received",
    "source": "pos",
    "item_count": 2,
    "total_quantity": 5,
    "created_at_millis": 1792600000000,
    "issued_at_millis": 1792600100000,
    "received_at_millis": 1792600200000,
    "voided_at_millis": null,
    "completed_at_millis": 1792600200000,
    "items": [{ "product_id": "uuid", "quantity": 3 }]
  }
}
```

## `fiado.created`

Alta de una cuenta de fiado.

```json theme={null}
{
  "type": "fiado.created",
  "data": {
    "credit_sale_id": "uuid",
    "sale_id": "uuid",
    "origin_location_id": "uuid",
    "barcode": "F…",
    "debtor_name": "Juan Pérez",
    "debtor_reference": "DNI 30123456",
    "principal_pesos": 10800,
    "status": "open"
  }
}
```

## `fiado.paid`

Cobro aplicado a un fiado.

```json theme={null}
{
  "type": "fiado.paid",
  "data": {
    "settlement_id": "uuid",
    "credit_sale_id": "uuid",
    "sale_id": "uuid",
    "pos_id": "uuid",
    "location_id": "uuid",
    "status": "applied",
    "requested_amount_pesos": 5000,
    "applied_amount_pesos": 5000,
    "payments": [
      { "line_index": 0, "payment_method": "EFECTIVO", "amount_pesos": 5000 }
    ]
  }
}
```

## `product.created`

Producto creado desde el POS (alta por escaneo) o desde el back office. El ERP lo adopta o lo rechaza (`DELETE` de producto vía API).

```json theme={null}
{
  "type": "product.created",
  "data": {
    "id": "uuid",
    "tenantId": "uuid",
    "categoryId": "uuid",
    "name": "Producto nuevo",
    "pricePesos": 1500,
    "sortOrder": 10,
    "ean": "7790000000001",
    "ivaAlicuota": 21,
    "kind": "simple",
    "eans": ["7790000000001"],
    "created_by_pos_id": "uuid|null"
  }
}
```

`created_by_pos_id` viene informado cuando el producto nació en una tablet.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.