
# Vidensbase-API

Din vidensbase er det, som AI'en læser fra. Den består af to dele, og denne side dækker begge:

- **Videnskilder** (`/kb-sources`) — de websider og uploadede dokumenter, du fodrer platformen med. Hver enkelt læses, opdeles i sektioner og omdannes til ofte stillede spørgsmål (FAQ'er), som din AI kan svare ud fra.
- **Vidensgrupper** (`/kb-groups`) — navngivne bundter af FAQ'er, som du kan anvende på en agent eller en kampagne i et enkelt kald, så en vidensmængde, du allerede har kurateret, kan genbruges på den næste agent, du opretter.

De FAQ'er, som en kilde producerer, lander i det samme bibliotek som dem, du skriver manuelt, så når en import er færdig, kan du læse, redigere og linke dem med [FAQ-API'en](faqs.md).

Alle endpoints herunder er relative til basis-URL'en `https://api.youraiconnector.com/v1`. Hver anmodning skal godkendes — se [API-adgang](../integrations/api-access.md) og [Godkendelse](authentication.md). API-adgang er en betalt funktion; uden den afvises anmodninger med en `403`.


> **Import koster kreditter.** At læse en side eller et dokument og skrive FAQ'er ud fra det forbruger kreditter, nogenlunde i forhold til hvor meget indhold der er. Brug [Estimer en import](#estimate-what-an-import-will-cost), før du forpligter dig til en stor crawl.

---

## Hvordan en import fungerer

Import er et baggrundsjob, ikke noget der afsluttes, mens du venter. Hvert import-slutpunkt svarer med det samme med et `source_id`, og du poller den kilde, indtil den er færdig:

1. **Start importen** — `POST /kb-sources/url` (én side), `POST /kb-sources/file` (et uploadet dokument) eller `POST /kb-sources/bulk-import` (op til 100 sider). Du får et kilde-id og et `status: "queued"` retur.
2. **Poll** — `GET /kb-sources/{sourceId}` indtil `status` ikke længere er `queued` eller `processing`.
3. **Læs FAQ'erne** — når status er `ready`, er de poster, den producerede, i dit FAQ-bibliotek: `GET /faqs`.

Hver kilde rapporterer en af disse statusser:

