
# Crear una integración de principio a fin

Esta guía le explica todo lo necesario para ejecutar <span data-t="appName">Your AI Connector</span> desde su propio código, sin tener que abrir nunca el panel de control. Al final, habrá creado una integración mínima que:

1. Autenticación con una clave API
2. Creación de un agente de IA y configuración de su comportamiento como asistente
3. Conexión de un canal de mensajería (usamos WhatsApp Web como ejemplo práctico) y asignación al agente
4. Importación de contactos
5. Envío y lectura de mensajes
6. Lectura de analíticas
7. Suscripción a webhooks para eventos en tiempo real

Cada paso enlaza con la guía de recursos completa para que pueda profundizar en los detalles cuando los necesite. Esta página es el mapa; las guías de recursos son el territorio.

> **Antes de empezar.** El acceso a la API es una función de pago. Si su plan no lo incluye, cada solicitud devolverá `403`. Consulte [Acceso a la API](../integrations/api-access.md) para confirmar que está habilitado, y [Autenticación](authentication.md) para conocer todas las formas de enviar su clave.

Todas las rutas a continuación son relativas a la URL base:

```
https://api.youraiconnector.com/v1
```

---

## Paso 1 — Obtenga una clave API y realice su primera solicitud

Tu clave API se encuentra en la aplicación en **Configuración → Integraciones → Clave API**; es una sección propia dentro de Integraciones, separada de los Webhooks, que solo aparece una vez que el acceso a la API está habilitado en el plan. Genera una, cópiala y guárdala en un lugar seguro (un almacén de secretos del lado del servidor o una variable de entorno; nunca en el código del navegador). Las instrucciones completas se encuentran en [Acceso a la API](../integrations/api-access.md).

Una vez que tenga una clave, confirme que funciona llamando al endpoint de estado (health). Hay varias formas de enviar la clave; la más sencilla es el parámetro de consulta `?apiKey=`, pero para código real, prefiera el encabezado `X-API-Key` para que la clave nunca termine en los registros del servidor o en el historial del navegador.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/health?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const BASE = "https://api.youraiconnector.com/v1";
const headers = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };

const res = await fetch(`${BASE}/health`, { headers });
const data = await res.json();
console.log(data); // { "success": true, ... }
```

**Python**

```python
import requests

BASE = "https://api.youraiconnector.com/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

res = requests.get(f"{BASE}/health", headers=HEADERS)
print(res.json())  # { "success": true, ... }
```

Cada respuesta exitosa se envuelve en el mismo sobre: un campo `success: true` más los datos resultantes. Los errores devuelven `success: false` con un mensaje `error` y un `error_code`. Consulte [Errores y paginación](errors-and-pagination.md) para obtener la lista completa y saber cómo los endpoints de lista se paginan con `?limit` y `?cursor`.

> **Límite de tasa.** Las solicitudes autenticadas están limitadas a **300 por minuto** (con un límite más amplio de 1200 por minuto por cuenta). Superar este límite devuelve `429`; espere un momento y vuelva a intentarlo.

---

## Paso 2 — Crear un agente de IA

Un **agente de IA** es la unidad que contiene el comportamiento de tu asistente: sus instrucciones, su objetivo, su horario de actividad y cómo interactúa con los contactos. Es el elemento que responde a una conversación, por lo que es lo primero que debes crear.

Crea uno con `POST /agents`. `name` es el único campo que vale la pena enviar inicialmente; todo lo demás se puede configurar con la llamada bot-config a continuación.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Inbound WhatsApp Leads",
    "language": "en"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/agents`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Inbound WhatsApp Leads",
    language: "en",
  }),
});
const { agent_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/agents",
    headers=HEADERS,
    json={"name": "Inbound WhatsApp Leads", "language": "en"},
)
agent_id = res.json()["agent_id"]
```

Una creación exitosa devuelve `201` con el nuevo ID:

```json
{
  "success": true,
  "agent_id": "abc123agent"
}
```

**Guarda el `agent_id`**; lo necesitarás como referencia al enrutar canales.

### Configurar el asistente

`PUT /agents/{agentId}/bot-config` establece el comportamiento del asistente. *Fusiona* los campos que envías con la configuración existente, por lo que todo lo que omitas se conservará:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/abc123agent/bot-config" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Greet warmly, answer questions about our services, and offer to book a call.",
    "goal": "Book a discovery call.",
    "ai_speed": "balanced"
  }'
```

Establece el horario de actividad con `PUT /agents/{agentId}/active-hours` para que el asistente solo responda durante el horario laboral; fuera de esos intervalos, no responderá automáticamente.

