# Referencia de funciones

Una función se llama así: `{{ nombre(argumento1, argumento2) }}`. Los argumentos son texto entre comillas, números, variables (`$nombre`) y, en las [expresiones](https://support.cleverapp.pro/es/chatbots/templates/expressions), los resultados de otras funciones.

Las funciones marcadas como **simples** funcionan en todos los lugares donde funcionan las plantillas. Las demás solo funcionan en los textos de los mensajes, en las condiciones y en la configuración de algunos bloques: consulta [Dónde funcionan las plantillas](https://support.cleverapp.pro/es/chatbots/templates/where).

## Texto

| Función | Qué hace | Ejemplo | Resultado |
|---|---|---|---|
| `upper(texto)` | Todas las letras en mayúsculas | `{{ upper("hola") }}` | `HOLA` |
| `lower(texto)` | Todas las letras en minúsculas | `{{ lower("HOLA") }}` | `hola` |
| `capitalize(texto)` | La primera letra en mayúscula | `{{ capitalize("anna") }}` | `Anna` |
| `len(texto)` | Número de caracteres | `{{ len("Viernes") }}` | `7` |
| `trim(texto)` | Quita los espacios de los dos extremos | `{{ trim("  sí ") }}` | `sí` |
| `replace(texto, qué, por)` | Sustituye todas las apariciones | `{{ replace("8-999-000", "-", "") }}` | `8999000` |
| `substr(texto, inicio, longitud)` | Una parte del texto; el inicio cuenta desde 0 | `{{ substr("Viernes", 0, 3) }}` | `Vie` |
| `number_format(número, decimales, separador_decimal, separador_de_miles)` | Un número con separadores. Por defecto: 0 decimales, coma y espacio | `{{ number_format(1234.5, 2) }}` | `1 234,50` |
| `urlencode(texto)` | Codifica el texto para un enlace | `https://site.com/?q={{ urlencode($busqueda) }}` | |
| `randomText(opción1, opción2, ...)` | Una opción al azar | `{{ randomText("Hola", "Buenas") }}` | |
| `strRandom(longitud, mayúsculas)` | Una cadena aleatoria de letras y dígitos, de hasta 1000 caracteres. Pasa `true` como segundo argumento para usar solo mayúsculas | `{{ strRandom(8, true) }}` | `K3JD8QWZ` |

Todas las funciones de esta sección son **simples**.

## Matemáticas

| Función | Qué hace | Ejemplo | Resultado |
|---|---|---|---|
| `round(número, decimales)` | Redondeo, por defecto a un número entero | `{{ round(2.567, 2) }}` | `2.57` |
| `ceil(número)` | Redondea hacia arriba | `{{ ceil(2.1) }}` | `3` |
| `floor(número)` | Redondea hacia abajo | `{{ floor(2.9) }}` | `2` |
| `abs(número)` | Valor absoluto | `{{ abs(-5) }}` | `5` |
| `sqrt(número)` | Raíz cuadrada | `{{ sqrt(16) }}` | `4` |
| `max(a, b, ...)` | El mayor | `{{ max(3, 7, 5) }}` | `7` |
| `min(a, b, ...)` | El menor | `{{ min(3, 7, 5) }}` | `3` |
| `rand(desde, hasta)` | Un número entero aleatorio | `{{ rand(1, 100) }}` | |

Todas las funciones de esta sección son **simples**. La suma, la resta, la multiplicación, la división y las potencias se escriben con operadores: consulta [Aritmética](https://support.cleverapp.pro/es/chatbots/templates/expressions#aritmética).

### Funciones obsoletas

Estas funciones siguen funcionando, pero en los textos nuevos usa operadores: es más corto y más claro.

| Función obsoleta | Cómo se escribe ahora |
|---|---|
| `sum($a, $b)`, `сумма($a, $b)` | `{{ $a + $b }}` |
| `diff($a, $b)`, `разность($a, $b)` | `{{ $a - $b }}` |
| `multiplication($a, $b)`, `произведение($a, $b)` | `{{ $a * $b }}` |
| `div($a, $b)`, `деление($a, $b)` | `{{ $a / $b }}` |
| `pow($a, $b)` | `{{ $a ** $b }}` |

Por ejemplo, en lugar de `{{ sum($precio, $envio) }}` escribe `{{ $precio + $envio }}`.

## Fecha y hora

> [!WARNING]
> La hora se calcula en UTC. Si hace falta, añade tu diferencia horaria, por ejemplo para UTC+1: `{{ date("H:i", "+1 hour") }}`.

| Función | Qué hace |
|---|---|
| `date(formato, fecha)` | Una fecha en el formato indicado. Sin fecha, el momento actual. La fecha puede ser `"2026-10-02"`, `"+7 days"`, `"next monday"`, etc. |
| `time()` | La hora actual en segundos desde 1970 (tiempo Unix) |
| `modifyDateTime(fecha, formato_fecha, formato_salida, desplazamiento)` | Lee una fecha de una variable según su formato, la desplaza y la muestra en otro formato |
| `modifyUnixTime(tiempo_unix, desplazamiento, formato)` | Desplaza un tiempo Unix; con formato muestra una fecha y, sin él, el nuevo tiempo Unix |

Ejemplos:

```
Hoy es {{ date("d.m.Y") }}
Nos vemos el {{ date("d.m.Y", "+3 days") }}
Tu cita se ha movido al {{ modifyDateTime($fecha_cita, "d.m.Y", "d.m.Y", "+1 day") }}
Acceso hasta el {{ modifyUnixTime(time(), "+30 days", "d.m.Y") }}
```

Caracteres de formato principales:

| Carácter | Significado | Ejemplo |
|---|---|---|
| `d` | día con cero inicial | `02` |
| `j` | día sin cero inicial | `2` |
| `m` | mes con cero inicial | `10` |
| `n` | mes sin cero inicial | `10` |
| `Y` | año | `2026` |
| `H` | horas, formato de 24 horas | `14` |
| `i` | minutos | `05` |
| `s` | segundos | `09` |
| `N` | día de la semana, 1 es el lunes | `5` |

El desplazamiento se escribe en inglés: `"+1 day"`, `"-2 hours"`, `"+1 month"`, `"next friday"`.

Todas las funciones de esta sección son **simples**.

> [!NOTE]
> En flujos antiguos a veces se usa un signo de interrogación como comodín: `{{ date("d.m.Y", "+? days", $dias) }}`: `?` se sustituye por el siguiente argumento. Sigue funcionando, pero en las expresiones es más fácil unir texto: `{{ date("d.m.Y", "+" ~ $dias ~ " days") }}`.

## Condiciones

| Función | Qué hace |
|---|---|
| `printByCondition(a, operador, b, si_sí, si_no)` | Compara `a` y `b` y muestra una de las opciones. Operadores: `=`, `!=`, `>`, `>=`, `<`, `<=`. Si `a` o `b` está vacío, muestra `si_no` |
| `printByExistsCondition(valor, si_sí, si_no)` | `si_sí` si el valor no está vacío y, si lo está, `si_no` |

```
{{ printByCondition($puntos, ">=", 100, "¡El regalo es tuyo!", "Sigue acumulando") }}
{{ printByExistsCondition($telefono, "Teléfono guardado", "Déjanos tu teléfono") }}
```

Las dos funciones son **simples**. En las expresiones es más práctico el operador de condición: `{{ $puntos >= 100 ? "¡El regalo es tuyo!" : "Sigue acumulando" }}`.

## Datos del contacto y del bot

| Función | Qué hace | Simple |
|---|---|---|
| `var("nombre")` | El valor de una variable del contacto; útil para nombres con espacios | sí |
| `global("nombre")` | El valor de una variable global | sí |
| `printContactTags()` | Las etiquetas del contacto, separadas por comas | sí |
| `printContactVariables()` | Todas las variables de texto del contacto como lista «- nombre: valor» | sí |
| `printGlobalVariables()` | Todas las variables globales del bot como lista «- nombre: valor» | sí |
| `getBalance("moneda", "etiqueta")` | El saldo de la cuenta del contacto en una moneda, con su símbolo: `getBalance("USD")`. Con un segundo argumento, un número y tu etiqueta: `getBalance("PTS", "puntos")` → `150 puntos` | no |
| `getCartAmount()` | El total del carrito del bloque antiguo «Carrito de compras» | no |

> [!WARNING]
> `printGlobalVariables()` muestra **todas** las variables globales. No la uses en mensajes a los contactos si tus variables globales guardan claves o contraseñas.

## Variables

Estas funciones escriben el resultado en una variable del contacto y no muestran nada.

| Función | Qué hace |
|---|---|
| `setSumVariablesIntoVariable("result", a, b, ...)` | Guarda la suma en la variable `result` |
| `setMultiplicationVariablesIntoVariable("result", a, b, ...)` | Guarda el producto en la variable `result` |

Los términos son números o nombres de variables entre comillas, al menos dos: `{{ setSumVariablesIntoVariable("result", "precio", "envio", 100) }}`.

Para los cálculos es más cómodo el bloque «Operación con variable», que también admite expresiones.

## Listas

| Función | Qué hace |
|---|---|
| `getListRow("id del registro", "plantilla")` | Muestra un registro de la lista según una plantilla |
| `getListRows("id de la lista", "plantilla", cuántos, "campo de orden", "asc" o "desc", "separador")` | Muestra registros de la lista según una plantilla, 10 por defecto y 50 como máximo, cada uno en una línea nueva |

En la plantilla, un campo del registro se escribe entre llaves simples: `{Nombre}`, `{Precio}`. En `getListRows` puedes insertar una variable del contacto en la plantilla: `{$ciudad}`.

```
{{ getListRows("6523f0c2a1b2c3d4e5f60718", "{Nombre} — {Precio} €", 5, "Precio", "asc") }}
```

El bot solo lee las listas que pertenecen a su propietario.

## Programa de referidos

| Función | Qué muestra |
|---|---|
| `getInviteLink()` | El enlace de referido personal del contacto (Telegram, MAX) |
| `getDirectInviteLink(id_flujo)` | Un enlace directo al bot con un parámetro de referido; con un flujo, un enlace que inicia ese flujo |
| `getInviteLinkWithSchema(id_flujo)` | Un enlace de referido que inicia un flujo |
| `getLinkBySchema(id_flujo)` | Un enlace que inicia un flujo, sin parámetro de referido |
| `getReferrals(cuántos, "etiqueta")` | La lista de contactos invitados por este contacto (primer nivel): «1. Nombre - username», 10 por defecto y 100 como máximo. Con una etiqueta, solo los que la tienen |
| `getReferralsByDepth(nivel, cuántos, "etiqueta")` | Lo mismo para el nivel indicado |
| `getReferralsCount("etiqueta")` | El número de invitados en todos los niveles |
| `getReferralsCountByDepth(nivel, "etiqueta")` | El número de invitados en el nivel indicado; 0, todos los niveles |
| `getReferrer(nivel)` | Quién invitó al contacto; 2, quién invitó a quien lo invitó, y así sucesivamente |
| `getReferrers(cuántos_niveles, desde_nivel, "etiqueta")` | La lista de quienes invitaron, subiendo por la cadena |

Las funciones de esta sección no son simples. Las variantes obsoletas con `Telegram` en el nombre (`getTelegramInviteLink` y otras) funcionan igual.

## Textos distintos para cada app de mensajería

El texto dentro de la función solo se muestra a los contactos de esa app de mensajería; el resto ve un espacio vacío:

| Función | App de mensajería |
|---|---|
| `messageToTelegram("texto")` | Telegram |
| `messageToViber("texto")` | Viber |
| `messageToVK("texto")` | VK |
| `messageToWeb("texto")` | Chat del sitio web |

```
Escríbenos{{ messageToTelegram(" en Telegram: @example_support") }}{{ messageToWeb(" directamente en este chat") }}
```

Las funciones de esta sección no son simples. En una expresión, una función de este tipo debe ir sola: no puede estar dentro de una condición ni de otra función.
