
# API da Base de Conhecimento

Sua base de conhecimento é de onde a IA lê as informações. Ela possui duas partes, e esta página cobre ambas:

- **Fontes de conhecimento** (`/kb-sources`) — as páginas da web e documentos enviados que você fornece à plataforma. Cada um é lido, dividido em seções e transformado em FAQs que sua IA pode usar para responder.
- **Grupos de conhecimento** (`/kb-groups`) — conjuntos nomeados de FAQs que você pode aplicar a um Agente ou a uma campanha em uma única chamada, para que um corpo de conhecimento que você já organizou possa ser reutilizado no próximo Agente que você criar.

As FAQs que uma fonte produz vão para a mesma biblioteca que aquelas que você escreve manualmente, portanto, assim que uma importação termina, você pode lê-las, editá-las e vinculá-las com a [API de FAQs](faqs.md).

Todos os endpoints abaixo são relativos à URL base `https://api.youraiconnector.com/v1`. Cada solicitação deve ser autenticada — consulte [Acesso à API](../integrations/api-access.md) e [Autenticação](authentication.md). O acesso à API é um recurso pago; sem ele, as solicitações são rejeitadas com um `403`.


> **A importação consome créditos.** Ler uma página ou documento e escrever FAQs a partir dele consome créditos, aproximadamente em proporção à quantidade de conteúdo existente. Use [Estimar uma importação](#estimate-what-an-import-will-cost) antes de se comprometer com um rastreamento grande.

---

## Como funciona uma importação

A importação é um trabalho em segundo plano, não algo que termina enquanto você espera. Cada endpoint de importação responde imediatamente com um `source_id`, e você consulta essa fonte até que ela esteja concluída:

1. **Inicie a importação** — `POST /kb-sources/url` (uma página), `POST /kb-sources/file` (um documento enviado) ou `POST /kb-sources/bulk-import` (até 100 páginas). Você recebe um ID de fonte e um `status: "queued"`.
2. **Consulte (Poll)** — `GET /kb-sources/{sourceId}` até que o `status` não seja mais `queued` ou `processing`.
3. **Leia as FAQs** — quando o status for `ready`, as entradas produzidas estarão em sua biblioteca de FAQs: `GET /faqs`.

Cada fonte relata um destes status:

| Status | O que significa |
|---|---|
| `queued` | Aguardando para ser lido. Nada foi cobrado ainda. |
| `processing` | Sendo lido e transformado em FAQs neste momento. |
| `ready` | Concluído. Suas FAQs estão na sua biblioteca. |
| `failed` | Não pôde ser importado. `error_message` indica o motivo. |
| `cancelled` | Interrompido antes de ser lido (veja [Parar uma importação](#stop-an-import)). |
| `paused` | Interrompido porque sua própria chave de IA falhou durante a importação (veja [Retomar uma importação pausada](#resume-a-paused-import)). |
| `deleting` | Uma remoção em massa está sendo processada. |
| `unknown` | O registro não possui status. Trate-o como não pronto. |

> **Vincule conforme você importa.** Passe `autoLinkToAgentId` em qualquer endpoint de importação e a fonte — além de cada FAQ que ela produz — será adicionada ao conhecimento daquele Agente na mesma chamada, sem necessidade de uma etapa de vinculação posterior. `autoLinkToCampaignId` faz o mesmo para uma campanha clássica. A vinculação é feita da melhor forma possível: um ID que não existe ou que pertence a outra conta é ignorado silenciosamente e a importação ainda é executada, portanto, confirme a vinculação lendo o Agente novamente.

---

## Importar uma página da web

`POST /kb-sources/url`

Adiciona uma página da web à sua base de conhecimento.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `url` | Sim | `http` ou `https` completo da página. |
| `autoLinkToAgentId` | Não | ID de um Agente de IA para anexar a fonte importada. |
| `autoLinkToCampaignId` | Não | Legado. ID de uma campanha para anexar a fonte 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")
```

**Resposta** — `202 Accepted`

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

Faça polling em `source_id` com [Verificar uma fonte](#check-a-source) até que o status seja `ready` ou `failed`.

Se a mesma página já estiver em sua base de conhecimento, nada de novo é colocado na fila e você recebe um `200` — e se você solicitou um link automático, a fonte existente é vinculada para você de qualquer maneira:

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

Um `url` ausente, ou um que não seja um endereço `http`/`https` válido, retorna `400`.

---

## Importar um documento enviado

`POST /kb-sources/file`

Adiciona um documento que **já está no armazenamento de arquivos da sua conta** como uma fonte de conhecimento. Tipos suportados: PDF, DOCX, TXT, MD, CSV e XLSX.

> **Este endpoint não transporta o arquivo.** Não há upload multipart, não há corpo base64 e não há download a partir de uma URL: você envia o local de armazenamento de um arquivo que já existe, e ele deve estar na sua própria pasta de uploads (`storage_path` deve começar com `users/{your user id}/uploads/`) ou a solicitação será recusada com `403`. O painel coloca os arquivos lá quando você os arrasta para dentro. Se você não tiver como colocar um arquivo lá, importe uma página da web com [Importar uma página da web](#import-a-web-page) em vez disso.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `storage_path` | Sim | Onde o arquivo enviado reside. Deve começar com `users/{your user id}/uploads/`. |
| `filename` | Sim | Nome original do arquivo, incluindo sua extensão — é assim que o tipo de arquivo é detectado. |
| `mime_type` | Sim | Tipo MIME do arquivo, por exemplo `application/pdf`. |
| `autoLinkToAgentId` | Não | ID de um Agente de IA para anexar o documento. |
| `autoLinkToCampaignId` | Não | Legado. ID de uma campanha para anexar o 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"
  }'
```

**Resposta** — `202 Accepted`

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

| Status | Quando |
|---|---|
| `400` | Um campo obrigatório está ausente, ou o arquivo não é de um tipo que podemos ler. |
| `403` | `storage_path` está fora da sua própria pasta de uploads. |

---

## Verificar uma fonte

`GET /kb-sources/{sourceId}`

O polling que segue cada importação e atualização. Repita-o até que o status seja `ready` ou `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()
```

**Resposta**

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

| Campo | Tipo | Descrição |
|---|---|---|
| `status` | string | Onde a fonte está no pipeline (veja a [tabela de status](#how-an-import-works)). |
| `faq_count` | integer | Quantas FAQs foram geradas a partir desta fonte até o momento. |
| `section_count` | integer | Em quantas seções de conteúdo a fonte foi dividida. |
| `error_message` | string \| null | Por que a importação falhou, quando o status é `failed`. `null` caso contrário. |

---

## Excluir uma fonte

`DELETE /kb-sources/{sourceId}`

Remove uma fonte de conhecimento. **Por padrão, as FAQs produzidas por ela são mantidas** — adicione `delete_faqs=true` para removê-las também.

**Parâmetros de consulta**

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `delete_faqs` | Não | Defina como `true` para também excluir todas as FAQs que esta fonte produziu. O padrão é `false`. |

**cURL**

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

**Resposta**

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

`faqs_deleted` é `0` a menos que você tenha solicitado `delete_faqs=true`.

---

## Importar várias páginas de uma vez

`POST /kb-sources/bulk-import`

Adiciona até 100 páginas da web em uma única chamada — o acompanhamento usual para [Descobrir páginas em um site](#discover-pages-on-a-website) ou [Encontrar novas páginas em um site](#find-new-pages-on-a-website). Páginas que já estão na sua base de conhecimento são ignoradas em vez de duplicadas (e ainda são vinculadas ao Agente quando você solicita isso).

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `urls` | Sim | Endereços para importar. Pelo menos 1, no máximo 100 por chamada. |
| `autoLinkToAgentId` | Não | ID de um Agente de IA para vincular a cada página importada. |
| `autoLinkToCampaignId` | Não | Legado. ID de uma campanha para vincular a 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"]
```

**Resposta** — `202 Accepted`

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

Verifique cada ID em `queued_source_ids` com [Verificar uma fonte](#check-a-source). Enviar um array `urls` vazio, uma entrada que não seja string ou mais de 100 entradas retorna `400`.

---

## Excluir várias fontes de uma vez

`POST /kb-sources/bulk-delete`

Remove até 2.000 fontes de conhecimento em uma única chamada. A remoção é executada em segundo plano e você recebe um e-mail quando ela for concluída.

> **A exclusão em massa sempre remove as FAQs também.** Diferente de [Excluir uma fonte](#delete-a-source), que as mantém a menos que você solicite o contrário, este endpoint exclui cada fonte juntamente com as FAQs que ela produziu. Não há opção para mantê-las.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `sourceIds` | Sim | IDs das fontes a serem removidas. Pelo menos 1, no máximo 2.000 por chamada. |
| `domainLabel` | Não | Um nome amigável para esta limpeza. Usado apenas no e-mail de conclusão. |

**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"
  }'
```

**Resposta** — `202 Accepted`

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

---

## Descobrir páginas em um site

`POST /kb-sources/discover-pages`

Explora um site a partir de um endereço inicial e lista as páginas encontradas no mesmo domínio, cada uma com uma opinião sobre se vale a pena importá-la. **Nada é importado e nada é selecionado para você** — este é o passo "o que há neste site" que você executa antes de decidir o que enviar para [Importar várias páginas de uma vez](#import-many-pages-at-once).

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `url` | Sim | Endereço para começar a explorar, geralmente a página inicial do site. |
| `maxPages` | Não | Limite superior de quantas páginas retornar. |

**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 }'
```

**Resposta**

```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 | Descrição |
|---|---|---|
| `source_type` | string | Como as páginas foram encontradas — `sitemap` (o sitemap do próprio site) ou `link_discovery` (seguindo links). |
| `url` | string | Endereço completo da página. |
| `title` | string \| null | Título da página, quando pôde ser lido. |
| `depth` | integer | A quantos links de distância da página inicial esta página foi encontrada. |
| `score` | integer | Quão útil a página parece como conhecimento, de `0` a `100`. |
| `recommendation` | string | `add` (claramente vale a pena importar, pontuação 90 ou superior), `maybe` (limítrofe) ou `skip` (conteúdo que raramente ajuda um assistente — logs de alterações, páginas legais, traduções duplicadas). |
| `reason_key` | string | Um motivo estável e legível por máquina por trás da recomendação, por exemplo `core_page`, `changelog_history`, `legal_page` ou `locale_duplicate`. |

> **A exploração é feita da melhor forma possível.** Se o site não puder ser lido, a resposta ainda será `200`, com `success: false`, uma lista `pages` vazia e uma mensagem `error`. Verifique `success` antes de ler `pages`.

Um `url` ausente retorna `400`.

---

## Estimar quanto custará uma importação

`POST /kb-sources/estimate-cost`

Calcula quantos créditos uma importação proposta consumiria, antes de você se comprometer com ela. As páginas são buscadas e os documentos são lidos para medir seu tamanho, mas nada é importado e a estimativa em si não gasta créditos.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `urls` | Não | Endereços de página que você está considerando importar. |
| `files` | Não | Arquivos já enviados que você está considerando. Cada entrada precisa de `storage_path`, `filename` e `mime_type`. |
| `tier` | Não | O nível de qualidade de IA em que a importação será executada, para que a estimativa corresponda ao que você será realmente cobrado. Deixe de fora para a taxa padrão. |

Envie `urls`, `files` ou 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"] }'
```

**Resposta**

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

Cada linha reflete a URL ou o caminho de armazenamento em `ref` para que você possa correspondê-lo à sua entrada. Uma página ou arquivo que não pôde ser lido ainda recebe uma linha, contada como um chunk, com um `error` nela.

---

## Parar uma importação

`POST /kb-sources/cancel-import`

Para páginas que ainda estão aguardando na fila de importação — o botão "parar importação" para um rastreamento que acabou sendo maior do que você esperava. Cancelar uma página em espera não custa nada, pois ela ainda não foi lida.

Páginas que já estão sendo processadas **não** são interrompidas: o trabalho delas está em andamento e é cobrado de qualquer forma, então elas são concluídas. A resposta informa quantas foram.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `host` | Não | Pare apenas as páginas em espera neste site (por exemplo, `docs.example.com`). Deixe em branco para parar todas as importações em espera na conta. |

**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" }'
```

**Resposta**

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

---

## Retomar uma importação pausada

`POST /kb-sources/resume-import`

Reinicia uma importação que foi pausada porque sua própria chave de IA parou de funcionar.

> Chamar isso **é** o seu consentimento para concluir a importação com qualquer chave que esteja ativa no momento — o que pode significar gastar créditos da plataforma se sua própria chave ainda estiver inativa.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `host` | Não | Retome apenas as páginas pausadas neste site. Deixe em branco para retomar tudo o que estiver 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 '{}'
```

**Resposta**

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

---

## Encontrar novas páginas em um site

`POST /kb-sources/refresh-domain`

Explora um site do qual você já importou e relata apenas as páginas que **ainda não** estão na sua base de conhecimento, cada uma com a mesma recomendação da descoberta de páginas. Nada é importado e nada é alterado.

Os dois acompanhamentos são chamadas deliberadamente separadas, portanto, desistir desta não custa nada:

- importe as novas páginas que você deseja com [Importar várias páginas de uma vez](#import-many-pages-at-once);
- releia as páginas que você já possui com [Atualizar todas as páginas de um site](#refresh-every-page-on-a-website).

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `baseUrl` | Sim | Qualquer endereço no site, ou apenas o host. |
| `maxPages` | Não | Limite superior de quantas 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" }'
```

**Resposta**

```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 | Descrição |
|---|---|---|
| `discovered` | integer | Quantas páginas foram encontradas no site no total. |
| `new_pages` | array | Páginas que ainda não estão na sua base de conhecimento. Nada é colocado na fila para você — importe as que desejar. |
| `new_urls_queued` | integer | Sempre `0`. Mantido para compatibilidade retroativa; este endpoint nunca coloca nada na fila. |
| `existing_refresh_queued` | integer | Quantas páginas que você já importou deste site foram encontradas prontas para serem relidas. Nada é colocado na fila por esta chamada. |
| `batch_id` | string | Presente apenas quando um lote foi criado. |

Assim como a descoberta, isso falha suavemente: um site que não pode ser lido ainda retorna `200`, com `success: false`, um `new_pages` vazio e um `error`. Um `baseUrl` ausente ou vazio retorna `400`.

---

## Atualizar todas as páginas de um site

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

Releia todas as páginas que você já importou de um site, para que suas FAQs sigam o conteúdo atual do site: seções alteradas são atualizadas, novas seções são adicionadas e seções removidas são descartadas.

Isso coloca o trabalho na fila e retorna imediatamente. Acompanhe com [Acompanhar uma atualização de site](#track-a-website-refresh) e interrompa com [Parar uma atualização de site](#stop-a-website-refresh).

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `baseUrl` | Sim | Qualquer endereço no site, ou apenas o 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" }'
```

**Resposta**

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

---

## Acompanhar uma atualização de site

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

O progresso de uma atualização de site, para que você possa exibir algo como "221 de 249".

**Parâmetros de consulta**

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `baseUrl` | Sim | Qualquer endereço no site, ou apenas o host. |

**cURL**

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

**Resposta**

```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` é `null` quando nenhuma atualização está sendo executada para aquele site. As páginas concluídas até o momento são `total` menos `pending`. O trabalho `status` é um entre `refreshing` (ainda processando páginas), `deduplicating` (a etapa de limpeza no final), ou os estados finais `completed`, `failed` e `cancelled`. Guarde o `domainBatchId` — é ele que você passa para o endpoint de cancelamento.

Um `baseUrl` ausente ou vazio retorna `400`.

---

## Interromper a atualização de um site

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

Interrompe a atualização de um site que ainda está processando suas páginas. As páginas já concluídas mantêm seu conteúdo atualizado; as páginas não iniciadas são descartadas, e as páginas que estavam sendo relidas retornam ao seu estado anterior.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `jobId` | Sim | O `domainBatchId` retornado por [Rastrear a atualização de um site](#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" }'
```

**Resposta**

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

| Campo | Tipo | Descrição |
|---|---|---|
| `status` | string | Estado da atualização após esta chamada: `cancelled`, `deduplicating`, `completed` ou `failed`. |
| `cancelled_units` | integer | Quanto trabalho ainda restava quando o cancelamento foi efetuado. `0` em um cancelamento repetido. |
| `sources_reset` | integer | Páginas removidas do processamento e retornadas para `ready`. |
| `sources_cancelled` | integer | Novas páginas desta atualização que ainda estavam na fila e agora foram canceladas. |

Cancelar duas vezes é inofensivo — a segunda chamada relata o mesmo estado final. Uma vez que a atualização tenha avançado para a etapa de limpeza, ela não pode mais ser interrompida, e a resposta retorna com `success: false` e `reason: "already_finalizing"`. Um `jobId` ausente retorna `400`, e um trabalho que não está em sua conta retorna `404`.

---

## Atualizar uma única fonte

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

Relê uma página da web que você já importou e alinha suas FAQs com o conteúdo atual da página: seções alteradas são atualizadas, novas são adicionadas e as removidas são descartadas.

**cURL**

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

**Resposta** — `202 Accepted`

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

Verifique a fonte até que seu status saia de `queued` e `processing`. Um ID de fonte que não está em sua conta retorna `404`.

---

## Escolher as páginas mais relevantes

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

Solicita à IA que escolha as cinco páginas, a partir de uma lista de candidatos, que melhor descrevem um negócio — usado ao gerar um manual de campanha a partir de um site. Isso consome créditos.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `urls` | Sim | Endereços de páginas candidatas para escolher, geralmente provenientes da descoberta de páginas. |
| `homeUrl` | Sim | A página inicial do site, usada como contexto para a escolha. |

**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"]
  }'
```

**Resposta**

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

Este é um auxiliar, não um recurso: em caso de falha, ele ainda responde `200`, com `success: false`, uma lista `pages` vazia e uma mensagem `error`.

---

## Grupos de conhecimento

Um **grupo de conhecimento** é um conjunto nomeado de FAQs — "Envio e devoluções", "Integração" — que você pode aplicar a um Agente ou a uma campanha em uma única chamada. O grupo contém referências, não cópias: as próprias FAQs permanecem em sua biblioteca única, portanto, editar uma delas com a [API de FAQs](faqs.md) a atualiza onde quer que ela seja usada.

Aplicar um grupo sempre **adiciona** apenas o que está faltando, portanto, aplicar o mesmo grupo duas vezes é inofensivo e `added_count` retorna como `0` na segunda vez.

---

## Criar um grupo de conhecimento

`POST /kb-groups`

Cria um grupo. Ele começa vazio — adicione FAQs a ele com [Adicionar uma FAQ a um grupo](#add-a-faq-to-a-group).

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `name` | Sim | Nome do 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"]
```

**Resposta** — `201 Created`

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

---

## Renomear um grupo de conhecimento

`PUT /kb-groups/{groupId}`

Altera o nome de um grupo. Suas FAQs permanecem inalteradas.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `name` | Sim | Novo nome para o 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" }'
```

**Resposta**

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

---

## Excluir um grupo de conhecimento

`DELETE /kb-groups/{groupId}`

Exclui o grupo. Apenas o conjunto é removido — as FAQs contidas nele permanecem em sua biblioteca, e tudo ao que o grupo já estava aplicado mantém essas FAQs.

**cURL**

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

**Resposta**

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

---

## Adicionar um FAQ a um grupo

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

Coloca um FAQ existente em um grupo. Isso altera apenas o pacote — não anexa o FAQ a nenhum Agente por si só; aplique o grupo para isso.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `faq_id` | Sim | ID do FAQ a ser adicionado. |

**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" }'
```

**Resposta**

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

---

## Remover um FAQ de um grupo

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

Remove um FAQ de um grupo. O FAQ em si não é excluído, e os Agentes aos quais o grupo já foi aplicado o mantêm.

**cURL**

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

**Resposta**

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

---

## Aplicar um grupo a um Agente

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

Adiciona todos os FAQs do grupo ao conhecimento de um Agente de IA em uma única chamada — a maneira rápida de fornecer a um novo Agente um corpo de conhecimento que você já curou.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `agent_id` | Sim | ID do Agente de IA ao qual o grupo será aplicado. |

**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"]
```

**Resposta**

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

`added_count` é a quantidade de FAQs que foram realmente adicionados — `0` quando o grupo está vazio ou já foi aplicado.

---

## Aplicar um grupo a uma campanha

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

A versão de campanha clássica da chamada acima. Em uma conta baseada em Agente, use [Aplicar um grupo a um Agente](#apply-a-group-to-an-agent) em vez disso.

**Campos da requisição**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `campaign_id` | Sim | ID da campanha à qual aplicar o 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" }'
```

**Resposta**

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

---

## Erros da API da Base de Conhecimento

Estes endpoints retornam o envelope de erro padrão:

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

| Status | Quando ocorre em um endpoint da base de conhecimento |
|---|---|
| `400` | Um campo obrigatório está ausente ou inválido — um `url` vazio, um `baseUrl` ou `jobId` ausente, mais de 100 URLs em uma importação em lote, mais de 2.000 IDs em uma exclusão em lote ou um tipo de arquivo que não conseguimos ler. |
| `402` | Créditos insuficientes para executar a importação. Recarregue e tente novamente. |
| `403` | Um `storage_path` fora da sua própria pasta de uploads — ou seu plano não inclui acesso à API. |
| `404` | A fonte, grupo, FAQ, Agente, campanha ou trabalho de atualização não foi encontrado — ou ele não existe ou pertence a outra conta. |

> **Falhas leves não são erros.** A descoberta (`discover-pages`, `refresh-domain`) e o auxiliar de seleção de página respondem `200` com `success: false` e uma mensagem `error` quando o site não pode ser lido, em vez de falhar na solicitação. Sempre verifique `success` antes de ler os dados.

Os códigos compartilhados que todo endpoint pode retornar — `401`, `403` (seu plano não inclui acesso à API), `429` (limite de taxa) e `500` — estão listados com orientações de nova tentativa em [Erros e Paginação](errors-and-pagination.md).

---

## Relacionado

- [API de FAQs](faqs.md) — leia, edite e vincule as FAQs que suas fontes produzem.
- [Gerenciando FAQs](../ai-automation/faq-management.md) — a mesma base de conhecimento no painel.
- [Agentes de IA](../ai-agents/ai-agents.md) — os Agentes aos quais você anexa fontes e grupos.
- [Acesso à API](../integrations/api-access.md) — gere sua chave de API.
- [Autenticação](authentication.md) — todas as maneiras de passar sua chave.
