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

# Conversaciones

> Cómo se identifica una conversación y por qué la ventana de 24h decide qué puedes enviar.

Una conversación es el hilo de WhatsApp entre tu negocio y un contacto. Casi
todos los endpoints de envío y de acciones (`/conversation/*`) la reciben en el
cuerpo del request bajo el objeto `conversation`.

## Identificar una conversación

El objeto `conversation` acepta **uno** de cuatro identificadores, más `channel`
(**obligatorio**), la clave pública del canal objetivo. El resolver
evalúa en este orden: `uuid` → `whatsapp_user_id` → `username` → `phone`:
`whatsapp_user_id` busca por igualdad exacta y `username` por igualdad
case-insensitive (ignora mayúsculas); `phone` se normaliza a dígitos.
Cuando el contacto tiene BSUID, `phone` y
`whatsapp_user_id` identifican valores distintos (ver Note).

<ParamField body="uuid" type="string">
  Clave estable de una conversación que ya conoces (por ejemplo, persistida de
  una integración previa). El camino más directo, aunque puede quedar obsoleto si
  dos conversaciones del mismo contacto se unifican — ver la nota de unificación
  más abajo.
</ParamField>

<ParamField body="whatsapp_user_id" type="string">
  El BSUID del contacto (identidad opaca de Meta). Resuelve por igualdad exacta
  contra el BSUID guardado; si no resuelve, el endpoint responde `404` sin caer a
  `phone`. Identificador recomendado de aquí en adelante.
</ParamField>

<ParamField body="username" type="string">
  Username público de WhatsApp del contacto, con o sin `@` inicial y sin
  distinguir mayúsculas. Resolución best-effort contra el último username
  observado por la plataforma (el usuario puede cambiar su handle); si varios
  contactos lo comparten, el endpoint responde `409` (`USERNAME_AMBIGUOUS`).
</ParamField>

<ParamField body="phone" type="string">
  Número en formato E.164 (`+5215512345678`). Se normaliza a dígitos antes del
  lookup. Útil cuando solo tienes el teléfono.
</ParamField>

<ParamField body="channel" type="string" required>
  Clave pública del canal — cópiala del dashboard en **Configuración → Canales**
  (campo **Clave de canal**), o lístalas con `GET /channels`. **Obligatorio** en todo
  request: fija el canal objetivo. No distingue mayúsculas/minúsculas (se
  normaliza en el servidor). No identifica por sí solo. En las vías por contacto
  (`phone`, `username`, `whatsapp_user_id`) restringe la resolución al canal
  indicado; con `uuid` el motor lo ignora, pero el contrato igual lo exige.
  Desambigua el **canal**, no el **contacto**: si varios contactos comparten
  `phone` o `username`, esa ambigüedad se resuelve con `whatsapp_user_id` o
  `uuid`. En las vías por contacto, si envías una clave que no existe, la API
  responde `404` (`CHANNEL_NOT_FOUND`).
</ParamField>

```jsonc theme={null}
{ "conversation": { "phone": "+52 55 1234 5678", "channel": "ch_7A9K2M4Q" } }
// equivalente: { "conversation": { "uuid": "7b8a1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d", "channel": "ch_7A9K2M4Q" } }
```

<Warning>
  El teléfono puede estar **duplicado** entre contactos (números reciclados o
  identidades separadas que comparten número): en ese caso la API responde `409`
  (`PHONE_NUMBER_AMBIGUOUS`) en vez de adivinar — identifica la conversación por
  `whatsapp_user_id` o `uuid`. Además, `whatsapp_user_id` puede **cambiar** si el
  usuario re-registra su cuenta de WhatsApp (rotación de identidad del lado de
  Meta). Usa el `uuid` como clave estable en tu sistema y `whatsapp_user_id` como
  identificador de resolución preferente.
</Warning>

<Note>
  `phone` y `whatsapp_user_id` son identificadores **distintos**: `phone` es el
  teléfono (wa\_id sin `+`) y `whatsapp_user_id` es el BSUID del contacto. Coinciden
  solo mientras el contacto no tiene BSUID. En las respuestas, `whatsapp_user_id`
  devuelve el BSUID real cuando existe, con fallback al teléfono para que siempre
  haya un valor resoluble. Cuidado en el round-trip: si el contacto aún no tiene
  BSUID, este campo trae el teléfono; reenvíalo entonces como `phone`, no como
  `whatsapp_user_id` — el resolver matchea `whatsapp_user_id` por igualdad exacta y
  daría `404`.
</Note>

<Note>
  Cuando un mismo contacto quedó registrado dos veces por identidad (por ejemplo,
  primero solo con su teléfono y luego con su BSUID), las dos conversaciones se
  **unifican automáticamente** en una sola: todo el historial pasa a la
  sobreviviente. El `uuid` de la conversación absorbida deja de resolver y responde
  `404`; el teléfono y el BSUID migran a la sobreviviente. Si guardaste un `uuid` y
  empieza a dar `404`, vuelve a resolver la conversación por `phone` o
  `whatsapp_user_id`.
</Note>

<Warning>
  `channel` es **obligatorio en todo request**: siempre fijas el canal objetivo con
  su clave pública (lístalas con `GET /channels`). Así, si un contacto tiene
  conversaciones en **más de un canal** (varios números de WhatsApp), la resolución
  por `phone`, `username` o `whatsapp_user_id` ya sabe a cuál apuntas. Una clave que
  no existe responde `404` (`CHANNEL_NOT_FOUND`).
</Warning>

## Leer una conversación

