
# API de la base de conocimientos

Tu base de conocimientos es de donde lee la IA. Consta de dos partes, y esta página cubre ambas:

- **Fuentes de conocimiento** (`/kb-sources`): las páginas web y los documentos cargados que proporcionas a la plataforma. Cada uno se lee, se divide en secciones y se convierte en preguntas frecuentes (FAQs) que tu IA puede responder.
- **Grupos de conocimiento** (`/kb-groups`): conjuntos de preguntas frecuentes con nombre que puedes aplicar a un agente o a una campaña en una sola llamada, de modo que un cuerpo de conocimientos que ya hayas seleccionado pueda reutilizarse en el siguiente agente que crees.

Las preguntas frecuentes que produce una fuente terminan en la misma biblioteca que las que escribes a mano, por lo que una vez que finaliza una importación, puedes leerlas, editarlas y vincularlas con la [API de preguntas frecuentes](faqs.md).

Todos los endpoints a continuación son relativos a la URL base `https://api.youraiconnector.com/v1`. Cada solicitud debe estar autenticada; consulta [Acceso a la API](../integrations/api-access.md) y [Autenticación](authentication.md). El acceso a la API es una función de pago; sin ella, las solicitudes se rechazan con un `403`.


> **La importación consume créditos.** Leer una página o documento y redactar preguntas frecuentes a partir de él consume créditos, aproximadamente en proporción a la cantidad de contenido que haya. Utiliza [Estimar una importación](#estimate-what-an-import-will-cost) antes de realizar un rastreo grande.

---

## Cómo funciona una importación

La importación es una tarea en segundo plano, no algo que finaliza mientras esperas. Cada endpoint de importación responde inmediatamente con un `source_id`, y debes consultar esa fuente hasta que termine:

1. **Iniciar la importación** — `POST /kb-sources/url` (una página), `POST /kb-sources/file` (un documento cargado) o `POST /kb-sources/bulk-import` (hasta 100 páginas). Obtendrás un ID de fuente y un `status: "queued"`.
2. **Consultar** — `GET /kb-sources/{sourceId}` hasta que `status` ya no sea `queued` o `processing`.
3. **Leer las preguntas frecuentes** — cuando el estado es `ready`, las entradas que produjo están en tu biblioteca de preguntas frecuentes: `GET /faqs`.

Cada fuente informa uno de estos estados:

| Estado | Qué significa |
|---|---|
| `queued` | Esperando a ser leído. Aún no se ha cobrado nada. |
| `processing` | Se está leyendo y convirtiendo en preguntas frecuentes en este momento. |
| `ready` | Finalizado. Sus preguntas frecuentes están en tu biblioteca. |
| `failed` | No se pudo importar. `error_message` indica el motivo. |
| `cancelled` | Detenido antes de ser leído (consulta [Detener una importación](#stop-an-import)). |
| `paused` | Detenido porque tu propia clave de IA falló durante la importación (consulta [Reanudar una importación pausada](#resume-a-paused-import)). |
| `deleting` | Una eliminación masiva está procesándolo. |
| `unknown` | El registro no tiene estado. Considéralo como no preparado. |

> **Adjuntar al importar.** Pasa `autoLinkToAgentId` en cualquier endpoint de importación y la fuente —además de cada pregunta frecuente que produzca— se añadirá al conocimiento de ese agente en la misma llamada, sin necesidad de un paso de vinculación posterior. `autoLinkToCampaignId` hace lo mismo para una campaña clásica. La vinculación se realiza de la mejor manera posible: un ID que no existe o que pertenece a otra cuenta se omite silenciosamente y la importación continúa, así que confirma la vinculación leyendo el agente de nuevo.

---

## Importar una página web

`POST /kb-sources/url`

Añade una página web a tu base de conocimientos.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `url` | Sí | Dirección `http` o `https` completa de la página. |
| `autoLinkToAgentId` | No | ID de un agente de IA al que adjuntar la fuente importada. |
| `autoLinkToCampaignId` | No | Legado. ID de una campaña a la que adjuntar la fuente importada. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/url?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/pricing",
    "autoLinkToAgentId": "ag7HkQ2ZpLxR3mNb"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/kb-sources/url", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com/pricing",
    autoLinkToAgentId: "ag7HkQ2ZpLxR3mNb",
  }),
});
const { source_id } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/kb-sources/url",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://example.com/pricing",
        "autoLinkToAgentId": "ag7HkQ2ZpLxR3mNb",
    },
)
source_id = res.json().get("source_id")
```

**Respuesta** — `202 Accepted`

```json
{
  "success": true,
  "source_id": "kb_src_abc123",
  "status": "queued",
  "batch_id": "batch_9f2a"
}
```

Realice un sondeo a `source_id` con [Comprobar una fuente](#check-a-source) hasta que el estado sea `ready` o `failed`.

Si la misma página ya se encuentra en su base de conocimientos, no se pone nada nuevo en cola y obtiene un `200` en su lugar; y si solicitó un enlace automático, la fuente existente se vinculará para usted de todos modos:

```json
{
  "success": true,
  "status": "exists",
  "skipped_duplicate": 1
}
```

Un `url` faltante, o uno que no sea una dirección `http`/`https` válida, devuelve `400`.

---

## Importar un documento cargado

`POST /kb-sources/file`

Añade un documento que **ya está en el almacenamiento de archivos de su cuenta** como fuente de conocimiento. Tipos admitidos: PDF, DOCX, TXT, MD, CSV y XLSX.

> **Este endpoint no transporta el archivo.** No hay carga multipart, ni cuerpo en base64, ni descarga desde una URL: usted envía la ubicación de almacenamiento de un archivo que ya existe, y debe residir en su propia carpeta de cargas (`storage_path` debe comenzar con `users/{your user id}/uploads/`) o la solicitud será rechazada con `403`. El panel de control coloca los archivos allí cuando los arrastra. Si no tiene forma de colocar un archivo allí, importe una página web con [Importar una página web](#import-a-web-page) en su lugar.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `storage_path` | Sí | Dónde reside el archivo cargado. Debe comenzar con `users/{your user id}/uploads/`. |
| `filename` | Sí | Nombre original del archivo incluyendo su extensión; así es como se detecta el tipo de archivo. |
| `mime_type` | Sí | Tipo MIME del archivo, por ejemplo `application/pdf`. |
| `autoLinkToAgentId` | No | ID de un agente de IA al que adjuntar el documento. |
| `autoLinkToCampaignId` | No | Legado. ID de una campaña a la que adjuntar el documento. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/file?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "storage_path": "users/abc123uid/uploads/handbook.pdf",
    "filename": "handbook.pdf",
    "mime_type": "application/pdf",
    "autoLinkToAgentId": "ag7HkQ2ZpLxR3mNb"
  }'
```