> **Base de conocimientos.** Para que el asistente responda basándose en tu propio contenido, adjunta preguntas frecuentes (FAQs). Consulta la [guía de preguntas frecuentes](faqs.md).

> **Legado: campañas clásicas.** Las cuentas que aún tienen una página de **Campañas** crean el mismo comportamiento de asistente en una campaña en su lugar (`POST /campaigns` con un objeto `type` y un objeto `bot`, luego `PUT /campaigns/{campaignId}/bot-config`). La lista completa de campos de campaña y los controles de ciclo de vida se encuentran en la [guía de campañas](campaigns.md). Si estás creando algo nuevo, crea un agente.

---

## Paso 3 — Conectar un canal

Un agente necesita una forma de enviar y recibir mensajes. Siete flujos de conexión pueden gestionarse desde la API: WhatsApp Business, WhatsApp Web, Instagram y Messenger juntos (un flujo Meta compartido), cuentas personales de Instagram, Telegram, LINE y Viber. Los canales restantes (SMS, correo electrónico, el widget de chat y canales personalizados, entre otros) se configuran en el panel de control en lugar de a través de REST, y una vez conectados, los endpoints de mensajería, contactos y enrutamiento funcionan exactamente de la misma manera. `GET /channels` es la fuente de información en tiempo real sobre lo que una cuenta determinada tiene conectado actualmente:

```bash
curl "https://api.youraiconnector.com/v1/channels?apiKey=YOUR_API_KEY"
```

El conjunto completo de flujos de conexión/desconexión para cada canal está documentado en la [Guía de canales](channels.md). A continuación, analizaremos **WhatsApp Web** de principio a fin, ya que muestra el patrón más interesante: un flujo de emparejamiento mediante código QR que tu wrapper debe renderizar y consultar.

### Ejemplo práctico: emparejar WhatsApp Web mediante código QR

El emparejamiento de WhatsApp Web es un proceso de tres llamadas: **iniciar**, **obtener el QR**, **consultar hasta conectar**.

**1. Iniciar la sesión de emparejamiento.** Pasa el número que deseas conectar en formato E.164.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+15551230000" }'
```

```javascript
await fetch(`${BASE}/channels/whatsapp-web/connections`, {
  method: "POST",
  headers,
  body: JSON.stringify({ phone_number: "+15551230000" }),
});
```

```python
requests.post(
    f"{BASE}/channels/whatsapp-web/connections",
    headers=HEADERS,
    json={"phone_number": "+15551230000"},
)
```

**2. Obtener el código QR y mostrarlo al usuario.** Consulta este endpoint cada 10–15 segundos. La respuesta incluye el payload `qr_code` sin procesar (renderízalo tú mismo como una imagen QR) y un `qr_data_url` listo para mostrar.

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/qr?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "status": "qr_pending",
  "qr_code": "2@abc...",
  "qr_data_url": "data:image/png;base64,iVBORw0KGgo..."
}
```

En la interfaz de usuario de tu wrapper, inserta el `qr_data_url` directamente en un `<img src="...">` y pide al usuario que lo escanee desde **WhatsApp → Dispositivos vinculados** en su teléfono. Si el QR caduca (una respuesta `410`), reinicia desde el paso 1 para obtener uno nuevo.

**3. Consultar el estado hasta que se conecte.** Después de que el usuario escanee, sigue consultando el endpoint de estado hasta que informe `connected` (el servicio también puede informar `open`). Trata `disconnected` y `not_initialized` como fallos terminales.

```python
import time

PHONE = "+15551230000"
while True:
    res = requests.get(
        f"{BASE}/channels/whatsapp-web/connections/{PHONE}/status",
        headers=HEADERS,
    )
    status = res.json()["status"]
    if status in ("connected", "open"):
        print("Connected!")
        break
    if status in ("disconnected", "not_initialized"):
        raise RuntimeError(f"Pairing failed: {status}")
    time.sleep(5)
```

```javascript
async function waitForConnection(phone) {
  while (true) {
    const res = await fetch(
      `${BASE}/channels/whatsapp-web/connections/${encodeURIComponent(phone)}/status`,
      { headers }
    );
    const { status } = await res.json();
    if (status === "connected" || status === "open") return;
    if (status === "disconnected" || status === "not_initialized") {
      throw new Error(`Pairing failed: ${status}`);
    }
    await new Promise((r) => setTimeout(r, 5000));
  }
}
```

> **Aviso.** Cada número de WhatsApp Web conectado conlleva un cargo de mantenimiento mensual recurrente hasta que lo desconectes (`DELETE /channels/whatsapp-web/connections/{phoneNumber}`).

