Reten Docs
Audiências

Criar Audience Criteria

Crie um critério de audiência a partir de sua definição completa (blocos de consulta, filtros, janela temporal, agregações e composições).

POST /api/audience-criterias

Cria um Audience Criteria a partir de sua definição completa. É o endpoint central do recurso: recebe toda a árvore da definição —blocos de consulta, projeção, filtros, janela temporal, cruzamentos, agregações e composições com outras audiências— e a persiste. A operação é transacional: o critério, seus query blocks e suas composições são criados juntos, ou nada é criado.

Auth: Obrigatória — permissão audience-criteria:create

Corpo da requisição

Nível raiz (CreateAudienceCriteriaDto):

CampoTipoObrigatórioDescrição
namestringSimNome do critério. Não pode ser vazio.
descriptionstringNãoDescrição de texto livre. Se omitida, a resposta a retorna como null.
queryBlocksQueryBlockDto[]SimMínimo 1 elemento. Cada bloco ≈ um statement SQL completo.
composedWithCreateCompositionDto[]NãoCompõe este critério com outras audiências via operações de conjunto.

queryBlocks[] — bloco de consulta

Cada elemento de queryBlocks (QueryBlockDto) é um statement SQL completo:

CampoTipoObrigatórioDescrição
ordernumber (inteiro)SimPosição do bloco; inteiro ≥ 0.
setOperatorSetOperatorEnumNãoCombina este bloco com o anterior. Ausente no primeiro bloco; obrigatório nos demais (ver regras).
fromFromDtoSimFonte de dados: tabela principal + joins.
selectSelectDtoSimProjeção (colunas e/ou agregações).
timeWindowTimeWindowDtoNãoJanela temporal do bloco (união discriminada por timeOperator).
whereWhereDtoSimÁrvore de predicados. Obrigatório mesmo que seja um grupo vazio.
groupByColumnRefDto[]NãoColunas de agrupamento.
havingHavingDtoNãoFiltro sobre agregados.

O setOperator de um query block combina blocos dentro do mesmo critério; não deve ser confundido com o setOperator de uma composição, que combina critérios inteiros. São dois níveis distintos de operação de conjunto.

ColumnRefDto — referência a coluna

Usado em toda a árvore (select, filtros, group by, joins, agregados, janela temporal):

CampoTipoObrigatórioDescrição
tablestringSimTabela do catálogo. Não vazio.
columnstringSimColuna. Não vazio. Pode ser um caminho STRUCT (ex.: "pricing.final_amount").

Toda coluna é sempre qualificada com sua table para evitar ambiguidade.

from — fonte de dados (FromDto)

CampoTipoObrigatórioDescrição
tablestringSimTabela principal do catálogo. Não vazio.
joinsJoinDto[]NãoCruzamentos com outras tabelas. Padrão [].
unnestsColumnRefDto[]NãoColunas repetidas declaradas como fonte de linhas (uma linha por elemento). Uma audiência não as aceita: omita o campo ou envie [] (o padrão); uma lista não vazia retorna 400.

Cada JoinDto:

CampoTipoObrigatórioDescrição
typeJoinTypeEnumSimINNER | LEFT | RIGHT | FULL.
tablestringSimTabela a unir (do catálogo). Não vazio.
onJoinPredicateDto[]SimCondições de junção.

Cada JoinPredicateDto é um par de colunas: { left: ColumnRefDto, right: ColumnRefDto }.

select — projeção (SelectDto)

CampoTipoObrigatórioDescrição
distinctbooleanSimAplica SELECT DISTINCT.
items(SelectColumnItem | SelectAggregateItem)[]SimNão vazio. União discriminada pelo campo kind.

Os items são discriminados por kind:

  • Coluna — kind: "column":

    CampoTipoObrigatórioDescrição
    kind"column"SimDiscriminador.
    columnColumnRefDtoSimColuna projetada.
    aliasstringNãoDeve corresponder a ^[A-Za-z_][A-Za-z0-9_]*$.
  • Agregado — kind: "aggregate":

    CampoTipoObrigatórioDescrição
    kind"aggregate"SimDiscriminador.
    aggregateAggregateDtoSimExpressão de agregação.
    aliasstringSimAqui o alias é obrigatório. Mesmo regex de identificador.

AggregateDto:

CampoTipoObrigatórioDescrição
aggregationOperatorAggregationOperatorEnumSimCOUNT | SUM | AVG | MIN | MAX.
operandobjectSimO que é agregado. União discriminada por kind: column, star ou arithmetic (veja abaixo).
distinctbooleanNãoAplica DISTINCT dentro do agregado.

operand —o que é agregado— é discriminado por kind:

kindCampos adicionaisSignificado
columncolumn: ColumnRefDtoUma coluna do catálogo.
star(nenhum)*: conta linhas. Só é válido com COUNT e sem distinct (COUNT(DISTINCT *) não é permitido).
arithmeticarithmeticOperator: ArithmeticOperatorEnum, left, rightExpressão binária. Cada lado é outro operando: uma column ou um arithmetic aninhado (nunca star).

ArithmeticOperatorEnum: ADD | SUBTRACT | MULTIPLY | SAFE_DIVIDE (uma divisão que retorna NULL quando o denominador é zero, em vez de fazer a consulta falhar). As colunas de uma expressão aritmética precisam ser numéricas (INT64, NUMERIC, BIGNUMERIC, FLOAT64), e as expressões se aninham até 3 níveis de arithmetic, contando o externo.

where — árvore de predicados (WhereDto)

O where é uma árvore recursiva. O nó raiz é sempre um grupo, e suas folhas são de dois tipos:

kindO que filtra
groupNão é uma folha: agrupa filhos com AND / OR. Os grupos podem ser aninhados.
predicateUma coluna escalar de uma tabela do from.
recordPredicateUma coluna RECORD REPEATED: pelo menos 1 elemento satisfaz o sub-filtro.
Grupo — kind: "group"
CampoTipoObrigatórioDescrição
kind"group"SimDiscriminador.
logicalOperatorLogicalOperatorEnum (AND | OR)SimConectivo entre os filhos.
children(Group | Leaf)[]SimFilhos do grupo; podem ser grupos aninhados.

logicalOperator é sempre obrigatório em um grupo, mas só tem efeito com 2 ou mais filhos. Com menos de 2 filhos seu valor é irrelevante (gera o mesmo SQL), mas ainda assim deve ser enviado. Um where sem filtros é expresso como um grupo vazio: { "kind": "group", "logicalOperator": "AND", "children": [] }.

Folha de coluna — kind: "predicate"

Compara uma coluna escalar qualificada por sua tabela.

CampoTipoObrigatórioDescrição
kind"predicate"SimDiscriminador.
columnColumnRefDtoSimColuna do predicado.
comparisonOperatorComparisonOperatorEnumSimOperador de comparação.
valuePredicateValueDependeSeu formato depende do operador.
{
  "kind": "predicate",
  "column": { "table": "user_properties", "column": "country" },
  "comparisonOperator": "IN",
  "value": ["CL", "MX"]
}
Folha de registro — kind: "recordPredicate"

Filtra por uma coluna RECORD REPEATED (um array de structs, como attributes). Significa que pelo menos um elemento do array satisfaz o sub-filtro.

CampoTipoObrigatórioDescrição
kind"recordPredicate"SimDiscriminador.
columnColumnRefDtoSimColuna RECORD REPEATED de uma tabela do from.
subWhereSub-árvore relativaSimCondições sobre os sub-campos do elemento. Não pode ficar vazio.
{
  "kind": "recordPredicate",
  "column": { "table": "event_transactions", "column": "attributes" },
  "subWhere": {
    "kind": "group",
    "logicalOperator": "AND",
    "children": [
      { "kind": "predicate", "field": "key", "comparisonOperator": "EQUALS", "value": "canal" },
      { "kind": "predicate", "field": "value", "comparisonOperator": "EQUALS", "value": "web" }
    ]
  }
}

As condições do subWhere são avaliadas sobre um mesmo elemento do array, e não sobre o array inteiro. O exemplo acima seleciona linhas que têm um atributo cujo key é canal e cujo value é web — não linhas que têm um atributo com esse key e outro, diferente, com esse value.

Quais colunas aceitam um filtro de registro é informado pelo catálogo: as que vêm com kind: "record".

Sub-árvore relativa

O subWhere é um grupo AND/OR cujas folhas são resolvidas contra os sub-campos que o registro declara.

Há uma única diferença em relação à árvore de nível superior, e ela é a origem mais comum de erros:

Dentro de uma sub-árvore relativa os operandos não levam tabela: você escreve "field": "key", e não "column": { "table": "attributes", "column": "key" }. A folha usa a chave field (uma string), não column.

Folhas permitidas dentro de uma sub-árvore relativa:

  • Folha escalar — { "kind": "predicate", "field": string, "comparisonOperator": …, "value"?: … }. O field deve ser um sub-campo escalar do registro.
  • Registro aninhado — { "kind": "recordPredicate", "field": string, "subWhere": … }. Um registro dentro de outro registro; aninha sem limite declarado, desde que o catálogo declare cada nível.
  • Grupo — o mesmo formato de grupo, para combinar as folhas anteriores com AND/OR.
Formato de value conforme comparisonOperator
OperadoresFormato de valueExemplo
IS_NULL, IS_NOT_NULLSem value (omitido)(omitido)
IN, NOT_INLista não vazia ScalarValue[]["CL", "MX"]
BETWEENPar [min, max][10, 20]
O resto (EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, CONTAINS, NOT_CONTAINS, STARTS_WITH, ENDS_WITH)Escalar único"activo" · 42

ScalarValue = string | number | boolean. Além disso, cada operador deve ser compatível com o tipo da coluna (ver regras de validação).

groupBy — colunas de agrupamento

Lista opcional de ColumnRefDto[]. Quando o bloco agrega (declara groupBy ou tem um agregado no select), o groupBy deve corresponder exatamente às colunas não agregadas do select (ver regras de validação).

having — filtro sobre agregados (HavingDto)

Mesma estrutura recursiva que where (grupos AND/OR aninhados e mesma regra de value por operador), mas a folha opera sobre um agregado, não sobre uma coluna:

  • Predicado (folha) — { kind: "predicate", aggregate: AggregateDto, comparisonOperator: ComparisonOperatorEnum, value?: PredicateValue }.
  • Grupo — idêntico ao de where.

timeWindow — janela temporal (TimeWindowDto)

União discriminada por timeOperator. Restringe o bloco a um período de tempo sobre uma coluna TIMESTAMP do catálogo (reference). É um campo irmão do where, não um nó da árvore de filtros.

timeOperatorCampos adicionais
ALL_TIME(nenhum) — sem restrição de tempo.
IN_THE_LASTreference: ColumnRefDto, unit: TimeUnitEnum, value: inteiro > 0
IN_THE_FIRSTreference: ColumnRefDto, unit: TimeUnitEnum, value: inteiro > 0
SINCEreference: ColumnRefDto, from: string (YYYY-MM-DD)
BETWEENreference: ColumnRefDto, from: string (YYYY-MM-DD), to: string (YYYY-MM-DD)

TimeUnitEnum: DAYS | WEEKS | MONTHS | YEARS.

Semântica de negócio de cada operador:

  • ALL_TIME — sem janela; considera todo o histórico.
  • IN_THE_LAST — janela rolante relativa a "agora": os últimos value unit (ex.: últimos 30 DAYS). Recalculada a cada execução.
  • IN_THE_FIRST — janela relativa à origem do ciclo de vida do usuário (atualmente, sua data de cadastro): os primeiros value unit de vida de cada usuário. É ancorada por usuário, não a uma data fixa.
  • SINCE — a partir da data civil from (inclusive).
  • BETWEEN — entre from e to, ambas as datas civis inclusivas de seu dia completo.

As datas civis YYYY-MM-DD (SINCE, BETWEEN) são resolvidas para o início do dia no fuso horário do tenant. O detalhe de fuso horário é interno; basta enviar a data civil.

composedWith[] — composição com outras audiências

Cada elemento (CreateCompositionDto) combina este critério com outra audiência via uma operação de conjunto:

CampoTipoObrigatórioDescrição
operandCriteriaIdstring (UUID)SimId da outra audiência (operando). Deve existir.
setOperatorSetOperatorEnumSimUNION_DISTINCT | UNION_ALL | INTERSECT_DISTINCT.

Regras de validação

A requisição passa por duas camadas de validação, ambas retornando 400 Bad Request:

  1. Validação do DTO (estrutura, tipos, enums, campos obrigatórios). Nesse caso message é um array de strings e propriedades desconhecidas são rejeitadas.
  2. Validação de negócio (o critério deve gerar SQL válido e coerente com o catálogo). Nesse caso message é uma string única com a mensagem da regra violada. A validação de negócio para no primeiro invariante violado.