**Respuesta** — `202 Accepted`

```json
{
  "success": true,
  "source_id": "kb_src_abc123",
  "status": "queued"
}
```

| Estado | Cuándo |
|---|---|
| `400` | Falta un campo obligatorio o el archivo no es de un tipo que podamos leer. |
| `403` | `storage_path` está fuera de su propia carpeta de cargas. |

---

## Comprobar una fuente

`GET /kb-sources/{sourceId}`

El sondeo que sigue a cada importación y actualización. Repítalo hasta que el estado sea `ready` o `failed`.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/kb-sources/kb_src_abc123?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/kb-sources/kb_src_abc123",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const source = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/kb-sources/kb_src_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
source = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "source_id": "kb_src_abc123",
  "status": "ready",
  "faq_count": 24,
  "section_count": 31,
  "error_message": null
}
```

| Campo | Tipo | Descripción |
|---|---|---|
| `status` | string | Dónde se encuentra la fuente en la canalización (consulte la [tabla de estado](#how-an-import-works)). |
| `faq_count` | integer | Cuántas preguntas frecuentes se han generado a partir de esta fuente hasta el momento. |
| `section_count` | integer | En cuántas secciones de contenido se dividió la fuente. |
| `error_message` | string \| null | Por qué falló la importación, cuando el estado es `failed`. `null` en caso contrario. |

---

## Eliminar una fuente

`DELETE /kb-sources/{sourceId}`

Elimina una fuente de conocimiento. **De forma predeterminada, las preguntas frecuentes que produjo se conservan**; añada `delete_faqs=true` para eliminarlas también.

**Parámetros de consulta**

| Parámetro | Requerido | Descripción |
|---|---|---|
| `delete_faqs` | No | Establézcalo en `true` para eliminar también todas las preguntas frecuentes que produjo esta fuente. El valor predeterminado es `false`. |

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/kb-sources/kb_src_abc123?delete_faqs=true&apiKey=YOUR_API_KEY"
```

