> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ouraicalling.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Variables personalizadas

> Define variables por asistente e inyecta valores en vivo — desde la API, leads de campaña, un webhook entrante o el contexto del sistema — en prompts, saludos y herramientas

Las variables personalizadas te permiten escribir un asistente una sola vez y personalizar cada llamada. En lugar de codificar un nombre, una cita o un número de cuenta directamente en el prompt del sistema, haces referencia a un marcador como `{{customer_name}}` y le das el valor en cada llamada: desde tu solicitud a la API, un lead de campaña, un webhook de enriquecimiento entrante o el contexto del sistema integrado en la plataforma.

## Sintaxis de referencia

Haz referencia a una variable con llaves dobles, la forma preferida y segura para JSON:

```text theme={null}
Hi {{customer_name}}, I see your appointment is on {{appointment_date}}.
```

La forma antigua de llave simple `{customer_name}` también se resuelve, pero **solo para claves que realmente existen** (una variable definida o del sistema). Así se mantienen intactas las llaves literales, por ejemplo el JSON dentro del cuerpo de una herramienta. Cualquier marcador cuya clave sea desconocida se deja tal cual.

## Definir variables en un asistente

Cada asistente tiene una lista de definiciones de variables. Una definición incluye:

| Campo           | Obligatorio | Descripción                                                                                                                                                                                                                                                                         |
| --------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key`           | Sí          | El identificador que se usa como `{{key}}`. Debe empezar con una letra minúscula, seguida de letras minúsculas, dígitos y guiones bajos; de 1 a 64 caracteres (`^[a-z][a-z0-9_]{0,63}$`). Único por asistente. No puede ser una [variable de sistema](#system-variables) reservada. |
| `label`         | Sí          | Nombre legible para humanos que se muestra en el editor.                                                                                                                                                                                                                            |
| `description`   | No          | Nota sobre para qué sirve la variable.                                                                                                                                                                                                                                              |
| `default_value` | No          | Valor de respaldo que se usa cuando no se proporciona ningún valor al momento de la llamada.                                                                                                                                                                                        |
| `example`       | No          | Valor de ejemplo (solo para el editor/documentación, nunca se envía).                                                                                                                                                                                                               |
| `source`        | No          | Pista informativa: `manual` (predeterminado), `lead`, `webhook` o `system`. Determina las sugerencias de la interfaz y el mapeo del webhook; no restringe de dónde puede venir un valor.                                                                                            |

<Note>
  Las claves se validan al guardar: se rechazan un formato inválido, una colisión con una variable de sistema reservada, una clave duplicada o una etiqueta faltante.
</Note>

## Dónde se sustituyen las variables

Los valores se sustituyen al inicio de la llamada, antes de que se ejecute el modelo o el Flow, en estos campos:

* **Prompt del sistema** del asistente
* **Primer mensaje** del asistente (saludo)
* Nodo `start.greeting` del Flow
* Nodo `agent.instructions` del Flow
* **URL** de la solicitud y **valores** de encabezado del nodo de herramienta del Flow

Así, un nodo de herramienta puede llamar a `https://app.famulor.de/api/user/orders/{{order_id}}` o enviar `Authorization: Bearer {{api_token}}` con valores propios de cada llamada.

## Origen de los valores y prioridad

Un valor puede llegar desde varios lugares. Al inicio de la llamada, el worker resuelve cada clave según este orden de prioridad, de mayor a menor:

1. **Explícito**: valores pasados con la llamada, ya sea el `variables` de la API `make-call` o los campos personalizados de un lead de campaña mapeados a claves coincidentes.
2. **Webhook de variables entrante**: enriquecimiento obtenido al inicio de la llamada (ver [más abajo](#inbound-variable-webhook)).
3. **Variables de sistema**: completadas por la plataforma a partir del contexto de la llamada.
4. **Predeterminado**: el `default_value` de la definición.

Un marcador sin valor en ningún nivel se deja tal cual.

### Valores explícitos mediante la API

```bash theme={null}
curl -X POST https://app.famulor.de/api/user/make-call \
  -H "Authorization: Bearer fam_..." \
  -H "Content-Type: application/json" \
  -d '{
    "assistant_id": "asst_123",
    "to_number": "+493012345678",
    "variables": { "customer_name": "Jordan", "appointment_date": "2026-07-10" }
  }'
```

### Leads de campaña → variables

En una [campaña](/campaigns/overview), cada lead lleva **campos personalizados** de formato libre (`leads.custom_fields`). Al marcar, el campo personalizado de un lead se mapea a una variable con la **misma clave**. Así, una columna del CSV se convierte en una variable:

```csv theme={null}
phone_number,name,customer_name,appointment_date
+493012345678,Jordan,Jordan,2026-07-10
+491701234567,Alex,Alex,2026-07-11
```

Aquí las columnas `customer_name` y `appointment_date` completan `{{customer_name}}` y `{{appointment_date}}` en cada llamada. Asigna `source: "lead"` a una variable proveniente de un lead para documentar su origen.

## Variables de sistema

Estas claves siempre están disponibles y el worker las completa al inicio de la llamada. Están reservadas: no puedes definir una variable personalizada con ninguna de estas claves.

| Clave            | Etiqueta                | Descripción                                                                                                      | Ejemplo                |
| ---------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `caller_number`  | Número de quien llama   | El número de teléfono desde el que llega la llamada (entrante) o al que se realiza (saliente), en formato E.164. | `+493012345678`        |
| `called_number`  | Número llamado          | El número que se marcó o el número tuyo que recibió la llamada, en formato E.164.                                | `+498998765432`        |
| `assistant_name` | Nombre del asistente    | El nombre del asistente que gestiona la llamada.                                                                 | `Reception Bot`        |
| `direction`      | Dirección de la llamada | `inbound`, `outbound` o `web`.                                                                                   | `inbound`              |
| `call_id`        | ID de llamada           | Identificador único de esta llamada.                                                                             | `c_a1b2c3`             |
| `date`           | Fecha                   | Fecha actual al inicio de la llamada (zona horaria del asistente), `YYYY-MM-DD`.                                 | `2026-07-05`           |
| `time`           | Hora                    | Hora actual al inicio de la llamada (zona horaria del asistente), `HH:MM`.                                       | `14:30`                |
| `datetime`       | Fecha y hora            | Fecha y hora actuales al inicio de la llamada (ISO 8601).                                                        | `2026-07-05T14:30:00Z` |
| `weekday`        | Día de la semana        | Día de la semana actual al inicio de la llamada.                                                                 | `Sunday`               |

## Webhook de variables entrante

En las llamadas **entrantes** muchas veces no conoces de antemano a quien llama. Configura un **webhook de variables** en el asistente (`variable_webhook_url` + `variable_webhook_secret`) y el worker lo llama al inicio de la llamada para enriquecer las variables, por ejemplo, buscando a un cliente por su número de llamada.

### Solicitud

El worker envía un `POST` con un cuerpo JSON:

```json theme={null}
{
  "event": "call.variables",
  "assistant_id": "asst_123",
  "call_id": "c_a1b2c3",
  "direction": "inbound",
  "from_number": "+493012345678",
  "to_number": "+498998765432"
}
```

El cuerpo de la solicitud, sin procesar, se firma con HMAC-SHA256 usando el `variable_webhook_secret` del asistente, y se envía en el encabezado:

```text theme={null}
X-Famulor-Signature: sha256=<hexdigest>
```

### Respuesta

Devuelve las variables que quieres fusionar:

```json theme={null}
{
  "variables": {
    "customer_name": "Jordan",
    "open_amount": "128.50"
  }
}
```

Estos valores se fusionan **por encima de** las variables de sistema y los valores predeterminados, pero **por debajo de** cualquier valor explícito enviado en el dispatch. La llamada tiene un tiempo límite de \~5 s; un fallo no es crítico: el worker lo registra y continúa con los valores que ya tiene.

### Automatización nativa (alternativa)

En lugar de un `variable_webhook_url` propio, puedes crear una **Automatización** con el disparador **Inyectar variables de entrada** (`call.variables`) vinculada al asistente. Al iniciar la llamada, el worker ejecuta esa automatización de forma síncrona y espera una acción **Devolver variables** (con la misma estructura `{ variables: {…} }`). Si no existe ninguna automatización activa que coincida, se usa como alternativa la URL del webhook clásico.

### Verificar la firma

<CodeGroup>
  ```js Node.js theme={null}
  import crypto from "node:crypto";

  // rawBody: los bytes exactos recibidos, antes de JSON.parse
  function verify(rawBody, signatureHeader, secret) {
    const expected =
      "sha256=" +
      crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
    const a = Buffer.from(signatureHeader);
    const b = Buffer.from(expected);
    return a.length === b.length && crypto.timingSafeEqual(a, b);
  }
  ```

  ```python Python theme={null}
  import hmac, hashlib

  # raw_body: los bytes exactos recibidos, antes de json.loads
  def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
      expected = "sha256=" + hmac.new(
          secret.encode(), raw_body, hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(expected, signature_header)
  ```
</CodeGroup>

<Warning>
  Calcula siempre el HMAC sobre los bytes **sin procesar** del cuerpo de la solicitud, no sobre un objeto reserializado: la reserialización puede cambiar los espacios en blanco o el orden de las claves y romper la firma. Usa una comparación de tiempo constante.
</Warning>

### Solicitud de ejemplo

```bash theme={null}
curl -X POST https://your-app.example.com/famulor/variables \
  -H "Content-Type: application/json" \
  -H "X-Famulor-Signature: sha256=6d3a...e1f0" \
  -d '{
    "event": "call.variables",
    "assistant_id": "asst_123",
    "call_id": "c_a1b2c3",
    "direction": "inbound",
    "from_number": "+493012345678",
    "to_number": "+498998765432"
  }'
```

## API y MCP

* `GET /v1/assistants/{id}/variables`: lee las definiciones de variables del asistente; alcance `assistants:read`.
* `PATCH /v1/assistants/{id}/variables`: reemplaza las definiciones de variables; alcance `assistants:write`.
* Herramientas MCP: `get_assistant_variables`, `set_assistant_variables`.

<Tip>
  La referencia completa de la REST API está en [docs.famulor.io](https://docs.famulor.io). Usa `{{key}}` en cualquier lugar donde necesites un valor propio de cada llamada, mantén las claves en `snake_case` y dale a cada variable un `default_value` razonable para que las llamadas se degraden con elegancia cuando falte una fuente.
</Tip>