Regras de negócio verificadas (todas retornam 400, com a mensagem exata da API):

RegraMensagem
A tabela deve pertencer ao catálogo.Table "<t>" is not in the catalog
Cada (table, column) deve pertencer ao catálogo.Column "<t>.<c>" is not in the catalog
Uma coluna repetida não pode ser usada fora de um filtro de registro.La columna "<t>.<c>" es una columna repetida y no puede usarse en <contexto>
Uma folha de coluna exige uma coluna escalar.La columna "<t>.<c>" es una columna repetida: no admite un filtro de columna
Um filtro de registro exige uma coluna repetida.La columna "<t>.<c>" no es una columna repetida: no admite un filtro de registro
O sub-campo de um filtro de registro deve existir no registro.El sub-campo "<f>" no existe en el registro
Uma folha escalar da sub-árvore não pode apontar para um sub-campo repetido.El sub-campo "<f>" es una columna repetida: usá un filtro de registro anidado
Um registro aninhado exige um sub-campo repetido.El sub-campo "<f>" no es una columna repetida
A sub-árvore de um filtro de registro não pode ficar vazia.Un filtro de registro no puede quedar sin condiciones
Uma folha da árvore deve declarar seu operando.Una hoja del filtro no declara una columna
O operando star (*) só é válido com COUNT.'*' is only valid with COUNT, not <op>
COUNT(DISTINCT *) não é permitido.COUNT(DISTINCT *) is not allowed
star não pode ser lado de uma expressão aritmética.'*' sólo vale como operando directo de COUNT, no como lado de una expresión aritmética
As colunas de uma expressão aritmética precisam ser numéricas.El operando "<t>.<c>" es de tipo <type>; una expresión aritmética sólo admite operandos numéricos (INT64, NUMERIC, BIGNUMERIC, FLOAT64)
Uma expressão aritmética se aninha até no máximo 3 níveis.La expresión aritmética supera la profundidad máxima de 3 niveles
Toda coluna referenciada deve pertencer a uma tabela do from (principal ∪ joins).Column "<t>.<c>" references a table that is not in the query block FROM
Ao agregar, toda coluna não agregada do select deve estar no groupBy.Column "<t>.<c>" must appear in GROUP BY when the operation aggregates
Toda coluna do groupBy deve ser uma coluna não agregada do select.Column "<t>.<c>" in GROUP BY must be a non-aggregated column of the SELECT
having exige um contexto de agregação (groupBy ou um agregado no select).HAVING requires an aggregation context (GROUP BY or an aggregate in the SELECT)
O critério deve projetar sua coluna de identidade (ex.: user_id) como coluna.Criteria requires at least one operation that selects its identity column (e.g. user_id)
O primeiro bloco (order=0) não leva setOperator.First operation (order=0) must not have a setOperator
Todo bloco posterior (order>0) deve levar setOperator.Operation with order=<n> must have a setOperator
O operador deve ser compatível com o tipo da coluna/agregado.Operator <op> is not allowed for <type> operands
Operador escalar com value ausente ou uma lista.Operator <op> requires a single value
IN/NOT_IN com value que não é lista ou está vazio.Operator <op> requires a non-empty list of values
BETWEEN sem exatamente dois valores.Operator <op> requires exactly two values
A reference do timeWindow deve estar no catálogo.timeWindow reference "<t>.<c>" is not in the catalog
A reference do timeWindow deve ser uma coluna TIMESTAMP.timeWindow reference "<t>.<c>" must be a TIMESTAMP column
A reference do timeWindow não pode ser uma coluna repetida.La referencia temporal "<t>.<c>" es una columna repetida y no puede anclar una ventana de tiempo
O value do timeWindow deve ser um inteiro positivo.timeWindow value must be a positive integer
Em timeWindow BETWEEN, from deve ser anterior ou igual a to.timeWindow BETWEEN requires "from" to be on or before "to"
As datas do timeWindow devem ser datas de calendário válidas.timeWindow date "<d>" is not a valid calendar date

Regras específicas de composedWith (também 400):

RegraMensagem
Um critério não pode referenciar a si mesmo.An audience criteria cannot reference itself
O operando deve existir.Operand audience criteria <id> not found or deleted
Não são permitidas referências circulares entre critérios.Circular reference detected

Exemplo