**Respuesta**

```json
{
  "success": true,
  "faqs_deleted": 24
}
```

`faqs_deleted` es `0` a menos que haya solicitado `delete_faqs=true`.

---

## Importar muchas páginas a la vez

`POST /kb-sources/bulk-import`

Añade hasta 100 páginas web en una sola llamada; es el paso siguiente habitual a [Descubrir páginas en un sitio web](#discover-pages-on-a-website) o [Buscar nuevas páginas en un sitio web](#find-new-pages-on-a-website). Las páginas que ya están en su base de conocimiento se omiten en lugar de duplicarse (y siguen vinculadas al Agente cuando usted lo solicitó).

**Campos de la solicitud**

| Campo | Requerido | Descripción |
|---|---|---|
| `urls` | Sí | Direcciones a importar. Al menos 1, como máximo 100 por llamada. |
| `autoLinkToAgentId` | No | ID de un Agente de IA al que adjuntar cada página importada. |
| `autoLinkToCampaignId` | No | Legado. ID de una campaña a la que adjuntar cada página importada. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/bulk-import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": ["https://example.com/pricing", "https://example.com/faq"],
    "autoLinkToAgentId": "ag7HkQ2ZpLxR3mNb"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/kb-sources/bulk-import", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    urls: ["https://example.com/pricing", "https://example.com/faq"],
    autoLinkToAgentId: "ag7HkQ2ZpLxR3mNb",
  }),
});
const { queued_source_ids } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/kb-sources/bulk-import",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "urls": ["https://example.com/pricing", "https://example.com/faq"],
        "autoLinkToAgentId": "ag7HkQ2ZpLxR3mNb",
    },
)
queued_source_ids = res.json()["queued_source_ids"]
```

**Respuesta** — `202 Accepted`

```json
{
  "success": true,
  "batch_id": "batch_9f2a",
  "queued": 2,
  "skipped_duplicate": 0,
  "queued_source_ids": ["kb_src_abc123", "kb_src_def456"]
}
```

Consulte cada ID en `queued_source_ids` con [Comprobar una fuente](#check-a-source). Enviar una matriz `urls` vacía, una entrada que no sea una cadena o más de 100 entradas devuelve `400`.

---

## Eliminar muchas fuentes a la vez

`POST /kb-sources/bulk-delete`

Elimina hasta 2000 fuentes de conocimiento en una sola llamada. La eliminación se ejecuta en segundo plano y recibirá un correo electrónico cuando finalice.

> **La eliminación masiva también elimina las preguntas frecuentes.** A diferencia de [Eliminar una fuente](#delete-a-source), que las conserva a menos que solicite lo contrario, este endpoint elimina cada fuente junto con las preguntas frecuentes que produjo. No hay opción para conservarlas.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `sourceIds` | Sí | IDs de las fuentes a eliminar. Al menos 1, como máximo 2000 por llamada. |
| `domainLabel` | No | Un nombre descriptivo para esta limpieza. Se utiliza solo en el correo electrónico de finalización. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/bulk-delete?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceIds": ["kb_src_abc123", "kb_src_def456"],
    "domainLabel": "example.com"
  }'
```

