# Contactos

Un contacto es una persona que escribe a un bot en una app de mensajería o en el chat de un sitio web. Los métodos de esta página exportan los contactos de tus bots (por ejemplo, para pasarlos a un CRM), los cuentan y crean un contacto desde tu propio sistema cuando ya conoces el ID de la persona en el canal. Para los contactos en el panel, consulta [Contactos](https://support.cleverapp.pro/es/chatbots/contacts).

Puedes recorrer una exportación de dos formas: por páginas (`page` y `count`, hasta 500 contactos por solicitud) o por desplazamiento desde el inicio (`offset` y `limit`, hasta 1000 contactos por solicitud). `getNumberOfContacts` indica cuántos contactos cumplen los filtros.

Los métodos devuelven solo los contactos de tus propios bots. Los contactos creados al probar un bot en la vista previa no se incluyen en exportaciones ni recuentos.

## Campos del contacto

Todos los métodos que devuelven contactos, aquí y en la página [Referidos](https://support.cleverapp.pro/es/api/referrals), los devuelven con la misma estructura.

| Campo | Tipo | Descripción |
|---|---|---|
| `id` | número | ID del contacto |
| `bot_id` | número | ID del bot |
| `phone` | cadena o `null` | Número de teléfono, si el contacto lo compartió o se definió mediante la API |
| `email` | cadena o `null` | Email |
| `name` | cadena | Nombre |
| `address` | cadena o `null` | Dirección |
| `messenger` | cadena | De dónde viene el contacto: `telegram`, `max`, `viber`, `vk` o `web` (chat del sitio web) |
| `utm` | objeto | Variables del contacto cuyo nombre empieza por `utm_`: `{"utm_source": "…"}`. Si no hay ninguna, un array vacío `[]` |
| `avatar` | cadena o `null` | Enlace a la foto del contacto. El enlace a un archivo del almacenamiento es temporal: guarda el archivo, no el enlace |
| `telegram_id` | cadena | ID del usuario en Telegram. Solo contactos de Telegram |
| `telegram_username` | cadena o `null` | Nombre de usuario de Telegram sin `@`. Solo contactos de Telegram |
| `max_user_id` | número | ID del usuario en MAX. Solo contactos de MAX |
| `max_username` | cadena o `null` | Nombre de usuario en MAX. Solo contactos de MAX |
| `vk_user_id` | número o `null` | ID del usuario en VK. Está en todos los contactos; `null` en los que no son de VK |
| `viber_id` | cadena | ID del usuario en Viber. Solo contactos de Viber |
| `created_at` | cadena | Cuándo apareció el contacto, ISO 8601 en UTC |
| `unsubscribed_at` | cadena o `null` | Cuándo el contacto se dio de baja del bot; `null` significa que está suscrito |
| `tags` | array de cadenas | Etiquetas del contacto |
| `variables` | array de objetos | Variables del contacto |

Cada variable de `variables` es un objeto:

| Campo | Descripción |
|---|---|
| `id` | ID de la variable dentro del contacto |
| `name` | Nombre de la variable |
| `value` | Valor |
| `type` | Qué contiene el valor: `0`, texto; `1`, imagen; `2`, documento; `3`, audio; `4`, video. En los archivos multimedia, `value` contiene un enlace al archivo, que el método [decodeShortLink](https://support.cleverapp.pro/es/api/links) resuelve |
| `schema_id`, `deletable`, `payload` | Campos internos |

Para las etiquetas y variables en el panel, consulta [Etiquetas y variables](https://support.cleverapp.pro/es/chatbots/contacts/tags-variables).

## getContacts

Devuelve los contactos de tus bots, por páginas (20 por página por defecto) o por desplazamiento desde el inicio.

```endpoint
GET POST https://app.cleverapp.pro/api/v1/getContacts
```

| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `bot_id` | número | no | Solo los contactos de este bot. Sin él, los contactos de todos tus bots |
| `count` | número | no | Contactos por página: de 1 a 500. Por defecto, 20 |
| `page` | número | no | Número de página, a partir de 1. Por defecto, 1 |
| `offset` | número | no | Cuántos contactos omitir desde el inicio, a partir de 0. Activa la paginación por desplazamiento |
| `limit` | número | no | Cuántos contactos devolver en la paginación por desplazamiento: de 1 a 1000. Por defecto, 100. También activa la paginación por desplazamiento |
| `date_from` | número | no | Contactos que aparecieron en este momento o después. Tiempo Unix en segundos |
| `date_to` | número | no | Contactos que aparecieron en este momento o antes. Tiempo Unix en segundos |
| `with` | cadena | no | Se acepta por compatibilidad, p. ej. `variables`. No cambia nada: las etiquetas y variables siempre van en la respuesta |

Los contactos se ordenan por `id` ascendente, tanto por páginas como por desplazamiento. Si se pasa `offset` o `limit`, se usa la paginación por desplazamiento y se ignoran `page` y `count`.

### Por páginas

```bash title="Solicitud"
curl -X POST "https://app.cleverapp.pro/api/v1/getContacts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"bot_id": 12345, "count": 2, "date_from": 1758931200}'
```

```json title="Respuesta 200"
{
  "data": [
    {
      "id": 4815162,
      "bot_id": 12345,
      "phone": "15550100123",
      "email": null,
      "name": "Emily Johnson",
      "address": null,
      "messenger": "telegram",
      "utm": {"utm_source": "newsletter"},
      "avatar": null,
      "telegram_id": "123456789",
      "telegram_username": "emily_j",
      "vk_user_id": null,
      "created_at": "2026-09-28T07:41:12+00:00",
      "unsubscribed_at": null,
      "tags": ["ordered"],
      "variables": [
        {"id": 17590475010001, "name": "utm_source", "value": "newsletter", "type": 0, "schema_id": null, "deletable": false, "payload": null},
        {"id": 17590475820003, "name": "city", "value": "Austin", "type": 0, "schema_id": null, "deletable": false, "payload": null}
      ]
    },
    {
      "id": 4815170,
      "bot_id": 12345,
      "phone": null,
      "email": null,
      "name": "Michael Brown",
      "address": null,
      "messenger": "vk",
      "utm": [],
      "avatar": null,
      "vk_user_id": 700123456,
      "created_at": "2026-09-29T15:02:47+00:00",
      "unsubscribed_at": null,
      "tags": [],
      "variables": []
    }
  ],
  "links": {
    "first": "https://app.cleverapp.pro/api/v1/getContacts?page=1",
    "last": "https://app.cleverapp.pro/api/v1/getContacts?page=38",
    "prev": null,
    "next": "https://app.cleverapp.pro/api/v1/getContacts?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 38,
    "links": […],
    "path": "https://app.cleverapp.pro/api/v1/getContacts",
    "per_page": 2,
    "to": 2,
    "total": 75
  }
}
```

- `meta.total` es el número total de contactos que cumplen los filtros, y `meta.last_page`, el número de la última página. Para exportarlo todo, pide páginas hasta que `links.next` sea `null`. Las URL de `links` no llevan ninguno de tus parámetros salvo `page`: envía `bot_id`, `count` y las fechas de nuevo en cada solicitud.
- Los contactos nuevos quedan al final de la exportación: ordenar por `id` evita que las páginas se desplacen. Para que la exportación no crezca mientras la recorres, limítala con `date_to`.
- Un `bot_id` de un bot que no es tuyo o que no existe no provoca un error: la lista simplemente queda vacía.

### Por desplazamiento

Solicitud de la segunda centena de contactos del bot:

```bash title="Solicitud"
curl -X POST "https://app.cleverapp.pro/api/v1/getContacts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"bot_id": 12345, "limit": 100, "offset": 100}'
```

```json title="Respuesta 200"
{
  "data": [
    {
      "id": 4815162,
      "bot_id": 12345,
      "phone": "15550100123",
      "email": null,
      "name": "Emily Johnson",
      "address": null,
      "messenger": "telegram",
      "utm": [],
      "avatar": null,
      "telegram_id": "123456789",
      "telegram_username": "emily_j",
      "vk_user_id": null,
      "created_at": "2026-09-28T07:41:12+00:00",
      "unsubscribed_at": null,
      "tags": ["ordered"],
      "variables": [
        {"id": 17590475820003, "name": "city", "value": "Austin", "type": 0, "schema_id": null, "deletable": false, "payload": null}
      ]
    }
  ],
  "meta": {
    "offset": 100,
    "limit": 100,
    "total": 101
  }
}
```

- `meta.total` es el número total de contactos que cumplen los filtros. La exportación está completa cuando `data` contiene menos contactos que `limit`, o cuando `offset + limit` alcanza `meta.total`.
- Para el primer lote, pasa `offset` `0` u omite `offset`.

## getNumberOfContacts

Cuenta los contactos de tus bots, con los mismos filtros que `getContacts`.

```endpoint
GET POST https://app.cleverapp.pro/api/v1/getNumberOfContacts
```

| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `bot_id` | número | no | Solo los contactos de este bot. Sin él, todos tus bots |
| `date_from` | número | no | Contactos que aparecieron en este momento o después. Tiempo Unix en segundos |
| `date_to` | número | no | Contactos que aparecieron en este momento o antes. Tiempo Unix en segundos |

```bash title="Solicitud"
curl "https://app.cleverapp.pro/api/v1/getNumberOfContacts?bot_id=12345" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

```json title="Respuesta 200"
{
  "count": 1284
}
```

El número está en el campo `count` del nivel superior, sin el contenedor `data`.

## createOrUpdateContact

Crea un contacto en un bot o actualiza uno existente. El contacto se busca en el bot por su ID en el canal: `telegram_id`, `max_id`, `vk_id` o `viber_id`. Si se encuentra, se actualizan sus datos; si no, se crea un contacto nuevo.

```endpoint
GET POST https://app.cleverapp.pro/api/v1/createOrUpdateContact
```

| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `bot_id` | número | sí | ID de tu bot |
| `messenger` | cadena | sí | Canal del contacto: `telegram`, `max`, `viber` o `vk` |
| `name` | cadena | sí | Nombre del contacto. Reemplaza el nombre anterior en cada llamada |
| `telegram_id` | número | para `telegram` | ID del usuario en Telegram |
| `telegram_username` | cadena | no | Nombre de usuario de Telegram, hasta 255 caracteres |
| `max_id` | número | para `max` | ID del usuario en MAX. También se puede pasar como `max_user_id`, el nombre que tiene en la respuesta |
| `max_username` | cadena | no | Nombre de usuario en MAX, hasta 255 caracteres |
| `vk_id` | número | para `vk` | ID del usuario en VK. También se puede pasar como `vk_user_id`, el nombre que tiene en la respuesta |
| `viber_id` | cadena | para `viber` | ID del usuario en Viber, hasta 255 caracteres |
| `phone` | cadena | no | Teléfono en formato internacional: `+` seguido de dígitos, de 9 a 16 caracteres con el signo más, `+15550100123`. Se guarda en dígitos, sin `+`; `null` equivale a no pasar teléfono |
| `email` | cadena | no | Email |
| `address` | cadena | no | Dirección, hasta 255 caracteres |
| `tags` | array de cadenas | no | Etiquetas, hasta 100, cada una de hasta 255 caracteres. **Reemplazan** todas las etiquetas del contacto |

```bash title="Solicitud"
curl -X POST "https://app.cleverapp.pro/api/v1/createOrUpdateContact" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": 12345,
    "messenger": "telegram",
    "telegram_id": 123456789,
    "telegram_username": "emily_j",
    "name": "Emily Johnson",
    "phone": "+15550100123",
    "email": "emily@example.com",
    "tags": ["client", "from CRM"]
  }'
```

```json title="Respuesta 201"
{
  "data": {
    "id": 4815162,
    "bot_id": 12345,
    "phone": "15550100123",
    "email": "emily@example.com",
    "name": "Emily Johnson",
    "address": null,
    "messenger": "telegram",
    "utm": [],
    "avatar": null,
    "telegram_id": "123456789",
    "telegram_username": "emily_j",
    "vk_user_id": null,
    "created_at": "2026-10-03T09:15:42+00:00",
    "unsubscribed_at": null,
    "tags": ["client", "from CRM"],
    "variables": []
  }
}
```

```json title="Respuesta 404"
{
  "message": "Bot not found",
  "errors": {
    "bot_id": ["Bot not found"]
  }
}
```

El estado `201` significa que se creó el contacto, y `200`, que se actualizó uno existente.

- **Qué cambia en un contacto existente.** `name`, siempre. `email`, `address`, `phone`, `telegram_username` y `max_username`, solo si se pasan y no están vacíos: este método no puede vaciarlos. `tags`, si se pasan, reemplazan todo el conjunto de etiquetas; un array vacío `[]` quita todas las etiquetas. El método no toca las variables del contacto.
- **Un contacto nuevo** aparece en la lista de contactos del bot con el primer mensaje «Created from API» y aumenta el número de suscriptores del bot. El flujo del bot no se inicia y no se envía nada al contacto.
- **El teléfono** se guarda en dígitos, sin `+`, igual que lo guardan los bloques del bot. `phone` en la respuesta tampoco lleva `+`.

Errores del método (los generales están en [Errores](https://support.cleverapp.pro/es/api#errores)):

| Código | Cuándo | Respuesta |
|---|---|---|
| `404` | Ninguno de tus bots tiene este `bot_id`: no existe o pertenece a otra cuenta | `{"message": "…", "errors": {"bot_id": ["…"]}}` |
| `422` | Falta el ID del canal elegido, o el formato del teléfono o del email no es válido | `{"message": "…", "errors": {…}}` |
