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

# Segmentos

> Agrupa contactos en segmentos estáticos o dinámicos y úsalos en campañas y agentes

## ¿Qué es un segmento?

Un segmento es un grupo de contactos de tu negocio. Hay dos tipos:

* **Estático**: una lista de contactos que tú agregas y quitas (a mano, por ID o con una selección por filtros). Los segmentos estáticos **no usan reglas**.
* **Dinámico**: un **filtro guardado** que se calcula al momento. No guarda una lista de miembros: cada vez que consultas el segmento, o que una campaña lo usa, se evalúa el filtro sobre tus contactos actuales. Un contacto que empieza a cumplir las condiciones entra solo; el que deja de cumplirlas sale solo.

Los segmentos dinámicos usan el mismo motor de filtros que [Búsqueda Avanzada de contactos](/api-reference/contacts/search), así que lo que ves en una búsqueda es exactamente lo que contiene el segmento.

<Info>
  Los endpoints de segmentos viven en `https://api.whaapy.com/segments` (sin `/v1`) y se autentican con tu API Key, igual que el resto de la API.
</Info>

***

## Reglas de un segmento dinámico

### Formato actual: versión 3

```json theme={null}
{
  "version": 3,
  "filters": {
    "tags": { "any": ["cliente", "vip"] },
    "funnel_stage_id": "11111111-1111-4111-8111-111111111111",
    "last_contact_at": { "older_than_days": 30 }
  }
}
```

`filters` acepta los mismos campos que `filters` en [Búsqueda Avanzada](/api-reference/contacts/search) (teléfono, nombre, email, tags, etapa del funnel, origen, fechas, campos personalizados, etc.), con una excepción: **no se permite `segment_id`** dentro de un segmento (evita segmentos que dependen de sí mismos). Se guarda en `snake_case`, como en la API de búsqueda.

La validación de v3 es **estricta** a propósito. Si una regla se ignorara en silencio, el segmento sería más grande de lo que esperas y podrías enviar una campaña a contactos equivocados. Por eso, en lugar de ignorarlas, se rechazan.

### Versiones anteriores (v1 y v2)

Las reglas heredadas siguen aceptándose al crear, actualizar y previsualizar:

* **v1**: `{ "operator": "AND" | "OR", "conditions": [...] }`, sin campo `version`.
* **v2**: `{ "version": 2, "operator": "AND" | "OR", "groups": [...] }`.

No es necesario migrar. Cuando una regla heredada tiene un equivalente exacto en v3, la API además te devuelve ese equivalente en `filters` (ver abajo). Convertirla nunca modifica lo guardado.

***

## Campos de respuesta

Además de los campos habituales (`id`, `name`, `type`, `contactCount`, `color`...), los segmentos devuelven:

<ResponseField name="contactCount" type="number">
  Número de contactos activos del segmento. En un dinámico se calcula **al momento**.
</ResponseField>

<ResponseField name="filters" type="object | null">
  Filtros v3 del segmento. En reglas v3 son los guardados. En reglas v1/v2 solo aparecen cuando la conversión es exacta y se comprobó que ambos motores cuentan lo mismo; esa comprobación se hace al consultar el detalle (`GET /segments/{id}`), por lo que en el listado puede venir `null`. En segmentos estáticos es `null`.
</ResponseField>

<ResponseField name="rulesFormat" type="string | null">
  `"filters"` si las reglas guardadas son v3, `"legacy"` si son v1/v2, y `null` en estáticos.
</ResponseField>

<ResponseField name="countStale" type="boolean">
  Solo aparece (con valor `true`) cuando no se pudo contar al momento, por ejemplo por un tiempo de espera. En ese caso `contactCount` es el último valor guardado. Vuelve a consultar el segmento o llama a `POST /segments/{id}/evaluate`.
</ResponseField>

<ResponseField name="rulesError" type="string">
  Solo aparece cuando las reglas guardadas ya no son válidas. El segmento se sigue devolviendo para que puedas abrirlo y corregirlo, pero **no contiene a nadie** hasta que lo hagas; nunca se amplía la audiencia.
</ResponseField>

<ResponseField name="typeChangeIgnored" type="boolean">
  Solo aparece en la respuesta de `PATCH /segments/{id}` cuando enviaste un `type` distinto al actual. El tipo de un segmento no se puede cambiar: se ignora y se avisa con este campo.
</ResponseField>

***

## Endpoints