**Respuesta** — `202 Accepted`

```json
{
  "success": true,
  "batch_id": "del_batch_31a",
  "queued": 2
}
```

---

## Descubrir páginas en un sitio web

`POST /kb-sources/discover-pages`

Explora un sitio web desde una dirección inicial y enumera las páginas encontradas en el mismo dominio, cada una con una opinión sobre si vale la pena importarla. **No se importa nada y no se selecciona nada por usted**; este es el paso de "qué hay en este sitio" que ejecuta antes de decidir qué enviar a [Importar muchas páginas a la vez](#import-many-pages-at-once).

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `url` | Sí | Dirección desde la que comenzar a explorar, generalmente la página de inicio del sitio. |
| `maxPages` | No | Límite superior de cuántas páginas devolver. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/discover-pages?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com", "maxPages": 100 }'
```

**Respuesta**

```json
{
  "success": true,
  "source_type": "sitemap",
  "pages": [
    {
      "url": "https://example.com/pricing",
      "title": "Pricing",
      "depth": 1,
      "score": 95,
      "recommendation": "add",
      "reason_key": "core_page"
    }
  ]
}
```

| Campo | Tipo | Descripción |
|---|---|---|
| `source_type` | string | Cómo se encontraron las páginas: `sitemap` (el mapa del sitio propio del sitio) o `link_discovery` (siguiendo enlaces). |
| `url` | string | Dirección completa de la página. |
| `title` | string \| null | Título de la página, cuando se pudo leer. |
| `depth` | integer | A cuántos enlaces de distancia de la página inicial se encontró esta página. |
| `score` | integer | Qué tan útil parece la página como conocimiento, de `0` a `100`. |
| `recommendation` | string | `add` (claramente vale la pena importar, puntuación 90 o superior), `maybe` (límite) o `skip` (contenido que rara vez ayuda a un asistente: registros de cambios, páginas legales, traducciones duplicadas). |
| `reason_key` | string | Una razón estable y legible por máquina detrás de la recomendación, por ejemplo `core_page`, `changelog_history`, `legal_page` o `locale_duplicate`. |

> **La exploración es un esfuerzo de mejor intento.** Si el sitio no se puede leer, la respuesta sigue siendo `200`, con `success: false`, una lista `pages` vacía y un mensaje `error`. Compruebe `success` antes de leer `pages`.

Un `url` faltante devuelve `400`.

---

## Estimar cuánto costará una importación

`POST /kb-sources/estimate-cost`

Calcula cuántos créditos consumiría una importación propuesta, antes de comprometerse con ella. Las páginas se obtienen y los documentos se leen para medir su tamaño, pero no se importa nada y la estimación en sí no gasta créditos.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `urls` | No | Direcciones de página que está considerando importar. |
| `files` | No | Archivos ya cargados que está considerando. Cada entrada necesita `storage_path`, `filename` y `mime_type`. |
| `tier` | No | El nivel de calidad de IA en el que se ejecutará la importación, para que la estimación coincida con lo que realmente se le cobrará. Déjelo fuera para la tarifa estándar. |

Envíe `urls`, `files` o ambos.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/estimate-cost?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "urls": ["https://example.com/pricing"] }'
```

**Respuesta**

```json
{
  "success": true,
  "estimates": [
    { "ref": "https://example.com/pricing", "chunks": 7, "credits": 7 }
  ],
  "total_chunks": 7,
  "total_credits": 7
}
```

Cada fila devuelve la URL o la ruta de almacenamiento en `ref` para que pueda hacerla coincidir con su entrada. Una página o archivo que no se pudo leer sigue obteniendo una fila, contada como un fragmento, con un `error` en ella.

---

## Detener una importación

`POST /kb-sources/cancel-import`

Detiene las páginas que aún están esperando en la cola de importación: el botón "detener importación" para un rastreo que resultó ser más grande de lo que esperaba. Cancelar una página en espera no cuesta nada, porque aún no se ha leído.

Las páginas que ya se están procesando **no** se detienen: su trabajo está en curso y se cobra de todos modos, por lo que terminan. La respuesta informa cuántas fueron.

**Campos de la solicitud**

| Campo | Requerido | Descripción |
|---|---|---|
| `host` | No | Solo detiene las páginas en espera en este sitio web (por ejemplo `docs.example.com`). Déjelo vacío para detener todas las importaciones en espera en la cuenta. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/cancel-import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "host": "docs.example.com" }'
```

**Respuesta**

```json
{
  "success": true,
  "cancelled": 412,
  "in_flight": 3
}
```

---

## Reanudar una importación pausada

`POST /kb-sources/resume-import`

Reinicia una importación que se pausó porque su propia clave de IA dejó de funcionar.

> Llamar a esto **es** su consentimiento para finalizar la importación con la clave que esté activa en ese momento, lo que puede significar gastar créditos de la plataforma si su propia clave sigue sin funcionar.

**Campos de la solicitud**

| Campo | Requerido | Descripción |
|---|---|---|
| `host` | No | Solo reanuda las páginas pausadas en este sitio web. Déjelo vacío para reanudar todo lo que esté pausado. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/resume-import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Respuesta**

```json
{
  "success": true,
  "resumed": 58
}
```

---

## Encontrar nuevas páginas en un sitio web

`POST /kb-sources/refresh-domain`

Explora un sitio web del que ya ha importado e informa solo de las páginas que **aún no** están en su base de conocimientos, cada una con la misma recomendación que el descubrimiento de páginas. No se importa nada y no se cambia nada.

Los dos seguimientos son llamadas deliberadamente separadas, por lo que abandonar esta no cuesta nada:

- importe las páginas nuevas que desee con [Importar muchas páginas a la vez](#import-many-pages-at-once);
- vuelva a leer las páginas que ya tiene con [Actualizar cada página de un sitio web](#refresh-every-page-on-a-website).

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `baseUrl` | Sí | Cualquier dirección del sitio web, o simplemente el host. |
| `maxPages` | No | Límite superior de cuántas páginas explorar. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/refresh-domain?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "baseUrl": "https://example.com" }'
```

