Reten Docs
Filtros de eventos

Actualizar filtro de eventos

Actualiza el nombre, la descripción o la definición completa de un filtro de eventos existente.

PATCH /api/event-criterias/:id

Actualiza un filtro de eventos existente. Los tres campos del cuerpo son opcionales: se puede cambiar solo el nombre, solo la descripción, solo la definición, o cualquier combinación.

Auth: Requerida — permiso event-criteria:update

Parámetros de ruta

ParámetroTipoDescripción
idUUIDID del filtro de eventos.

Cuerpo de la solicitud

Nivel raíz (UpdateEventCriteriaDto):

CampoTipoRequeridoDescripción
namestringNoNuevo nombre. Si se envía, no puede ser vacío ni null.
descriptionstring | nullNoNueva descripción. Enviar null la deja vacía.
queryBlocksQueryBlockDto[]NoNueva definición completa. Mínimo 1 elemento si se envía. Reemplaza los bloques existentes.

La estructura de cada bloque está en Definición.

Semántica del PATCH

El PATCH es parcial entre campos, pero total dentro de queryBlocks. Es la distinción que decide si una actualización pierde bloques:

Qué se envíaQué pasa
name y/o descriptionSe actualizan solo esos campos. Los bloques de consulta quedan intactos.
queryBlocksSe borran todos los bloques del filtro y se crean los enviados. No hay merge por order ni por id.
Nada (cuerpo {})El filtro no cambia, salvo updatedBy y updatedAt.

queryBlocks reemplaza la definición entera. Enviar un solo bloque en un filtro que tenía tres deja el filtro con un bloque; los otros dos se borran. Para modificar un bloque hay que enviar la lista completa, incluidos los que no cambian.

Los bloques enviados se persisten como bloques nuevos: sus id no son los que tenía el filtro antes, aunque el order y el contenido coincidan. Un id de bloque no es un identificador estable entre actualizaciones de la definición.

En toda actualización, updatedBy pasa a ser el usuario que hace la solicitud y updatedAt se refresca.

Ejemplo

Cambiar el nombre y reemplazar la definición por una que agrega un filtro de registro sobre items.

curl -X PATCH https://api.reten.ai/api/event-criterias/4b8e0f15-2c76-4a03-9d58-7e1f2a3b4c5d \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ventas con ítems no-devolución",
    "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": "recordPredicate",
              "column": { "table": "event_transactions", "column": "items" },
              "subWhere": {
                "kind": "group",
                "logicalOperator": "AND",
                "children": [
                  {
                    "kind": "predicate",
                    "field": "category",
                    "comparisonOperator": "NOT_IN",
                    "value": ["devolucion"]
                  }
                ]
              }
            }
          ]
        }
      }
    ]
  }'
import axios from 'axios';

const id = '4b8e0f15-2c76-4a03-9d58-7e1f2a3b4c5d';
const body = {
  name: 'Ventas con ítems no-devolución',
  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: 'recordPredicate',
            column: { table: 'event_transactions', column: 'items' },
            subWhere: {
              kind: 'group',
              logicalOperator: 'AND',
              children: [
                {
                  kind: 'predicate',
                  field: 'category',
                  comparisonOperator: 'NOT_IN',
                  value: ['devolucion'],
                },
              ],
            },
          },
        ],
      },
    },
  ],
};

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

Respuesta 200 OK

Devuelve el filtro actualizado como IEventCriteriaDetail — la misma forma que GET /event-criterias/:id, con los bloques ya persistidos y sus id nuevos.

{
  "id": "4b8e0f15-2c76-4a03-9d58-7e1f2a3b4c5d",
  "projectId": "3f6c2b1a-8d4e-4f7a-9b2c-5e1d0a7f6c34",
  "name": "Ventas con ítems no-devolución",
  "description": "Ventas facturadas con al menos una línea que no es devolución",
  "isActive": true,
  "ownerId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "updatedBy": "0f0e0d0c-0b0a-4090-8070-605040302010",
  "createdAt": "2026-07-12T11:05:19.220Z",
  "updatedAt": "2026-07-18T16:41:02.907Z",
  "queryBlocks": [
    {
      "id": "c8d9e0f1-2a3b-4c5d-8e6f-7a8b9c0d1e2f",
      "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"
          },
          {
            "kind": "recordPredicate",
            "column": { "table": "event_transactions", "column": "items" },
            "subWhere": {
              "kind": "group",
              "logicalOperator": "AND",
              "children": [
                {
                  "kind": "predicate",
                  "field": "category",
                  "comparisonOperator": "NOT_IN",
                  "value": ["devolucion"]
                }
              ]
            }
          }
        ]
      },
      "groupBy": null,
      "having": null
    }
  ]
}

Reglas de validación

La definición se valida solo si el cuerpo trae queryBlocks, y antes de tocar nada: un reemplazo que no compila a SQL no borra los bloques que ya existían. Una actualización que solo cambia name o description no revalida la definición guardada.

El catálogo completo de reglas y sus mensajes exactos está en Definición → Reglas de validación.

Respuestas de error

EstadoDescripción
400El id no es un UUID válido, el DTO es inválido (tipo incorrecto, enum fuera de rango, queryBlocks vacío, propiedad desconocida) o una regla de negocio incumplida.
401Falta o es inválido el Authorization: Bearer.
403El usuario no tiene el permiso event-criteria:update, o el x-tenant-id no está autorizado.
404No existe un filtro de eventos con ese id en el tenant (Event criteria not found).