| Método | Ruta | Descripción |
| - | - | - |
| `GET` | `/segments` | Lista los segmentos con su conteo al momento |
| `POST` | `/segments` | Crea un segmento estático o dinámico |
| `POST` | `/segments/preview` | Previsualiza reglas antes de crear el segmento |
| `GET` | `/segments/{id}` | Detalle y contactos (`limit` y `offset`) |
| `PATCH` | `/segments/{id}` | Actualiza nombre, descripción, color o reglas |
| `DELETE` | `/segments/{id}` | Elimina el segmento (no borra contactos) |
| `POST` | `/segments/{id}/contacts` | Agrega contactos a un estático por ID |
| `DELETE` | `/segments/{id}/contacts/{contactId}` | Quita un contacto de un estático |
| `POST` | `/segments/{id}/evaluate` | Recalcula el conteo de un dinámico |
| `GET` | [`/segments/{id}/usage`](/api-reference/segments/usage) | Dónde se usa el segmento |
| `POST` | [`/segments/{id}/members`](/api-reference/segments/members) | Alta o baja masiva en un estático |

### Crear un segmento dinámico

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.whaapy.com/segments \
    -H "Authorization: Bearer wha_TU_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Clientes sin contacto en 30 días",
      "type": "dynamic",
      "rules": {
        "version": 3,
        "filters": {
          "tags": { "all": ["cliente"] },
          "last_contact_at": { "older_than_days": 30 }
        }
      }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "data": {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "name": "Clientes sin contacto en 30 días",
      "type": "dynamic",
      "contactCount": 128,
      "rulesFormat": "filters",
      "filters": {
        "tags": { "all": ["cliente"] },
        "last_contact_at": { "older_than_days": 30 }
      }
    }
  }
  ```
</ResponseExample>

Un `type` `"dynamic"` requiere `rules`. Un `type` `"static"` no las usa: enviar reglas v3 a un estático responde `400`; reglas heredadas, `null` o vacías se ignoran por compatibilidad. El campo `autoRefreshInterval` se sigue aceptando pero se ignora, porque los dinámicos ya se calculan al momento.

### Previsualizar reglas

`POST /segments/preview` recibe `{ "rules": ... }` (v1, v2 o v3) y devuelve `data.count` y `data.preview` (una muestra de contactos) sin guardar nada.

***

## Errores 400

Un segmento rechaza reglas que no se pueden aplicar con seguridad. Todas las respuestas tienen la forma `{ "error": "..." }`.

| Causa | Ejemplo de mensaje |
| - | - |
| Reglas dinámicas ausentes | `Los segmentos dinámicos requieren reglas` |
| Reglas v3 en un segmento estático | `Los segmentos estáticos no usan reglas` |
| Versión de reglas desconocida | `Versión de reglas no soportada` |
| Filtros vacíos (`{}`) o sin ninguna condición | `Regla de segmento inválida ...: se necesita al menos un filtro` |
| Valor, lista u objeto vacío (`""`, `[]`, `{}`) | `...: la lista no puede estar vacía` |
| Clave desconocida en `filters`, en cualquier nivel (por ejemplo `tags.alll`) | `...: filtro no soportado: alll` |
| Clave extra junto a `version` y `filters` | `...: clave no soportada: ...` |
| `segment_id` dentro de los filtros del segmento | `...: filtro no soportado: segment_id` |
| Teléfono sin dígitos (solo `+`, espacios o guiones) | `...: el teléfono debe tener al menos un dígito` |
| Reglas heredadas con campo u operador desconocido | `Regla de segmento inválida (campo "...", operador "..."): ...` |

Los mensajes de reglas terminan con `Corrige la regla del segmento e inténtalo de nuevo.` En validaciones de formato (por ejemplo un campo que falta) la respuesta es `{ "error": "Datos inválidos", "details": [...] }`.

Otros códigos: `404` si el segmento no existe o no es de tu negocio (nunca se distingue entre ambos casos) y `500` ante un error interno.

***

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Búsqueda Avanzada" icon="magnifying-glass" href="/api-reference/contacts/search">
    Todos los filtros disponibles
  </Card>

  <Card title="Uso de un segmento" icon="diagram-project" href="/api-reference/segments/usage">
    Campañas y agentes que lo usan
  </Card>

  <Card title="Alta y baja masiva" icon="users-gear" href="/api-reference/segments/members">
    Agregar o quitar miembros de un estático
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.