**Respuesta**

```json
{
  "success": true,
  "source_type": "sitemap",
  "discovered": 249,
  "new_pages": [
    {
      "url": "https://example.com/new-guide",
      "score": 95,
      "recommendation": "add",
      "reason_key": "core_page"
    }
  ],
  "new_urls_queued": 0,
  "existing_refresh_queued": 249
}
```

| Campo | Tipo | Descripción |
|---|---|---|
| `discovered` | entero | Cuántas páginas se encontraron en el sitio en total. |
| `new_pages` | matriz | Páginas que aún no están en su base de conocimientos. No se pone nada en cola para usted: importe las que desee. |
| `new_urls_queued` | entero | Siempre `0`. Se mantiene por compatibilidad con versiones anteriores; este endpoint nunca pone nada en cola. |
| `existing_refresh_queued` | entero | Cuántas páginas que ya importó de este sitio se encontraron listas para ser leídas de nuevo. Esta llamada no pone nada en cola. |
| `batch_id` | cadena | Presente solo cuando se creó un lote. |

Al igual que la detección, esto falla de forma controlada: un sitio que no se puede leer sigue devolviendo `200`, con `success: false`, un `new_pages` vacío y un `error`. Un `baseUrl` faltante o vacío devuelve `400`.

---

## Actualizar cada página de un sitio web

`POST /kb-sources/trigger-domain-refresh`

Vuelve a leer cada página que ya ha importado de un sitio web, para que sus preguntas frecuentes sigan el contenido actual del sitio: las secciones modificadas se actualizan, las nuevas secciones se añaden y las secciones eliminadas se descartan.