### Enrutar el canal a tu agente

Conectar un canal hace que funcione; enrutarlo le indica a la plataforma *qué agente de IA* debe responder a las nuevas conversaciones entrantes en dicho canal. Establece el punto de entrada predeterminado para el canal, indicando el nombre del agente que creaste en el Paso 2:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "whatsapp_web", "agent_id": "abc123agent" }'
```

Repite la llamada una vez por canal: un valor predeterminado por canal. Para dejar un canal sin un agente que responda, llama a `DELETE /entry-points/channel-defaults?channel=whatsapp_web`; para comprobar si la jerarquía de puntos de entrada está activa para la cuenta, llama a `GET /entry-points/routing-status`. El mapa anterior `POST /channels/campaign` se conserva solo para reversiones y ya no se consulta para el enrutamiento entrante. Consulta la [guía de canales](channels.md) para conocer los otros tipos de canales y el flujo OAuth de WhatsApp Business.

---

## Paso 4 — Importe sus contactos

Con un canal activo, cargue a las personas a las que desea llegar. El endpoint de importación admite hasta **500 registros por llamada**. Cada registro necesita un `phone_number` en formato internacional; todo lo demás es opcional. Los registros con números incorrectos, canales no admitidos o números que ya existen se omiten, y cada omisión se informa con su índice y motivo, para que pueda volver a intentar solo los fallidos.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/import" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee" },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "defaultChannel": "whatsapp_web"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/import`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee" },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    defaultChannel: "whatsapp_web",
  }),
});
const result = await res.json();
console.log(`${result.imported} imported, ${result.skipped.length} skipped`);
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/import",
    headers=HEADERS,
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee"},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "defaultChannel": "whatsapp_web",
    },
)
result = res.json()
print(f"{result['imported']} imported, {len(result['skipped'])} skipped")
```

La respuesta le indica exactamente lo que sucedió:

```json
{
  "success": true,
  "imported": 2,
  "contact_ids": ["contactId1", "contactId2"],
  "skipped": []
}
```

Para la creación uno a uno, listado/búsqueda, listas, etiquetas y campos personalizados, consulte la [guía de contactos](contacts.md).

---

## Paso 5 — Envíe y lea mensajes

### Envíe un mensaje

El envío más sencillo es **agnóstico al canal**: proporcione la identidad del contacto y el cuerpo del mensaje, y la plataforma lo entregará en cualquier canal en el que se encuentre el contacto. Puede dirigirse por `contact_id`, o por `channel` más el campo de identidad coincidente (`phone_number` para WhatsApp/WhatsApp Web/SMS, `instagram_id` para Instagram, etcétera).

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/send" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "whatsapp_web",
    "phone_number": "+12025551234",
    "body": "Hi Ann! Thanks for reaching out."
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    channel: "whatsapp_web",
    phone_number: "+12025551234",
    body: "Hi Ann! Thanks for reaching out.",
  }),
});
const { message_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/send",
    headers=HEADERS,
    json={
        "channel": "whatsapp_web",
        "phone_number": "+12025551234",
        "body": "Hi Ann! Thanks for reaching out.",
    },
)
message_id = res.json()["message_id"]
```

La entrega es **asíncrona**: un `201` significa que el mensaje fue *aceptado y puesto en cola*, aún no entregado. (Los contactos con el modo no molestar o privado activado son rechazados con un `422`).

```json
{
  "success": true,
  "message_id": "aB3dE5fG7hI9jK1lM2nO",
  "contact_id": "contact123",
  "channel": "whatsapp_web"
}
```

### Lea una conversación

Para leer mensajes, enumérelos por contacto, del más reciente al más antiguo, con paginación de cursor. Pase el `next_cursor` de una respuesta como el `cursor` de la siguiente para retroceder en el historial.

```bash
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&apiKey=YOUR_API_KEY"
```

```python
res = requests.get(
    f"{BASE}/contacts/contact123/messages",
    headers=HEADERS,
    params={"limit": 50},
)
page = res.json()
for msg in page["messages"]:
    print(msg)
next_cursor = page["next_cursor"]  # pass back as ?cursor= for the next page
```

También puede filtrar por tipo de contenido (`?filter=text|media|tool_use`) o dirección (`?direction=inbound|outbound`). La [guía de mensajes](messages.md) cubre los archivos adjuntos multimedia, marcar mensajes como leídos y las vistas de mensajes por sesión.

> **No realice sondeos para obtener respuestas.** Listar mensajes con un temporizador funciona, pero desperdicia solicitudes y añade retraso. Para los mensajes entrantes, utilice webhooks en su lugar; ese es el Paso 7.