| Status | Hvad det betyder |
|---|---|
| `queued` | Venter på at blive læst. Der er endnu ikke trukket noget. |
| `processing` | Bliver læst og omdannet til FAQ'er lige nu. |
| `ready` | Færdig. Dens FAQ'er er i dit bibliotek. |
| `failed` | Kunne ikke importeres. `error_message` forklarer hvorfor. |
| `cancelled` | Stoppet før den blev læst (se [Stop en import](#stop-an-import)). |
| `paused` | Stoppet fordi din egen AI-nøgle fejlede midt i importen (se [Genoptag en pauset import](#resume-a-paused-import)). |
| `deleting` | En massefjernelse arbejder sig igennem den. |
| `unknown` | Posten har ingen status. Behandl den som ikke klar. |

> **Tilknyt mens du importerer.** Send `autoLinkToAgentId` til et hvilket som helst import-slutpunkt, og kilden — plus hver FAQ den producerer — lander på den agents viden i samme kald, uden et efterfølgende link-trin. `autoLinkToCampaignId` gør det samme for en klassisk kampagne. Linkning er en "best effort"-proces: et ID, der ikke eksisterer eller tilhører en anden konto, springes over uden fejlmeddelelse, og importen kører stadig, så bekræft linket ved at læse agenten tilbage.

---

## Importér en webside

`POST /kb-sources/url`

Tilføjer én webside til din vidensbase.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `url` | Ja | Fuld `http` eller `https` adresse på siden. |
| `autoLinkToAgentId` | Nej | ID på en AI-agent, som den importerede kilde skal tilknyttes. |
| `autoLinkToCampaignId` | Nej | Legacy. ID på en kampagne, som den importerede kilde skal tilknyttes. |

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

**Svar** — `202 Accepted`

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

Pol `source_id` med [Tjek en kilde](#check-a-source), indtil status er `ready` eller `failed`.

Hvis den samme side allerede findes i din vidensbase, bliver intet nyt sat i kø, og du får en `200` i stedet — og hvis du bad om et auto-link, bliver den eksisterende kilde linket til dig alligevel:

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

En manglende `url`, eller en der ikke er en gyldig `http`/`https` adresse, returnerer `400`.

---

## Importér et uploadet dokument

`POST /kb-sources/file`

Tilføjer et dokument, der **allerede er i din kontos fillager**, som en videnskilde. Understøttede typer: PDF, DOCX, TXT, MD, CSV og XLSX.

> **Dette endpoint indeholder ikke selve filen.** Der er intet multipart-upload, ingen base64-body og ingen download-fra-en-URL: du sender placeringen af en fil, der allerede eksisterer, og den skal ligge i din egen upload-mappe (`storage_path` skal starte med `users/{your user id}/uploads/`), ellers afvises anmodningen med `403`. Dashboardet placerer filer der, når du trækker dem ind. Hvis du ikke har mulighed for at placere en fil der, skal du i stedet importere en webside med [Importér en webside](#import-a-web-page).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `storage_path` | Ja | Hvor den uploadede fil ligger. Skal starte med `users/{your user id}/uploads/`. |
| `filename` | Ja | Oprindeligt filnavn inklusive filendelse — det er sådan, filtypen detekteres. |
| `mime_type` | Ja | MIME-type for filen, for eksempel `application/pdf`. |
| `autoLinkToAgentId` | Nej | ID på en AI-agent, som dokumentet skal tilknyttes. |
| `autoLinkToCampaignId` | Nej | Legacy. ID på en kampagne, som dokumentet skal tilknyttes. |

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

**Svar** — `202 Accepted`

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

| Status | Hvornår |
|---|---|
| `400` | Et påkrævet felt mangler, eller filen er af en type, vi ikke kan læse. |
| `403` | `storage_path` er uden for din egen upload-mappe. |

---

## Tjek en kilde

`GET /kb-sources/{sourceId}`

Det pol, der følger hver import og opdatering. Gentag det, indtil status er `ready` eller `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()
```

**Svar**

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

| Felt | Type | Beskrivelse |
|---|---|---|
| `status` | string | Hvor kilden befinder sig i pipelinen (se [statustabellen](#how-an-import-works)). |
| `faq_count` | integer | Hvor mange ofte stillede spørgsmål (FAQ'er) der er genereret fra denne kilde indtil videre. |
| `section_count` | integer | Hvor mange indholdssektioner kilden blev opdelt i. |
| `error_message` | string \| null | Hvorfor importen fejlede, når status er `failed`. `null` ellers. |

---

## Slet en kilde

`DELETE /kb-sources/{sourceId}`

Fjerner én videnskilde. **Som standard beholdes de FAQ'er, den har produceret** — tilføj `delete_faqs=true` for også at fjerne disse.

**Forespørgselsparametre**

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `delete_faqs` | Nej | Sæt til `true` for også at slette alle FAQ'er, som denne kilde har produceret. Standard er `false`. |

**cURL**

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

**Svar**

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

`faqs_deleted` er `0`, medmindre du har anmodet om `delete_faqs=true`.

---

## Importér mange sider på én gang

`POST /kb-sources/bulk-import`

Tilføjer op til 100 websider i ét kald — den sædvanlige opfølgning på [Find sider på et websted](#discover-pages-on-a-website) eller [Find nye sider på et websted](#find-new-pages-on-a-website). Sider, der allerede findes i din vidensbase, springes over i stedet for at blive duplikeret (og er stadig linket til agenten, hvis du har anmodet om det).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `urls` | Ja | Adresser der skal importeres. Mindst 1, højst 100 pr. kald. |
| `autoLinkToAgentId` | Nej | ID på en AI-agent, som hver importeret side skal tilknyttes. |
| `autoLinkToCampaignId` | Nej | Forældet. ID på en kampagne, som hver importeret side skal tilknyttes. |

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

**Svar** — `202 Accepted`

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

Forespørg hvert ID i `queued_source_ids` med [Tjek en kilde](#check-a-source). Afsendelse af et tomt `urls`-array, en post der ikke er en streng, eller mere end 100 poster returnerer `400`.

---

## Slet mange kilder på én gang

`POST /kb-sources/bulk-delete`

Fjerner op til 2.000 videnskilder i ét kald. Fjernelsen kører i baggrunden, og du modtager en e-mail, når den er færdig.

> **Massletning fjerner altid også FAQ'erne.** I modsætning til [Slet en kilde](#delete-a-source), som beholder dem, medmindre du beder om andet, sletter dette endepunkt hver kilde sammen med de FAQ'er, den har produceret. Der er ingen mulighed for at beholde dem.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `sourceIds` | Ja | ID'er på de kilder, der skal fjernes. Mindst 1, højst 2.000 pr. kald. |
| `domainLabel` | Nej | Et venligt navn til denne oprydning. Bruges kun i færdiggørelses-e-mailen. |

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

**Svar** — `202 Accepted`

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

---

## Find sider på et websted

`POST /kb-sources/discover-pages`

Udforsker et websted fra en startadresse og viser de sider, der findes på det samme domæne, hver med en vurdering af, om det er værd at importere. **Intet importeres, og intet vælges for dig** — dette er "hvad er der på dette websted"-trinnet, som du kører, før du beslutter, hvad der skal sendes til [Importér mange sider på én gang](#import-many-pages-at-once).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `url` | Ja | Adresse at starte udforskningen fra, normalt webstedets startside. |
| `maxPages` | Nej | Øvre grænse for, hvor mange sider der skal returneres. |

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

**Svar**

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

| Felt | Type | Beskrivelse |
|---|---|---|
| `source_type` | string | Hvordan siderne blev fundet — `sitemap` (webstedets eget sitemap) eller `link_discovery` (ved at følge links). |
| `url` | string | Fuld adresse på siden. |
| `title` | string \| null | Sidetitel, når en kunne læses. |
| `depth` | integer | Hvor mange links væk fra startsiden denne side blev fundet. |
| `score` | integer | Hvor nyttig siden ser ud som viden, fra `0` til `100`. |
| `recommendation` | string | `add` (helt klart værd at importere, score 90 eller derover), `maybe` (grænsetilfælde) eller `skip` (indhold, der sjældent hjælper en assistent — ændringslogs, juridiske sider, duplikerede oversættelser). |
| `reason_key` | string | En stabil, maskinlæsbar årsag bag anbefalingen, for eksempel `core_page`, `changelog_history`, `legal_page` eller `locale_duplicate`. |

> **Udforskning er efter bedste evne.** Hvis webstedet ikke kan læses, er svaret stadig `200`, med `success: false`, en tom `pages` liste og en `error` besked. Tjek `success` før du læser `pages`.

En manglende `url` returnerer `400`.

---

## Estimer hvad en import vil koste

`POST /kb-sources/estimate-cost`

Beregner hvor mange kreditter en foreslået import ville forbruge, før du forpligter dig til den. Sider hentes og dokumenter læses for at måle deres størrelse, men intet importeres, og selve estimatet bruger ikke kreditter.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `urls` | Nej | Sideadresser, som du overvejer at importere. |
| `files` | Nej | Allerede uploadede filer, som du overvejer. Hver post kræver `storage_path`, `filename` og `mime_type`. |
| `tier` | Nej | AI-kvalitetsniveauet, som importen vil køre på, så estimatet matcher det, du faktisk vil blive opkrævet. Udelad det for standardtaksten. |

Send `urls`, `files` eller begge dele.

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

**Svar**

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

Hver række gentager URL'en eller lagringsstien i `ref`, så du kan matche den med dit input. En side eller fil, der ikke kunne læses, får stadig en række, talt som én blok, med en `error` på.

---

## Stop en import

`POST /kb-sources/cancel-import`

Stopper sider, der stadig venter i importkøen — "stop import"-knappen til en crawl, der viste sig at være større, end du forventede. Det koster intet at annullere en ventende side, da den endnu ikke er blevet læst.

Sider, der allerede er under behandling, stoppes **ikke**: deres arbejde er i gang og bliver faktureret under alle omstændigheder, så de færdiggøres. Svaret rapporterer, hvor mange der var tale om.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `host` | Nej | Stop kun ventende sider på dette websted (for eksempel `docs.example.com`). Udelad dette for at stoppe alle ventende importer på kontoen. |

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

**Svar**

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

---

## Genoptag en pauset import

`POST /kb-sources/resume-import`

Genstarter en import, der blev pauset, fordi din egen AI-nøgle holdt op med at fungere.

> Ved at kalde denne **giver** du dit samtykke til at færdiggøre importen med den nøgle, der er aktiv nu — hvilket kan betyde brug af platform-kreditter, hvis din egen nøgle stadig er nede.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `host` | Nej | Genoptag kun pausede sider på dette websted. Udelad dette for at genoptage alt, der er pauset. |

**cURL**

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

**Svar**

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

---

## Find nye sider på et websted

`POST /kb-sources/refresh-domain`

Udforsker et websted, du allerede har importeret fra, og rapporterer kun de sider, der **ikke** er i din vidensbase endnu, hver med den samme anbefaling som ved sideopdagelse. Intet importeres, og intet ændres.

De to opfølgninger er bevidst separate kald, så det koster intet at forlade denne:

- importer de nye sider, du ønsker, med [Importér mange sider på én gang](#import-many-pages-at-once);
- genlæs de sider, du allerede har, med [Opdatér hver side på et websted](#refresh-every-page-on-a-website).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `baseUrl` | Ja | Enhver adresse på webstedet eller blot værten. |
| `maxPages` | Nej | Øvre grænse for, hvor mange sider der skal udforskes. |

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

**Svar**

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

| Felt | Type | Beskrivelse |
|---|---|---|
| `discovered` | integer | Hvor mange sider der i alt blev fundet på webstedet. |
| `new_pages` | array | Sider, der endnu ikke er i din vidensbase. Intet er sat i kø til dig — importér dem, du ønsker. |
| `new_urls_queued` | integer | Altid `0`. Beholdt for bagudkompatibilitet; dette endepunkt sætter aldrig noget i kø. |
| `existing_refresh_queued` | integer | Hvor mange sider, du allerede har importeret fra dette websted, der blev fundet klar til genlæsning. Intet sættes i kø af dette kald. |
| `batch_id` | string | Findes kun, når en batch blev oprettet. |

Ligesom opdagelse fejler dette blødt: et websted, der ikke kan læses, returnerer stadig `200` med `success: false`, en tom `new_pages` og en `error`. Et manglende eller tomt `baseUrl` returnerer `400`.

---

## Opdatér hver side på et websted

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

Genlæser hver side, du allerede har importeret fra et websted, så dens ofte stillede spørgsmål følger webstedets aktuelle indhold: ændrede sektioner opdateres, nye sektioner tilføjes, og fjernede sektioner slettes.

Dette sætter arbejde i kø og returnerer med det samme. Følg op med [Spor en webstedsopdatering](#track-a-website-refresh), og stop den med [Stop en webstedsopdatering](#stop-a-website-refresh).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `baseUrl` | Ja | Enhver adresse på webstedet eller blot værten. |

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

**Svar**

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

---

## Spor en webstedsopdatering

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

Hvor langt en webstedsopdatering er nået, så du kan vise fremskridt som "221 af 249".

**Forespørgselsparametre**

| Parameter | Påkrævet | Beskrivelse |
|---|---|---|
| `baseUrl` | Ja | Enhver adresse på webstedet eller blot værten. |

**cURL**

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

**Svar**

```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` er `null`, når ingen opdatering kører for det websted. Sider færdiggjort indtil videre er `total` minus `pending`. Jobbet `status` er et af `refreshing` (arbejder stadig gennem sider), `deduplicating` (oprydningspasset til sidst) eller det endelige `completed`, `failed` og `cancelled`. Behold `domainBatchId` — det er det, du sender til annulleringsendepunktet.

Et manglende eller tomt `baseUrl` returnerer `400`.

---

## Stop en opdatering af et websted

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

Stopper en opdatering af et websted, der stadig er i gang med at gennemgå sine sider. Sider, der allerede er færdige, beholder deres opdaterede indhold; sider, der ikke er påbegyndt, droppes, og sider, der var ved at blive genlæst, vender tilbage til deres tidligere tilstand.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `jobId` | Ja | Det `domainBatchId`, der returneres af [Spor en opdatering af et websted](#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" }'
```

**Svar**

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

| Felt | Type | Beskrivelse |
|---|---|---|
| `status` | string | Status for opdateringen efter dette kald: `cancelled`, `deduplicating`, `completed` eller `failed`. |
| `cancelled_units` | integer | Hvor meget arbejde der stadig udestod, da annulleringen blev modtaget. `0` ved en gentaget annullering. |
| `sources_reset` | integer | Sider, der blev taget ud af behandlingen og returneret til `ready`. |
| `sources_cancelled` | integer | Helt nye sider fra denne opdatering, der stadig lå i kø og nu er annulleret. |

Det er harmløst at annullere to gange — det andet kald rapporterer den samme endelige tilstand. Når opdateringen er gået videre til sin oprydningsfase, kan den ikke længere stoppes, og svaret returneres med `success: false` og `reason: "already_finalizing"`. Et manglende `jobId` returnerer `400`, og et job, der ikke findes på din konto, returnerer `404`.

---

## Opdater en enkelt kilde

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

Genlæser én webside, som du allerede har importeret, og bringer dens ofte stillede spørgsmål (FAQ) i overensstemmelse med sidens aktuelle indhold: ændrede sektioner opdateres, nye tilføjes, og fjernede sektioner slettes.

**cURL**

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

**Svar** — `202 Accepted`

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

Forespørg kilden, indtil dens status forlader `queued` og `processing`. Et kilde-ID, der ikke findes på din konto, returnerer `404`.

---

## Vælg de mest relevante sider

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

Beder AI'en om at vælge de fem sider ud fra en liste af kandidater, der bedst beskriver en virksomhed — bruges når der genereres en kampagne-playbook fra et websted. Dette forbruger kreditter.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `urls` | Ja | Kandidatsideadresser, der kan vælges imellem, normalt fra sideopdagelse. |
| `homeUrl` | Ja | Webstedets startside, der bruges som kontekst for valget. |

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

**Svar**

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

Dette er en hjælper, ikke en ressource: ved fejl svarer den stadig `200`, med `success: false`, en tom `pages` liste og en `error` besked.

---

## Vidensgrupper

En **vidensgruppe** er en navngiven samling af ofte stillede spørgsmål (FAQ'er) — "Forsendelse og returnering", "Onboarding" — som du kan anvende på en agent eller en kampagne i ét kald. Gruppen indeholder referencer, ikke kopier: selve FAQ'erne forbliver i dit centrale bibliotek, så hvis du redigerer en med [FAQs API](faqs.md), opdateres den overalt, hvor den bruges.

Anvendelse af en gruppe **tilføjer** kun det, der mangler, så det er harmløst at anvende den samme gruppe to gange, og `added_count` returneres som `0` anden gang.

---

## Opret en vidensgruppe

`POST /kb-groups`

Opretter en gruppe. Den starter tom — tilføj FAQ'er til den med [Tilføj en FAQ til en gruppe](#add-a-faq-to-a-group).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `name` | Ja | Navn på gruppen. |

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

**Svar** — `201 Created`

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

---

## Omdøb en vidensgruppe

`PUT /kb-groups/{groupId}`

Ændrer navnet på en gruppe. Dens FAQ'er forbliver uberørte.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `name` | Ja | Nyt navn til gruppen. |

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

**Svar**

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

---

## Slet en vidensgruppe

`DELETE /kb-groups/{groupId}`

Sletter gruppen. Kun samlingen fjernes — FAQ'erne i den forbliver i dit bibliotek, og alt, som gruppen allerede var anvendt på, beholder disse FAQ'er.

**cURL**

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

**Svar**

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

---

## Tilføj en FAQ til en gruppe

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

Placerer en eksisterende FAQ i en gruppe. Dette ændrer kun bundtet — det knytter ikke i sig selv FAQ'en til en Agent; anvend gruppen til det formål.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `faq_id` | Ja | ID på den FAQ, der skal tilføjes. |

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

**Svar**

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

---

## Fjern en FAQ fra en gruppe

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

Fjerner en FAQ fra en gruppe. Selve FAQ'en slettes ikke, og agenter, som gruppen allerede var anvendt på, beholder den.

**cURL**

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

**Svar**

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

---

## Anvend en gruppe på en agent

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

Tilføjer hver FAQ i gruppen til en AI-agents viden i ét kald — den hurtige måde at give en ny agent en vidensbase, som du allerede har kurateret.

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `agent_id` | Ja | ID på den AI-agent, som gruppen skal anvendes på. |

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

**Svar**

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

`added_count` er antallet af FAQ'er, der rent faktisk blev tilføjet — `0` når gruppen er tom eller allerede anvendt.

---

## Anvend en gruppe på en kampagne

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

Classic-kampagneversionen af kaldet ovenfor. På en agent-baseret konto skal du i stedet bruge [Anvend en gruppe på en agent](#apply-a-group-to-an-agent).

**Anmodningsfelter**

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `campaign_id` | Ja | ID på kampagnen, som gruppen skal anvendes på. |

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

**Svar**

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

---

## Knowledge Base API-fejl

Disse slutpunkter returnerer standardfejl-konvolutten:

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

| Status | Hvornår det sker på et knowledge base-slutpunkt |
|---|---|
| `400` | Et påkrævet felt mangler eller er ugyldigt — et tomt `url`, et manglende `baseUrl` eller `jobId`, mere end 100 URL'er i en bulk-import, mere end 2.000 ID'er i en bulk-sletning eller en filtype, vi ikke kan læse. |
| `402` | Ikke nok kreditter til at køre importen. Fyld op og prøv igen. |
| `403` | Et `storage_path` uden for din egen upload-mappe — eller din plan inkluderer ikke API-adgang. |
| `404` | Kilden, gruppen, FAQ'en, agenten, kampagnen eller opdateringsjobbet blev ikke fundet — enten eksisterer det ikke, eller også tilhører det en anden konto. |

> **Soft-fejl er ikke fejl.** Discovery (`discover-pages`, `refresh-domain`) og sidevalgs-hjælperen svarer `200` med `success: false` og en `error`-besked, når hjemmesiden ikke kan læses, i stedet for at fejle anmodningen. Tjek altid `success`, før du læser dataene.

De delte koder, som ethvert endpoint kan returnere — `401`, `403` (din plan inkluderer ikke API-adgang), `429` (rate limit) og `500` — er angivet med vejledning om genforsøg i [Errors & Pagination](errors-and-pagination.md).

---

## Relateret

- [FAQs API](faqs.md) — læs, rediger og link de FAQ'er, dine kilder producerer.
- [Håndtering af FAQ'er](../ai-automation/faq-management.md) — den samme vidensbase i dashboardet.
- [AI-agenter](../ai-agents/ai-agents.md) — de agenter, du tilknytter kilder og grupper til.
- [API-adgang](../integrations/api-access.md) — generer din API-nøgle.
- [Autentificering](authentication.md) — alle måder at angive din nøgle på.