Esto pone el trabajo en cola y devuelve una respuesta inmediatamente. Siga con [Seguimiento de una actualización de sitio web](#track-a-website-refresh) y deténgalo con [Detener una actualización de sitio web](#stop-a-website-refresh).

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `baseUrl` | Sí | Cualquier dirección del sitio web, o simplemente el host. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/trigger-domain-refresh?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "baseUrl": "https://example.com" }'
```

**Respuesta**

```json
{
  "success": true,
  "queued": 249
}
```

---

## Seguimiento de una actualización de sitio web

`GET /kb-sources/domain-refresh-status`

El progreso de una actualización de sitio web, para que pueda mostrar el avance como "221 de 249".

**Parámetros de consulta**

| Parámetro | Obligatorio | Descripción |
|---|---|---|
| `baseUrl` | Sí | Cualquier dirección del sitio web, o simplemente el host. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/kb-sources/domain-refresh-status?baseUrl=https://example.com&apiKey=YOUR_API_KEY"
```

**Respuesta**

```json
{
  "success": true,
  "job": {
    "domainBatchId": "job_7c1e",
    "host": "example.com",
    "total": 249,
    "pending": 28,
    "succeeded": 219,
    "failed": 2,
    "skippedDuplicate": 0,
    "status": "refreshing",
    "startedAtIso": "2026-06-15T09:00:00.000Z"
  }
}
```

`job` es `null` cuando no hay ninguna actualización ejecutándose para ese sitio web. Las páginas terminadas hasta el momento son `total` menos `pending`. El trabajo `status` es uno de `refreshing` (todavía procesando páginas), `deduplicating` (la pasada de limpieza al final), o el `completed`, `failed` y `cancelled` final. Guarde `domainBatchId`: es lo que debe pasar al endpoint de cancelación.

Un `baseUrl` faltante o vacío devuelve `400`.

---

## Detener una actualización de sitio web

`POST /kb-sources/refresh-domain/cancel`

Detiene una actualización de sitio web que aún está procesando sus páginas. Las páginas ya finalizadas mantienen su contenido actualizado; las páginas que no se han iniciado se descartan, y las páginas que se estaban volviendo a leer regresan a su estado anterior.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `jobId` | Sí | El `domainBatchId` devuelto por [Rastrear una actualización de sitio web](#track-a-website-refresh). |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/refresh-domain/cancel?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "jobId": "job_7c1e" }'
```

**Respuesta**

```json
{
  "success": true,
  "status": "cancelled",
  "cancelled_units": 28,
  "sources_reset": 3,
  "sources_cancelled": 25
}
```

| Campo | Tipo | Descripción |
|---|---|---|
| `status` | string | Estado de la actualización después de esta llamada: `cancelled`, `deduplicating`, `completed` o `failed`. |
| `cancelled_units` | integer | Cuánto trabajo quedaba pendiente cuando se recibió la cancelación. `0` en una cancelación repetida. |
| `sources_reset` | integer | Páginas retiradas del procesamiento y devueltas a `ready`. |
| `sources_cancelled` | integer | Páginas nuevas de esta actualización que aún estaban en cola y ahora han sido canceladas. |

Cancelar dos veces es inofensivo: la segunda llamada informa el mismo estado final. Una vez que la actualización ha pasado a su fase de limpieza, ya no se puede detener, y la respuesta devuelve `success: false` y `reason: "already_finalizing"`. Un `jobId` faltante devuelve `400`, y un trabajo que no está en su cuenta devuelve `404`.

---

## Actualizar una sola fuente

`POST /kb-sources/{sourceId}/refresh`

Vuelve a leer una página web que ya ha importado y sincroniza sus preguntas frecuentes con el contenido actual de la página: las secciones modificadas se actualizan, las nuevas se añaden y las eliminadas se descartan.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/kb_src_abc123/refresh?apiKey=YOUR_API_KEY"
```

**Respuesta** — `202 Accepted`

```json
{
  "success": true,
  "source_id": "kb_src_abc123",
  "status": "queued"
}
```

Consulte la fuente hasta que su estado deje de ser `queued` y `processing`. Un ID de fuente que no esté en su cuenta devuelve `404`.

---

## Elegir las páginas más relevantes

`POST /kb-sources/select-relevant-pages`

Solicita a la IA que elija las cinco páginas, de una lista de candidatas, que mejor describen un negocio; se utiliza al generar un manual de campaña a partir de un sitio web. Esto consume créditos.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `urls` | Sí | Direcciones de páginas candidatas para elegir, generalmente provenientes del descubrimiento de páginas. |
| `homeUrl` | Sí | La página de inicio del sitio, utilizada como contexto para la elección. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-sources/select-relevant-pages?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "homeUrl": "https://example.com",
    "urls": ["https://example.com/about", "https://example.com/pricing"]
  }'