---

## Paso 6 — Leer analíticas

Una vez que los mensajes comienzan a fluir, el resumen de análisis le ofrece recuentos agregados durante un rango de fechas: enviados, entregados, leídos, respondidos, reservados, contactos creados y créditos gastados/recargados. Obtendrá tanto los totales del rango como una serie diaria con ceros, perfecta para un gráfico de panel. Opcionalmente, puede limitar el alcance a una sola campaña con `campaign_id` (los ejemplos a continuación utilizan un ID de campaña de marcador de posición, `abc123campaign`); omita el parámetro para obtener los totales de toda la cuenta.

```bash
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&campaign_id=abc123campaign&apiKey=YOUR_API_KEY"
```

```javascript
const params = new URLSearchParams({
  from: "2026-05-01",
  to: "2026-05-31",
  campaign_id: "abc123campaign",
});
const res = await fetch(`${BASE}/analytics/summary?${params}`, { headers });
const { totals, by_date } = await res.json();
```

```python
res = requests.get(
    f"{BASE}/analytics/summary",
    headers=HEADERS,
    params={"from": "2026-05-01", "to": "2026-05-31", "campaign_id": "abc123campaign"},
)
data = res.json()
totals = data["totals"]
by_date = data["by_date"]
```

El rango predeterminado es de los últimos 30 días y tiene un límite de 366. Para obtener registros de uso crédito por crédito y desgloses de costes de IA, consulte la [Guía de analíticas](analytics.md).

---

## Paso 7 — Suscribirse a webhooks para eventos en tiempo real

El sondeo (polling) está bien para un script rápido, pero una integración real debería estar **basada en push**. Los webhooks permiten que la plataforma llame a *su* servidor en el momento en que ocurre algo: un nuevo contacto, una respuesta, una cita reservada, un chat concluido.

Primero, descubra los nombres exactos de los eventos a los que puede suscribirse:

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "events": [
    "Contact Created",
    "Human Alerted",
    "Appointment Booked",
    "Replies",
    "New Message",
    "Chat Concluded",
    "Task Created",
    "Daily Summary Created"
  ]
}
```

Luego, cree una suscripción que apunte a una URL HTTPS en su servidor. Utilice las cadenas de eventos exactas de la llamada anterior.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Lead updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/webhooks`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Lead updates hook",
  }),
});
const { webhook_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/webhooks",
    headers=HEADERS,
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Lead updates hook",
    },
)
webhook_id = res.json()["webhook_id"]
```

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Lead updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

La URL debe usar HTTPS y ser accesible públicamente. A partir de aquí, su servidor recibirá un POST por cada evento suscrito. Puede enviar una entrega de prueba, comprobar el estado de una suscripción y volver a habilitar una suscripción que se desactivó automáticamente tras fallos repetidos; consulte la [Guía de webhooks](webhooks.md) y la página de [Webhooks](../integrations/webhooks.md) a nivel de integraciones para ver los formatos de carga útil y la verificación.

---

## Resumen de todo el proceso

Aquí tiene todo el flujo de un vistazo:

| Paso | Objetivo | Llamada clave |
|---|---|---|
| 1 | Autenticar | `GET /health` |
| 2 | Crear y ajustar el asistente | `POST /agents`, `PUT /agents/{id}/bot-config`, `PUT /agents/{id}/active-hours` |
| 3 | Conectar un canal y enrutarlo | `POST /channels/whatsapp-web/connections` → consultar QR + estado → `PUT /entry-points/channel-defaults` |
| 4 | Cargar contactos | `POST /contacts/import` |
| 5 | Enviar y leer | `POST /contacts/send`, `GET /contacts/{id}/messages` |
| 6 | Medir | `GET /analytics/summary` |
| 7 | Reaccionar en tiempo real | `POST /webhooks` |

Un envoltorio mínimo consiste solo en estas siete llamadas conectadas a su propia interfaz de usuario. A partir de ahí, añada las guías por recurso a medida que necesite más:

- [Campañas](campaigns.md) · [Contactos](contacts.md) · [Preguntas frecuentes](faqs.md) · [Mensajes](messages.md) · [Citas](appointments.md)
- [Canales](channels.md) · [Plantillas](templates.md) · [Analíticas](analytics.md) · [Webhooks](webhooks.md) · [Claves de API](api-keys.md)
- ¿Es nuevo aquí? [Primeros pasos](getting-started.md) · [Autenticación](authentication.md) · [Errores y paginación](errors-and-pagination.md)

Stuck on something this guide does not cover? Email [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com).