Audiência de usuários que nos últimos 90 dias completaram transações de valor superior a 100000, cruzando event_transactions com user_properties para filtrar por país, e intersectada com outra audiência existente que também projeta apenas user_id.

curl -X POST https://api.reten.ai/api/audience-criterias \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Compradores VIP (últimos 90 días)",
    "queryBlocks": [
      {
        "order": 0,
        "from": {
          "table": "event_transactions",
          "joins": [
            {
              "type": "INNER",
              "table": "user_properties",
              "on": [
                {
                  "left":  { "table": "event_transactions", "column": "user_id" },
                  "right": { "table": "user_properties", "column": "user_id" }
                }
              ]
            }
          ]
        },
        "select": {
          "distinct": false,
          "items": [
            { "kind": "column", "column": { "table": "event_transactions", "column": "user_id" } }
          ]
        },
        "timeWindow": {
          "timeOperator": "IN_THE_LAST",
          "reference": { "table": "event_transactions", "column": "event_date" },
          "unit": "DAYS",
          "value": 90
        },
        "where": {
          "kind": "group",
          "logicalOperator": "AND",
          "children": [
            {
              "kind": "predicate",
              "column": { "table": "event_transactions", "column": "status" },
              "comparisonOperator": "EQUALS",
              "value": "completed"
            },
            {
              "kind": "predicate",
              "column": { "table": "user_properties", "column": "country" },
              "comparisonOperator": "IN",
              "value": ["CL", "MX"]
            }
          ]
        },
        "groupBy": [
          { "table": "event_transactions", "column": "user_id" }
        ],
        "having": {
          "kind": "group",
          "logicalOperator": "AND",
          "children": [
            {
              "kind": "predicate",
              "aggregate": {
                "aggregationOperator": "SUM",
                "operand": { "kind": "column", "column": { "table": "event_transactions", "column": "pricing.final_amount" } }
              },
              "comparisonOperator": "GREATER_THAN",
              "value": 100000
            }
          ]
        }
      }
    ],
    "composedWith": [
      {
        "operandCriteriaId": "b2c3d4e5-6789-4abc-9def-0123456789ab",
        "setOperator": "INTERSECT_DISTINCT"
      }
    ]
  }'
import axios from 'axios';

const body = {
  name: 'Compradores VIP (últimos 90 días)',
  queryBlocks: [
    {
      order: 0,
      from: {
        table: 'event_transactions',
        joins: [
          {
            type: 'INNER',
            table: 'user_properties',
            on: [
              {
                left: { table: 'event_transactions', column: 'user_id' },
                right: { table: 'user_properties', column: 'user_id' },
              },
            ],
          },
        ],
      },
      select: {
        distinct: false,
        items: [
          { kind: 'column', column: { table: 'event_transactions', column: 'user_id' } },
        ],
      },
      timeWindow: {
        timeOperator: 'IN_THE_LAST',
        reference: { table: 'event_transactions', column: 'event_date' },
        unit: 'DAYS',
        value: 90,
      },
      where: {
        kind: 'group',
        logicalOperator: 'AND',
        children: [
          {
            kind: 'predicate',
            column: { table: 'event_transactions', column: 'status' },
            comparisonOperator: 'EQUALS',
            value: 'completed',
          },
          {
            kind: 'predicate',
            column: { table: 'user_properties', column: 'country' },
            comparisonOperator: 'IN',
            value: ['CL', 'MX'],
          },
        ],
      },
      groupBy: [{ table: 'event_transactions', column: 'user_id' }],
      having: {
        kind: 'group',
        logicalOperator: 'AND',
        children: [
          {
            kind: 'predicate',
            aggregate: {
              aggregationOperator: 'SUM',
              operand: { kind: 'column', column: { table: 'event_transactions', column: 'pricing.final_amount' } },
            },
            comparisonOperator: 'GREATER_THAN',
            value: 100000,
          },
        ],
      },
    },
  ],
  composedWith: [
    {
      operandCriteriaId: 'b2c3d4e5-6789-4abc-9def-0123456789ab',
      setOperator: 'INTERSECT_DISTINCT',
    },
  ],
};

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

Resposta 201 Created

Retorna o critério criado como IAudienceCriteriaDetail — a mesma forma que GET /audience-criterias/:id. É o recurso base mais a árvore completa: queryBlocks[] (com seu id e order já resolvidos, ordenados por order ascendente) e compositions[] (com id e operandCriteriaName).