```

**Respuesta**

```json
{
  "success": true,
  "pages": [
    { "url": "https://example.com/pricing", "title": "Pricing", "type": "pricing" }
  ]
}
```

Este es un asistente, no un recurso: en caso de error, sigue respondiendo `200`, con `success: false`, una lista `pages` vacía y un mensaje `error`.

---

## Grupos de conocimiento

Un **grupo de conocimiento** es un conjunto con nombre de preguntas frecuentes (FAQ) — "Envíos y devoluciones", "Incorporación" — que puede aplicar a un agente o a una campaña en una sola llamada. El grupo contiene referencias, no copias: las preguntas frecuentes permanecen en su biblioteca única, por lo que editar una con la [API de FAQ](faqs.md) la actualiza en todos los lugares donde se utilice.

Aplicar un grupo solo **añade** lo que falta, por lo que aplicar el mismo grupo dos veces es inofensivo y `added_count` devuelve `0` la segunda vez.

---

## Crear un grupo de conocimiento

`POST /kb-groups`

Crea un grupo. Comienza vacío: añádale preguntas frecuentes con [Añadir una FAQ a un grupo](#add-a-faq-to-a-group).

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `name` | Sí | Nombre del grupo. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-groups?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Shipping and returns" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/kb-groups", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Shipping and returns" }),
});
const { group_id } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/kb-groups",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"name": "Shipping and returns"},
)
group_id = res.json()["group_id"]
```

**Respuesta** — `201 Created`

```json
{
  "success": true,
  "group_id": "kbg_abc123"
}
```

---

## Cambiar el nombre de un grupo de conocimiento

`PUT /kb-groups/{groupId}`

Cambia el nombre de un grupo. Sus preguntas frecuentes permanecen intactas.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `name` | Sí | Nuevo nombre para el grupo. |

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Shipping, returns and refunds" }'
```

**Respuesta**

```json
{
  "success": true,
  "group_id": "kbg_abc123",
  "name": "Shipping, returns and refunds"
}
```

---

## Eliminar un grupo de conocimiento

`DELETE /kb-groups/{groupId}`

Elimina el grupo. Solo se elimina el conjunto: las preguntas frecuentes que contiene permanecen en su biblioteca, y cualquier elemento al que ya se hubiera aplicado el grupo conservará esas preguntas frecuentes.

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123?apiKey=YOUR_API_KEY"
```

**Respuesta**

```json
{
  "success": true
}
```

---

## Añadir una FAQ a un grupo

`POST /kb-groups/{groupId}/faqs`

Coloca una FAQ existente en un grupo. Esto solo cambia el paquete; no adjunta la FAQ a ningún agente por sí solo; aplique el grupo para ello.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `faq_id` | Sí | ID de la FAQ a añadir. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/faqs?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "faq_id": "aBcD1234eFgH5678" }'
```

**Respuesta**

```json
{
  "success": true,
  "group_id": "kbg_abc123",
  "faq_id": "aBcD1234eFgH5678"
}
```

---

## Eliminar una FAQ de un grupo

`DELETE /kb-groups/{groupId}/faqs/{faqId}`

Saca una FAQ de un grupo. La FAQ en sí no se elimina, y los agentes a los que ya se había aplicado el grupo la conservan.

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/faqs/aBcD1234eFgH5678?apiKey=YOUR_API_KEY"
```

