# Sintaxis para expresiones La expresión de una [condición](/es/rules/conditions/) sigue una sintaxis sencilla, inspirada en fórmulas de planillas. Siempre resulta en verdadero o falso, y está compuesta por, como mínimo, una **variable**, una **operación** y un **valor**. ``` $merchant_id == "XYZ" ``` La expresión anterior es verdadera cuando el campo `merchant_id` del evento es igual a `"XYZ"`. ## Los tres prefijos Toda variable comienza con un símbolo que indica **de dónde viene el valor** y **cuánto tiempo dura**: | Prefijo | Contiene | Duración | | :------------- | :---------------------------------------------- | :------------------------------------------ | | `$campo` | un campo del evento | persistido con el evento | | `@lista` | una lista de valores de la cuenta | mantenida por la cuenta, entre eventos | | `%temporal` | un valor calculado durante esta ejecución | solo existe durante la ejecución de la regla | ## Campos del evento (`$`) Las variables disponibles son exactamente los **campos del tipo de evento** al que pertenece la regla; no existe una lista fija. Si el tipo de evento tiene un campo `amount`, la regla puede usar `$amount`; un tipo de evento diferente tendrá otro conjunto de variables. El panel ofrece los campos disponibles mientras usted escribe la condición y resalta la expresión a medida que se escribe. Los campos que comienzan con `_` están reservados por la plataforma y no quedan disponibles para su uso en expresiones. Además de los campos del tipo de evento, `$id` contiene el identificador del evento informado en `POST /events`, y puede usarse en las condiciones y como dimensión de un [análisis](/es/rules/analyses/). El tipo del campo determina cómo se compara el valor: | Tipo del campo | Ejemplo de comparación | | :------------- | :------------------------------------- | | Texto | `$status == "approved"` | | Entero | `$installments > 6` | | Decimal | `$amount >= 1500.00` | | Booleano | `$is_first_purchase == true` | | Fecha y hora | `$signup_at > "30 days ago"` | Un campo que no vino en el evento se trata como vacío. Para probar esa ausencia, compárelo con `null`, sin comillas: ``` $device_fingerprint_id == null ``` La expresión anterior es verdadera cuando el evento no trajo fingerprint del dispositivo. Use `!=` para el caso contrario. ## Operaciones | Operación | Significado | | :-------- | :------------------------------ | | `==` | Igualdad | | `!=` | Desigualdad | | `>` | Mayor que | | `>=` | Mayor o igual | | `<` | Menor que | | `<=` | Menor o igual | | `in` | Pertenece a una colección | | `not in` | No pertenece a una colección | | `any in` | Al menos uno de los valores pertenece a una colección | | `all in` | Todos los valores pertenecen a una colección | ## Valores El valor comparado con una variable puede ser un texto, un número o un booleano: - **Texto**: siempre entre comillas dobles, como `"XYZ"`. No se aceptan comillas simples ni textos sin comillas. - **Número**: sin comillas, con punto como separador decimal, como `1000` o `99.01`. - **Booleano**: `true` o `false`, sin comillas. Como todo texto va entre comillas dobles, valores como una IP, una fecha o una palabra usada en la propia sintaxis (por ejemplo, `in`) también necesitan las comillas para ser tratados como texto. ### Fechas Los campos de fecha y hora aceptan valores relativos y absolutos, siempre entre comillas: ``` $signup_at > "30 days ago" $signup_at == "2026-03-15" ``` El formato relativo es `[número] [hour|day|week|month|year]s ago`. El formato absoluto acepta año (`"2026"`), año y mes (`"2026-03"`) o fecha completa (`"2026-03-15"`); en los dos primeros casos, la comparación cubre todo el período. ## Combinando expresiones Use `and` y `or` para combinar expresiones. `and` tiene precedencia sobre `or`: en una combinación sin paréntesis, las partes unidas por `and` se evalúan primero. Así, `A and B or C` equivale a `(A and B) or C`. Use paréntesis para agrupar expresiones y alterar esa precedencia: ``` ($amount > 1000 and $user_email_domain == "gmail.com") or $issuer_country != "BR" ``` Un salto de línea funciona como un espacio entre los términos. Una combinación larga puede distribuirse en varias líneas para facilitar la lectura, sin alterar el resultado: ``` ($amount > 1000 and $user_email_domain == "gmail.com") or $issuer_country != "BR" ``` ## `true` y `false` como condición entera Una expresión puede consistir solo en `true` o `false`, sin variable ni comparación. `true` es siempre verdadera y mantiene la condición siempre activa; `false` es siempre falsa y desactiva la condición sin eliminarla. Difiere de la comparación de un campo booleano con `true` o `false`, descrita en [Valores](#valores): en ese caso el literal está a la derecha de una comparación; como condición entera, constituye la expresión por completo. ## Colecciones (`@`) Las [listas](/es/rules/lists/) de la cuenta quedan disponibles como colecciones, identificadas por el prefijo `@`. Por ejemplo, para verificar si un cliente está en una lista de cuarentena: ``` $user_id in @clientes_cuarentena ``` También es posible escribir la colección directamente en la expresión, entre corchetes y con los valores separados por coma: ``` $issuer_country not in ["BR", "AR", "CL"] ``` Además del formato anterior, `in` y `not in` aceptan: - **un texto fijo a la izquierda**, para probar un valor conocido contra una colección: `"BR" in @paises_atendidos`; - **un campo en ambos lados**, para probar si el valor de un campo está contenido en el de otro: `$user_id in $allowed_users`. ### Probando varios valores a la vez Cuando el lado izquierdo es una colección escrita entre corchetes, hay que indicar **cuántos** de los valores necesitan pertenecer a la colección de la derecha: | Operación | Verdadera cuando | | :-------- | :--------------------------------------- | | `any in` | al menos uno de los valores pertenece | | `all in` | todos los valores pertenecen | | `not in` | ninguno de los valores pertenece | ``` ["susp_59", "susp_83"] any in %regla.triggered_cells ["BR", "AR"] all in @paises_atendidos ["tor", "vpn"] not in @tipos_permitidos ``` **No existe forma sin cuantificador**: escribir `["a", "b"] in @lista` es un error de escritura. "A y B están en la lista" es ambiguo entre "al menos uno" y "los dos", y una condición de riesgo no puede depender de cuál de las dos lecturas tenía en mente el autor. En la negación no hay ambigüedad, ya que "A y B no están en la lista" solo puede significar que ninguno de los dos está, y por eso `not in` no necesita cuantificador. Por el mismo motivo, `not any in` y `not all in` no se aceptan. La colección de la derecha puede ser una lista de la cuenta, una variable temporal de conjunto, un campo u otra colección literal. ## Variables temporales (`%`) Una variable temporal guarda un valor **calculado durante la ejecución de la regla**: una [acción](/es/rules/actions/) la produce y las condiciones siguientes pueden leerla. No se graba en el evento, no aparece en la respuesta de la API y no se reaprovecha en el evento siguiente: un valor que deba sobrevivir al evento debe grabarse en un campo. Las variables temporales existen en dos formas. **Valores simples**, definidos por una acción de definir variable temporal: ``` %revision_manual == "1" ``` **Resultados de un [análisis](/es/rules/analyses/)**, publicados por una acción de ejecutar análisis bajo el nombre del resultado, con atributos accedidos por punto: | Atributo | Contiene | Tipo | | :----------------- | :---------------------------------------------------- | :------- | | `score` | puntuación calculada por el análisis | Decimal | | `score_cell` | nombre de la celda que originó la puntuación | Texto | | `triggered` | si el análisis fue activado | Booleano | | `triggered_count` | cuántas celdas fueron activadas | Entero | | `triggered_cells` | nombres de las celdas activadas | Conjunto | ``` %bot.triggered_count >= 2 ``` El atributo `triggered_cells` es un **conjunto**, no un valor único: solo puede usarse a la derecha de una operación de pertenencia, para probar qué celdas fueron activadas. ``` "email_velocity" in %bot.triggered_cells ["susp_59", "susp_83"] any in %bot.triggered_cells ``` Compararlo con `==`, o usarlo en cualquier otra operación, es un error de escritura y la condición no se acepta. Un conjunto también puede guardarse en una variable temporal simple, mediante una [acción en modo expresión](/es/rules/actions/#valor-fijo-o-expresión), y sigue siendo un conjunto, comprobable de la misma manera. ## Funciones ### `concat` La función `concat` une varios valores en un único texto, que puede compararse con un valor. Cada argumento es un campo del evento (`$campo`), una [variable temporal](#variables-temporales-) (`%temporal`) o un texto fijo, separados por coma: ``` concat($user_id, "-", $merchant_id) == "cliente-1234-tienda-1234" concat($merchant_id, "-", %bot.score_cell) == "tienda-1234-email_velocity" ``` La primera expresión es verdadera cuando la combinación del ID del usuario y el ID del establecimiento, unidos por un guion, resulta en `"cliente-1234-tienda-1234"`. Consideraciones sobre los valores unidos: - Las variables sin valor se tratan como texto vacío. - Los valores numéricos se convierten a texto en su forma original (por ejemplo, `99.01` y `0.9`). - Un conjunto, como `%bot.triggered_cells`, no puede entrar en un `concat`: solo puede probarse con una operación de pertenencia. El resultado de `concat` también acepta `in` y `not in`, lo que permite comparar la combinación contra una lista: ``` concat($user_id, "-", $merchant_id) in @pares_bloqueados ``` ## Errores de escritura La expresión se valida en el momento en que se guarda la condición. La regla no se publica mientras haya un error, y el panel señala el problema. Los casos más comunes: - **campo inexistente**: la variable no corresponde a ningún campo del tipo de evento vinculado a la regla; - **tipo incompatible**: el valor comparado no tiene sentido para el tipo del campo, como comparar un campo numérico con `"aprobado"`; - **variable temporal desconocida**: el nombre o el atributo no es producido por ninguna acción de la regla; - **variable temporal leída demasiado pronto**: ninguna condición anterior la produce. Como las condiciones se evalúan en orden, el productor debe venir antes que el lector; - **texto sin comillas**: los valores de texto necesitan comillas dobles. Cada expresión tiene un límite de tamaño. Consulte [límites y parámetros](/es/limits/#reglas-y-listas).