Campos base (IAudienceCriteria) — todos camelCase; os instantes são serializados em ISO 8601:

CampoTipoDescrição
idstring (UUID)Id do critério criado.
projectIdstring (UUID)Projeto ao qual o critério pertence.
namestring
descriptionstring | nullnull se não enviado.
isActivebooleanOs critérios são criados ativos (true).
isRootbooleantrue apenas para a audiência raiz do projeto (veja Projetos).
ownerIdstring (UUID)Usuário criador.
updatedBystring (UUID)Último editor (na criação, o criador).
createdAtstring (ISO 8601)
updatedAtstring (ISO 8601)

Relações aninhadas:

  • queryBlocks[] — cada bloco adiciona seu id (UUID) e retorna a árvore exatamente como foi enviada (from, select, timeWindow, where, groupBy, having). Campos opcionais ausentes são retornados como null (setOperator, timeWindow, groupBy, having) e from.joins como [] se não havia joins; from.unnests vem sempre como [].
  • compositions[] — cada composição: id (UUID), operandCriteriaId, operandCriteriaName (nome do operando resolvido; "" se não resolver) e setOperator.
{
  "id": "a1b2c3d4-5678-4abc-9def-1234567890ab",
  "projectId": "3f6c2b1a-8d4e-4f7a-9b2c-5e1d0a7f6c34",
  "name": "Compradores VIP (últimos 90 días)",
  "description": null,
  "isActive": true,
  "isRoot": false,
  "ownerId": "0f0e0d0c-0b0a-4090-8070-605040302010",
  "updatedBy": "0f0e0d0c-0b0a-4090-8070-605040302010",
  "createdAt": "2026-07-15T14:32:07.481Z",
  "updatedAt": "2026-07-15T14:32:07.481Z",
  "queryBlocks": [
    {
      "id": "c3d4e5f6-7890-4abc-9def-34567890abcd",
      "order": 0,
      "setOperator": null,
      "from": {
        "table": "event_transactions",
        "joins": [
          {
            "type": "INNER",
            "table": "user_properties",
            "on": [
              {
                "left":  { "table": "event_transactions", "column": "user_id" },
                "right": { "table": "user_properties", "column": "user_id" }
              }
            ]
          }
        ],
        "unnests": []
      },
      "select": {
        "distinct": false,
        "items": [
          { "kind": "column", "column": { "table": "event_transactions", "column": "user_id" } }
        ]
      },
      "timeWindow": {
        "timeOperator": "IN_THE_LAST",
        "reference": { "table": "event_transactions", "column": "event_date" },
        "unit": "DAYS",
        "value": 90
      },
      "where": {
        "kind": "group",
        "logicalOperator": "AND",
        "children": [
          {
            "kind": "predicate",
            "column": { "table": "event_transactions", "column": "status" },
            "comparisonOperator": "EQUALS",
            "value": "completed"
          },
          {
            "kind": "predicate",
            "column": { "table": "user_properties", "column": "country" },
            "comparisonOperator": "IN",
            "value": ["CL", "MX"]
          }
        ]
      },
      "groupBy": [
        { "table": "event_transactions", "column": "user_id" }
      ],
      "having": {
        "kind": "group",
        "logicalOperator": "AND",
        "children": [
          {
            "kind": "predicate",
            "aggregate": {
              "aggregationOperator": "SUM",
              "operand": { "kind": "column", "column": { "table": "event_transactions", "column": "pricing.final_amount" } }
            },
            "comparisonOperator": "GREATER_THAN",
            "value": 100000
          }
        ]
      }
    }
  ],
  "compositions": [
    {
      "id": "d4e5f6a7-8901-4abc-9def-4567890abcde",
      "operandCriteriaId": "b2c3d4e5-6789-4abc-9def-0123456789ab",
      "operandCriteriaName": "Usuarios activos",
      "setOperator": "INTERSECT_DISTINCT"
    }
  ]
}

Respostas de erro

StatusDescrição
400DTO inválido (campo faltante, tipo incorreto, enum fora do intervalo, propriedade desconhecida) ou uma regra de negócio violada (ver regras de validação).
401Authorization: Bearer ausente ou inválido.
403O usuário não tem a permissão audience-criteria:create, ou o x-tenant-id não está autorizado.