**Respuesta**

```json
{
  "success": true,
  "group_id": "kbg_abc123",
  "faq_id": "aBcD1234eFgH5678"
}
```

---

## Aplicar un grupo a un agente

`POST /kb-groups/{groupId}/apply-to-agent`

Añade todas las FAQ del grupo al conocimiento de un agente de IA en una sola llamada: la forma rápida de dotar a un nuevo agente de un cuerpo de conocimiento que ya ha seleccionado.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `agent_id` | Sí | ID del agente de IA al que aplicar el grupo. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/apply-to-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agent_id": "ag7HkQ2ZpLxR3mNb" }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/apply-to-agent",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ agent_id: "ag7HkQ2ZpLxR3mNb" }),
  }
);
const { added_count } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/apply-to-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"agent_id": "ag7HkQ2ZpLxR3mNb"},
)
added_count = res.json()["added_count"]
```

**Respuesta**

```json
{
  "success": true,
  "group_id": "kbg_abc123",
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "added_count": 12
}
```

`added_count` es cuántas FAQ se añadieron realmente; `0` cuando el grupo está vacío o ya se ha aplicado.

---

## Aplicar un grupo a una campaña

`POST /kb-groups/{groupId}/apply-to-campaign`

La versión de campaña clásica de la llamada anterior. En una cuenta basada en agentes, utilice [Aplicar un grupo a un agente](#apply-a-group-to-an-agent) en su lugar.

**Campos de la solicitud**

| Campo | Obligatorio | Descripción |
|---|---|---|
| `campaign_id` | Sí | ID de la campaña a la que aplicar el grupo. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/kb-groups/kbg_abc123/apply-to-campaign?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "campaign_id": "campaign123" }'
```

**Respuesta**

```json
{
  "success": true,
  "group_id": "kbg_abc123",
  "campaign_id": "campaign123",
  "added_count": 12
}
```

---

## Errores de la API de la base de conocimientos

Estos endpoints devuelven el sobre de error estándar:

```json
{
  "success": false,
  "error": "Knowledge base source not found."
}
```

| Estado | Cuándo ocurre en un endpoint de la base de conocimientos |
|---|---|
| `400` | Falta un campo obligatorio o no es válido: un `url` vacío, falta un `baseUrl` o `jobId`, más de 100 URL en una importación masiva, más de 2000 ID en una eliminación masiva o un tipo de archivo que no podemos leer. |
| `402` | No hay suficientes créditos para ejecutar la importación. Recargue e inténtelo de nuevo. |
| `403` | Un `storage_path` fuera de su propia carpeta de cargas, o su plan no incluye acceso a la API. |
| `404` | No se encontró la fuente, el grupo, las preguntas frecuentes (FAQ), el agente, la campaña o el trabajo de actualización; o bien no existe o pertenece a otra cuenta. |

> **Los fallos leves no son errores.** La detección (`discover-pages`, `refresh-domain`) y el asistente de selección de páginas responden `200` con `success: false` y un mensaje `error` cuando no se puede leer el sitio web, en lugar de fallar la solicitud. Compruebe siempre `success` antes de leer los datos.

Los códigos compartidos que puede devolver cualquier endpoint — `401`, `403` (su plan no incluye acceso a la API), `429` (límite de tasa) y `500` — se enumeran con orientación sobre reintentos en [Errores y paginación](errors-and-pagination.md).

---

## Relacionado

- [API de preguntas frecuentes](faqs.md): lea, edite y vincule las preguntas frecuentes que generan sus fuentes.
- [Gestión de preguntas frecuentes](../ai-automation/faq-management.md): la misma base de conocimientos en el panel de control.
- [Agentes de IA](../ai-agents/ai-agents.md): los agentes a los que adjunta fuentes y grupos.
- [Acceso a la API](../integrations/api-access.md): genere su clave de API.
- [Autenticación](authentication.md): todas las formas de enviar su clave.