Te diriges a una conversación con una de las referencias de arriba: la API
pública no ofrece un listado para enumerarlas. Esas referencias salen de tu
propio inbound —el `phone` o el `whatsapp_user_id` del contacto que te
escribió— o de un `uuid` que hayas persistido.

Con esa referencia, `GET /conversation` devuelve su estado (`conversation_info`
y `contact_info`) y `GET /conversation/messages` su historial. El shape completo
y los parámetros están en [Conversación e hilo](/es/action-groups/query-conversation).

## La ventana de 24h

Es el concepto central de WhatsApp y decide qué puedes enviar.

<Steps>
  <Step title="El contacto te escribe">
    WhatsApp abre una **ventana de 24 horas**. Cada nuevo mensaje del contacto
    reinicia el contador.
  </Step>

  <Step title="Ventana abierta">
    Puedes enviar mensajes libres: texto, media y respuestas rápidas.
  </Step>

  <Step title="Pasan 24h sin respuesta">
    La ventana se cierra. El único mensaje permitido es una **plantilla**
    aprobada por Meta.
  </Step>

  <Step title="Enviar una plantilla reabre la ventana">
    Vuelves a poder enviar mensajes libres.
  </Step>
</Steps>

<Warning>
  Enviar texto, media o una respuesta rápida con la ventana cerrada falla con
  `WINDOW_CLOSED` (422). Envía una plantilla primero para reabrirla.
</Warning>

## Consultar el estado de la ventana

Antes de enviar un mensaje libre, puedes verificar si la ventana está abierta
con `POST /conversation/status`:

```bash theme={null}
curl -X POST "https://app.1to1.ai/api/v1/public/{slug}/conversation/status" \
  -H "Authorization: Bearer sk_1to1_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "conversation": { "phone": "+5215512345678", "channel": "ch_7A9K2M4Q" } }'
```

Respuesta:

```jsonc theme={null}
{
  "conversation": {
    "uuid": "7b8a2c1d-3e4f-…",
    "phone": "5215512345678",
    "whatsapp_user_id": "5215512345678"
  },
  "window": {
    "status": "open",
    "expires_at": "2026-07-21T18:30:00Z",
    "hours_remaining": 18.5
  },
  "assignment": { "type": "ai_employee", "ai_employee": { "uuid": "1a2b…", "name": "Aura" } },
  "mailbox": { "uuid": "5c6d…", "name": "Ventas" },
  "tags": [{ "uuid": "9e0f…", "name": "VIP", "color": "#22c55e" }],
  "inbox_status": "pending",
  "last_message": null,
  "is_tester": false,
  "tester_virtual_now": null
}
```

La respuesta incluye `conversation.uuid` (la clave estable de la conversación),
`window.status` (`open` o `closed`), `window.expires_at` (timestamp ISO de cierre
de la ventana; `null` si el contacto nunca escribió) y `window.hours_remaining`,
además del estado de asignación, buzón, tags e `inbox_status` de la conversación.
Úsalo para decidir entre un mensaje libre y una plantilla.

## Leer el hilo

```http theme={null}
GET /conversation/messages?phone=+5215512345678&limit=50
```

Devuelve los mensajes y los eventos de la conversación. Se identifica con la
misma referencia que el resto de la API, así que **no hace falta conocer ningún
uuid**.

<Note>
  El hilo se pagina **hacia atrás en el tiempo**: la primera llamada trae los
  items más recientes y `next_cursor` avanza hacia los más antiguos.
</Note>

Cada item responde cuatro preguntas: quién habló (`direction` y `author`), qué
pasó (`event`), con qué contenido (`content_type` y `body`) y cuándo
(`sent_at`). Leídos en orden, se ven como la conversación real:

```
--- 2 de julio de 2026 ---
contact   message_received  text   "Hola, ¿tienen disponible el paquete premium?"
business  message_sent      text   "¡Buen día! Sí, el paquete premium está disponible."
  └ Empleado AI: Ventas nocturnas
business  context_note             "Cliente pidió cotización formal por correo."
  └ CRM externo (vía API)
```

Y así viaja en el JSON:

```json theme={null}
{
  "items": [
    {
      "type": "message",
      "direction": "contact",
      "event": "message_received",
      "content_type": "text",
      "body": "Hola, ¿tienen disponible el paquete premium?",
      "author": { "type": "customer", "name": "Ana Pérez" },
      "status": "delivered",
      "sent_at": "2026-07-02T14:39:00.000Z"
    },
    {
      "type": "message",
      "direction": "business",
      "event": "message_sent",
      "content_type": "text",
      "body": "¡Buen día! Sí, el paquete premium está disponible.",
      "author": { "type": "ai_employee", "name": "Ventas nocturnas" },
      "status": "read",
      "sent_at": "2026-07-02T14:39:12.000Z"
    }
  ],
  "next_cursor": "MjAyNi0wNy0wMlQxNDozOTowMC4wMDBafDkxODIz",
  "has_more": true
}
```

**`type`** distingue las dos clases de item: `message` es contenido que viajó
por WhatsApp (trae `content_type` y `status`), y `event` es algo que ocurrió en
el historial —una nota de contexto, un dato del contacto actualizado, una
conversión— sin contenido enviado.

El orden dentro de cada página es cronológico, y `sent_at` es la clave para
ordenar el hilo completo a medida que paginas hacia atrás.

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Enviar mensajes" icon="paper-plane" href="/es/messages">
    Texto, media, respuestas rápidas y plantillas.
  </Card>

  <Card title="Plantillas" icon="newspaper" href="/es/templates">
    Cómo enviar plantillas con la ventana de 24h cerrada.
  </Card>
</CardGroup>
