Reten Docs
Filtros de eventos

Pré-visualizar

Executa um filtro de eventos contra o BigQuery e retorna uma amostra limitada de linhas mais o total correspondente.

Pré-visualizar

Executa um filtro de eventos contra o BigQuery e retorna uma amostra das linhas reais que ele seleciona, mais o total. São duas rotas com a mesma resposta: uma executa uma definição enviada no corpo e a outra um filtro já salvo.

RotaOrigem da definiçãoCódigo de sucesso
POST /api/event-criterias/preview-from-bodyO corpo201
POST /api/event-criterias/:id/previewO filtro salvo201

Auth: Obrigatória — permissão event-criteria:view-sql em ambas as rotas

Diferente de Validar, que faz um dry-run, pré-visualizar executa a consulta: consome cota do BigQuery e seu custo aparece em bytesProcessed.


POST /api/event-criterias/preview-from-body

Corpo da requisição

CampoTipoObrigatórioDescrição
queryBlocksQueryBlockDto[]SimMínimo 1 elemento. A definição a executar.
limitnumberNãoTamanho da amostra. Inteiro entre 1 e 500. Padrão 100.

A estrutura de cada bloco está em Definição.

Este endpoint recebe apenas a definição e o limit: name, description e format não fazem parte do corpo e enviá-los produz um 400 por propriedade desconhecida.

Exemplo

curl -X POST https://api.reten.ai/api/event-criterias/preview-from-body \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "limit": 50,
    "queryBlocks": [
      {
        "order": 0,
        "from": { "table": "event_transactions", "joins": [] },
        "select": {
          "distinct": true,
          "items": [
            { "kind": "column", "column": { "table": "event_transactions", "column": "event_id" } },
            { "kind": "column", "column": { "table": "event_transactions", "column": "event_date" } }
          ]
        },
        "timeWindow": {
          "timeOperator": "IN_THE_LAST",
          "reference": { "table": "event_transactions", "column": "event_date" },
          "unit": "DAYS",
          "value": 30
        },
        "where": {
          "kind": "group",
          "logicalOperator": "AND",
          "children": [
            {
              "kind": "predicate",
              "column": { "table": "event_transactions", "column": "status" },
              "comparisonOperator": "EQUALS",
              "value": "Facturada"
            }
          ]
        }
      }
    ]
  }'
import axios from 'axios';

const body = {
  limit: 50,
  queryBlocks: [
    {
      order: 0,
      from: { table: 'event_transactions', joins: [] },
      select: {
        distinct: true,
        items: [
          { kind: 'column', column: { table: 'event_transactions', column: 'event_id' } },
          { kind: 'column', column: { table: 'event_transactions', column: 'event_date' } },
        ],
      },
      timeWindow: {
        timeOperator: 'IN_THE_LAST',
        reference: { table: 'event_transactions', column: 'event_date' },
        unit: 'DAYS',
        value: 30,
      },
      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/preview-from-body',
  body,
  { headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);
const { rows, totalCount, bytesProcessed } = response.data;

POST /api/event-criterias/:id/preview

Executa um filtro já salvo. A definição é lida do filtro e validada antes de executá-la.

Parâmetros de rota

ParâmetroTipoDescrição
idUUIDID do filtro de eventos.

Corpo da requisição

CampoTipoObrigatórioDescrição
limitnumberNãoTamanho da amostra. Inteiro entre 1 e 500. Padrão 100.

O corpo não leva a definição: o filtro salvo é a definição. Enviar queryBlocks produz um 400 por propriedade desconhecida.

Exemplo

curl -X POST https://api.reten.ai/api/event-criterias/6d2a9c41-7e35-48b0-b1c9-0f8e7d6c5b4a/preview \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{ "limit": 50 }'
import axios from 'axios';

const id = '6d2a9c41-7e35-48b0-b1c9-0f8e7d6c5b4a';
const response = await axios.post(
  `https://api.reten.ai/api/event-criterias/${id}/preview`,
  { limit: 50 },
  { headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);
const { rows, totalCount, bytesProcessed } = response.data;

limit — tamanho da amostra

limit limita apenas quantas linhas a resposta traz em rows (a amostra), não o universo que o filtro seleciona.

  • Intervalo: inteiro 1..500 (menor que 1 ou maior que 500 ⇒ 400).
  • Padrão: 100 quando omitido.

Pré-visualizar executa duas consultas sobre a mesma definição: um SELECT … LIMIT <limit> para a amostra e um SELECT COUNT(*) para o total. Por isso você pode ver rows.length = 50 com totalCount = 4821: rows é um vislumbre, totalCount é a quantidade real de linhas que o filtro seleciona.

Resposta

Status 201 Created em ambas as rotas.

CampoTipoDescrição
rowsRecord<string, unknown>[]Amostra de linhas reais, limitada por limit. As colunas dependem do select da definição (e de seus aliases); por isso rows não tem uma forma fixa.
totalCountnumberTotal de linhas que o filtro seleciona, não limitado por limit.
bytesProcessednumberBytes processados pelo BigQuery na execução. Soma os bytes de ambas as consultas (amostra + contagem).

Exemplo

Resposta 201 ao exemplo acima (limit: 50). O filtro seleciona 4821 eventos; rows mostra os primeiros 50 (aqui reduzidos a 3 por brevidade), cada um com as colunas projetadas:

{
  "rows": [
    { "event_id": "evt_9f3a1c", "event_date": { "value": "2026-07-14T18:02:11.000Z" } },
    { "event_id": "evt_2b7e04", "event_date": { "value": "2026-07-14T17:45:03.000Z" } },
    { "event_id": "evt_c081ff", "event_date": { "value": "2026-07-13T09:21:58.000Z" } }
  ],
  "totalCount": 4821,
  "bytesProcessed": 5242880
}

As chaves de cada objeto em rows (event_id, event_date) vêm do select da definição: outra definição produz outras colunas.

Uma coluna TIMESTAMP não chega como string: chega envolvida em { "value": "<ISO 8601>" }. A data ISO está em row.event_date.value, não em row.event_date. Os demais tipos do catálogo chegam como escalares JSON.

Regras de validação

Antes de executar, a definição passa pelas duas camadas de validação. A validação de negócio roda em ambas as rotas: preview-from-body valida a definição do corpo, e :id/preview valida o filtro salvo antes de executá-lo.

O catálogo completo de regras e suas mensagens exatas está em Definição → Regras de validação.

Se a definição passar pelas duas camadas mas a execução no BigQuery falhar —por exceder o limite de bytes faturáveis (10 GB), esgotar o timeout de 30 s, ou qualquer outro erro do motor— a resposta também é 400, com um message no formato Query execution failed: <detail>.

Respostas de erro

StatusDescrição
400DTO inválido (limit fora de 1..500, tipo incorreto, enum fora do intervalo, propriedade desconhecida), uma regra de negócio violada, ou uma falha de execução no BigQuery (Query execution failed: …). Em :id/preview, também se o id não for um UUID válido.
401O Authorization: Bearer está ausente ou é inválido.
403O usuário não tem a permissão event-criteria:view-sql, ou o x-tenant-id não está autorizado.
404Em :id/preview, não existe um filtro de eventos com esse id no tenant (Event criteria not found). Em ambas as rotas, se o tenant não tiver dataset configurado.