Reten Docs
Filtros de eventos

Crear filtro de eventos

Crea un filtro de eventos a partir de su definición completa (bloques de consulta, filtros, ventana temporal y agregaciones).

POST /api/event-criterias

Crea un filtro de eventos a partir de su definición completa. La operación es transaccional: el filtro y sus bloques de consulta se crean juntos, o no se crea nada.

Auth: Requerida — permiso event-criteria:create

Cuerpo de la solicitud

Nivel raíz (CreateEventCriteriaDto):

CampoTipoRequeridoDescripción
namestringSíNombre del filtro. No puede ser vacío.
descriptionstringNoDescripción de texto libre. Si se omite, la respuesta la devuelve como null.
queryBlocksQueryBlockDto[]SíMínimo 1 elemento. Cada bloque ≈ un statement SQL completo.

La estructura de cada bloque —order, setOperator, from, select, timeWindow, where, groupBy, having— está en Definición.

No existe composedWith: un filtro de eventos no se compone con otros filtros. Enviarlo produce un 400 por propiedad desconocida.

Ejemplos

Filtro de columna

Eventos cuyo status es Facturada.

curl -X POST https://api.reten.ai/api/event-criterias \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Venta oficial — solo facturada",
    "description": "Definición canónica de evento válido",
    "queryBlocks": [
      {
        "order": 0,
        "from": { "table": "event_transactions", "joins": [] },
        "select": {
          "distinct": true,
          "items": [
            { "kind": "column", "column": { "table": "event_transactions", "column": "event_id" } }
          ]
        },
        "where": {
          "kind": "group",
          "logicalOperator": "AND",
          "children": [
            {
              "kind": "predicate",
              "column": { "table": "event_transactions", "column": "status" },
              "comparisonOperator": "EQUALS",
              "value": "Facturada"
            }
          ]
        }
      }
    ]
  }'
import axios from 'axios';

const body = {
  name: 'Venta oficial — solo facturada',
  description: 'Definición canónica de evento válido',
  queryBlocks: [
    {
      order: 0,
      from: { table: 'event_transactions', joins: [] },
      select: {
        distinct: true,
        items: [
          { kind: 'column', column: { table: 'event_transactions', column: 'event_id' } },
        ],
      },
      where: {
        kind: 'group',
        logicalOperator: 'AND',
        children: [
          {
            kind: 'predicate',
            column: { table: 'event_transactions', column: 'status' },
            comparisonOperator: 'EQUALS',
            value: 'Facturada',
          },
        ],
      },
    },
  ],
};

const response = await axios.post(
  'https://api.reten.ai/api/event-criterias',
  body,
  { headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);
const created = response.data;

Filtro de registro

Eventos que tienen un atributo cuya key es documento_tipo y cuyo value es factura — las dos condiciones sobre el mismo elemento de attributes.

{
  "name": "Documentos tipo factura",
  "queryBlocks": [
    {
      "order": 0,
      "from": { "table": "event_transactions", "joins": [] },
      "select": {
        "distinct": true,
        "items": [
          { "kind": "column", "column": { "table": "event_transactions", "column": "event_id" } }
        ]
      },
      "where": {
        "kind": "group",
        "logicalOperator": "AND",
        "children": [
          {
            "kind": "recordPredicate",
            "column": { "table": "event_transactions", "column": "attributes" },
            "subWhere": {
              "kind": "group",
              "logicalOperator": "AND",
              "children": [
                { "kind": "predicate", "field": "key", "comparisonOperator": "EQUALS", "value": "documento_tipo" },
                { "kind": "predicate", "field": "value", "comparisonOperator": "EQUALS", "value": "factura" }
              ]
            }
          }
        ]
      }
    }
  ]
}

Filtro de tabla relacionada

Eventos facturados con al menos una línea cuyo producto es de categoría Food Service u HORECA. El camino hasta product_properties lo resuelve el catálogo: la solicitud solo nombra el semi-join.

{
  "name": "Proyecto Food Service",
  "queryBlocks": [
    {
      "order": 0,
      "from": { "table": "event_transactions", "joins": [] },
      "select": {
        "distinct": true,
        "items": [
          { "kind": "column", "column": { "table": "event_transactions", "column": "event_id" } }
        ]
      },
      "where": {
        "kind": "group",
        "logicalOperator": "AND",
        "children": [
          {
            "kind": "predicate",
            "column": { "table": "event_transactions", "column": "status" },
            "comparisonOperator": "EQUALS",
            "value": "Facturada"
          },
          {
            "kind": "semiJoinPredicate",
            "table": "event_transactions",
            "semiJoin": "products",
            "subWhere": {
              "kind": "group",
              "logicalOperator": "AND",
              "children": [
                {
                  "kind": "predicate",
                  "field": "categorization.category_name",
                  "comparisonOperator": "IN",
                  "value": ["Food Service", "HORECA"]
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

Respuesta 201 Created

Devuelve el filtro creado como IEventCriteriaDetail — la misma forma que GET /event-criterias/:id: el recurso base más queryBlocks[], con su id ya resuelto y ordenados por order ascendente.

CampoTipoDescripción
idstring (UUID)Id del filtro creado.
projectIdstring (UUID)Proyecto al que pertenece el filtro.
namestring
descriptionstring | nullnull si no se envió.
isActivebooleanSiempre true: ningún endpoint lo modifica.
ownerIdstring (UUID)Usuario creador.
updatedBystring (UUID)Último editor (en la creación, el creador).
createdAtstring (ISO 8601)
updatedAtstring (ISO 8601)
queryBlocksarrayLos bloques persistidos, con su id.
{
  "id": "9f3a1c22-4b7e-4c31-9a8d-2f5e6b7c8d90",
  "projectId": "3f6c2b1a-8d4e-4f7a-9b2c-5e1d0a7f6c34",
  "name": "Venta oficial — solo facturada",
  "description": "Definición canónica de evento válido",
  "isActive": true,
  "ownerId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "updatedBy": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "createdAt": "2026-07-10T09:12:44.005Z",
  "updatedAt": "2026-07-10T09:12:44.005Z",
  "queryBlocks": [
    {
      "id": "e5f6a708-91b2-4c33-8d44-5e6f7a8b9c01",
      "order": 0,
      "setOperator": null,
      "from": { "table": "event_transactions", "joins": [] },
      "select": {
        "distinct": true,
        "items": [
          { "kind": "column", "column": { "table": "event_transactions", "column": "event_id" } }
        ]
      },
      "timeWindow": null,
      "where": {
        "kind": "group",
        "logicalOperator": "AND",
        "children": [
          {
            "kind": "predicate",
            "column": { "table": "event_transactions", "column": "status" },
            "comparisonOperator": "EQUALS",
            "value": "Facturada"
          }
        ]
      },
      "groupBy": null,
      "having": null
    }
  ]
}

Reglas de validación

La definición se valida antes de persistirse: un filtro que no compila a SQL no se crea. El catálogo completo de reglas y sus mensajes exactos está en Definición → Reglas de validación.

Respuestas de error

EstadoDescripción
400DTO inválido (campo faltante, tipo incorrecto, enum fuera de rango, propiedad desconocida) o una regla de negocio incumplida.
401Falta o es inválido el Authorization: Bearer.
403El usuario no tiene el permiso event-criteria:create, o el x-tenant-id no está autorizado.