
# API Basis Pengetahuan

Basis pengetahuan Anda adalah sumber bacaan AI. Basis ini terdiri dari dua bagian, dan halaman ini membahas keduanya:

- **Sumber pengetahuan** (`/kb-sources`) — halaman web dan dokumen yang diunggah yang Anda masukkan ke platform. Masing-masing dibaca, dibagi menjadi beberapa bagian, dan diubah menjadi FAQ yang dapat dijawab oleh AI Anda.
- **Grup pengetahuan** (`/kb-groups`) — kumpulan FAQ bernama yang dapat Anda terapkan ke Agen atau kampanye dalam satu panggilan, sehingga kumpulan pengetahuan yang telah Anda kurasi dapat digunakan kembali pada Agen berikutnya yang Anda buat.

FAQ yang dihasilkan oleh sumber akan masuk ke pustaka yang sama dengan FAQ yang Anda tulis secara manual, jadi setelah impor selesai, Anda dapat membaca, mengedit, dan menautkannya dengan [API FAQ](faqs.md).

Semua endpoint di bawah ini bersifat relatif terhadap URL dasar `https://api.youraiconnector.com/v1`. Setiap permintaan harus diautentikasi — lihat [Akses API](../integrations/api-access.md) dan [Autentikasi](authentication.md). Akses API adalah fitur berbayar; tanpanya, permintaan akan ditolak dengan `403`.


> **Mengimpor memerlukan kredit.** Membaca halaman atau dokumen dan menulis FAQ darinya akan menghabiskan kredit, kira-kira sebanding dengan jumlah konten yang ada. Gunakan [Perkirakan impor](#estimate-what-an-import-will-cost) sebelum melakukan crawling dalam jumlah besar.

---

## Cara kerja impor

Impor adalah pekerjaan latar belakang, bukan sesuatu yang selesai saat Anda menunggu. Setiap endpoint impor akan langsung menjawab dengan `source_id`, dan Anda melakukan polling pada sumber tersebut hingga selesai:

1. **Mulai impor** — `POST /kb-sources/url` (satu halaman), `POST /kb-sources/file` (dokumen yang diunggah), atau `POST /kb-sources/bulk-import` (hingga 100 halaman). Anda akan mendapatkan ID sumber dan `status: "queued"`.
2. **Polling** — `GET /kb-sources/{sourceId}` hingga `status` tidak lagi `queued` atau `processing`.
3. **Baca FAQ** — saat statusnya `ready`, entri yang dihasilkan ada di pustaka FAQ Anda: `GET /faqs`.

Setiap sumber melaporkan salah satu status berikut:

| Status | Artinya |
|---|---|
| `queued` | Menunggu untuk dibaca. Belum ada biaya yang dikenakan. |
| `processing` | Sedang dibaca dan diubah menjadi FAQ saat ini. |
| `ready` | Selesai. FAQ-nya ada di pustaka Anda. |
| `failed` | Tidak dapat diimpor. `error_message` menjelaskan alasannya. |
| `cancelled` | Dihentikan sebelum dibaca (lihat [Hentikan impor](#stop-an-import)). |
| `paused` | Dihentikan karena kunci AI Anda gagal di tengah impor (lihat [Lanjutkan impor yang dijeda](#resume-a-paused-import)). |
| `deleting` | Penghapusan massal sedang memprosesnya. |
| `unknown` | Catatan tidak memiliki status. Anggap sebagai belum siap. |

> **Lampirkan saat Anda mengimpor.** Teruskan `autoLinkToAgentId` pada endpoint impor mana pun dan sumber tersebut — ditambah setiap FAQ yang dihasilkannya — akan langsung masuk ke pengetahuan Agen tersebut dalam panggilan yang sama, tanpa langkah penautan lanjutan. `autoLinkToCampaignId` melakukan hal yang sama untuk kampanye klasik. Penautan dilakukan dengan upaya terbaik: ID yang tidak ada, atau milik akun lain, akan dilewati secara diam-diam dan impor tetap berjalan, jadi konfirmasikan tautan dengan membaca kembali Agen tersebut.

---

## Impor halaman web

`POST /kb-sources/url`

Menambahkan satu halaman web ke basis pengetahuan Anda.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `url` | Ya | Alamat `http` atau `https` lengkap dari halaman tersebut. |
| `autoLinkToAgentId` | Tidak | ID Agen AI untuk melampirkan sumber yang diimpor. |
| `autoLinkToCampaignId` | Tidak | Warisan. ID kampanye untuk melampirkan sumber yang diimpor. |

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

**Respons** — `202 Accepted`

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

Lakukan polling `source_id` dengan [Periksa sumber](#check-a-source) hingga statusnya menjadi `ready` atau `failed`.

Jika halaman yang sama sudah ada di basis pengetahuan Anda, tidak ada yang baru yang diantrekan dan Anda akan mendapatkan `200` sebagai gantinya — dan jika Anda meminta tautan otomatis, sumber yang ada akan ditautkan untuk Anda:

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

`url` yang hilang, atau yang bukan merupakan alamat `http`/`https` yang valid, akan mengembalikan `400`.

---

## Impor dokumen yang diunggah

`POST /kb-sources/file`

Menambahkan dokumen yang **sudah ada di penyimpanan file akun Anda** sebagai sumber pengetahuan. Jenis yang didukung: PDF, DOCX, TXT, MD, CSV, dan XLSX.

> **Endpoint ini tidak membawa file.** Tidak ada unggahan multipart, tidak ada body base64, dan tidak ada unduhan dari URL: Anda mengirim lokasi penyimpanan file yang sudah ada, dan file tersebut harus berada di bawah folder unggahan Anda sendiri (`storage_path` harus dimulai dengan `users/{your user id}/uploads/`) atau permintaan akan ditolak dengan `403`. Dasbor menempatkan file di sana saat Anda menyeretnya ke dalam. Jika Anda tidak memiliki cara untuk menempatkan file di sana, impor halaman web dengan [Impor halaman web](#import-a-web-page) sebagai gantinya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `storage_path` | Ya | Tempat file yang diunggah berada. Harus dimulai dengan `users/{your user id}/uploads/`. |
| `filename` | Ya | Nama file asli termasuk ekstensinya — ini adalah cara jenis file dideteksi. |
| `mime_type` | Ya | Tipe MIME file, contohnya `application/pdf`. |
| `autoLinkToAgentId` | Tidak | ID Agen AI untuk melampirkan dokumen tersebut. |
| `autoLinkToCampaignId` | Tidak | Warisan. ID kampanye untuk melampirkan dokumen tersebut. |

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

**Respons** — `202 Accepted`

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

| Status | Kapan |
|---|---|
| `400` | Bidang wajib tidak ada, atau file bukan jenis yang dapat kami baca. |
| `403` | `storage_path` berada di luar folder unggahan Anda sendiri. |

---

## Periksa sumber

`GET /kb-sources/{sourceId}`

Polling yang mengikuti setiap impor dan penyegaran. Ulangi hingga statusnya menjadi `ready` atau `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()
```

**Respons**

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

| Bidang | Tipe | Deskripsi |
|---|---|---|
| `status` | string | Di mana sumber berada dalam pipeline (lihat [tabel status](#how-an-import-works)). |
| `faq_count` | integer | Berapa banyak FAQ yang telah dibuat dari sumber ini sejauh ini. |
| `section_count` | integer | Berapa banyak bagian konten yang dipecah dari sumber tersebut. |
| `error_message` | string \| null | Mengapa impor gagal, saat statusnya adalah `failed`. `null` jika tidak. |

---

## Menghapus sumber

`DELETE /kb-sources/{sourceId}`

Menghapus satu sumber pengetahuan. **Secara default, FAQ yang dihasilkannya akan tetap disimpan** — tambahkan `delete_faqs=true` untuk menghapusnya juga.

**Parameter kueri**

| Parameter | Wajib | Deskripsi |
|---|---|---|
| `delete_faqs` | Tidak | Atur ke `true` untuk juga menghapus setiap FAQ yang dihasilkan oleh sumber ini. Default-nya adalah `false`. |

**cURL**

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

**Respons**

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

`faqs_deleted` adalah `0` kecuali jika Anda meminta `delete_faqs=true`.

---

## Mengimpor banyak halaman sekaligus

`POST /kb-sources/bulk-import`

Menambahkan hingga 100 halaman web dalam satu panggilan — tindak lanjut yang biasa dilakukan setelah [Menemukan halaman di situs web](#discover-pages-on-a-website) atau [Mencari halaman baru di situs web](#find-new-pages-on-a-website). Halaman yang sudah ada di basis pengetahuan Anda akan dilewati alih-alih diduplikasi (dan tetap ditautkan ke Agen saat Anda memintanya).

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `urls` | Ya | Alamat untuk diimpor. Minimal 1, maksimal 100 per panggilan. |
| `autoLinkToAgentId` | Tidak | ID Agen AI untuk melampirkan setiap halaman yang diimpor. |
| `autoLinkToCampaignId` | Tidak | Warisan. ID kampanye untuk melampirkan setiap halaman yang diimpor. |

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

**Respons** — `202 Accepted`

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

Polling setiap ID di `queued_source_ids` dengan [Memeriksa sumber](#check-a-source). Mengirim array `urls` kosong, entri non-string, atau lebih dari 100 entri akan mengembalikan `400`.

---

## Menghapus banyak sumber sekaligus

`POST /kb-sources/bulk-delete`

Menghapus hingga 2.000 sumber pengetahuan dalam satu panggilan. Penghapusan berjalan di latar belakang dan Anda akan mendapatkan email setelah selesai.

> **Penghapusan massal juga akan menghapus FAQ.** Berbeda dengan [Hapus sumber](#delete-a-source), yang menyimpannya kecuali Anda meminta sebaliknya, endpoint ini menghapus setiap sumber beserta FAQ yang dihasilkannya. Tidak ada opsi untuk menyimpannya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `sourceIds` | Ya | ID sumber yang akan dihapus. Minimal 1, maksimal 2.000 per panggilan. |
| `domainLabel` | Tidak | Nama yang mudah diingat untuk pembersihan ini. Hanya digunakan dalam email penyelesaian. |

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

**Respons** — `202 Accepted`

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

---

## Menemukan halaman di situs web

`POST /kb-sources/discover-pages`

Menjelajahi situs web dari satu alamat awal dan mencantumkan halaman yang ditemukan di domain yang sama, masing-masing dengan pendapat mengenai apakah halaman tersebut layak diimpor. **Tidak ada yang diimpor dan tidak ada yang dipilihkan untuk Anda** — ini adalah langkah "apa yang ada di situs ini" yang Anda jalankan sebelum memutuskan apa yang akan dikirim ke [Impor banyak halaman sekaligus](#import-many-pages-at-once).

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `url` | Ya | Alamat untuk mulai menjelajah, biasanya halaman beranda situs. |
| `maxPages` | Tidak | Batas atas jumlah halaman yang akan dikembalikan. |

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

**Respons**

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

| Bidang | Tipe | Deskripsi |
|---|---|---|
| `source_type` | string | Bagaimana halaman ditemukan — `sitemap` (peta situs milik situs itu sendiri) atau `link_discovery` (dengan mengikuti tautan). |
| `url` | string | Alamat lengkap halaman. |
| `title` | string \| null | Judul halaman, jika dapat dibaca. |
| `depth` | integer | Seberapa jauh jarak tautan dari halaman awal halaman ini ditemukan. |
| `score` | integer | Seberapa berguna halaman tersebut sebagai pengetahuan, dari `0` hingga `100`. |
| `recommendation` | string | `add` (jelas layak diimpor, skor 90 atau lebih), `maybe` (perbatasan), atau `skip` (konten yang jarang membantu asisten — log perubahan, halaman hukum, terjemahan duplikat). |
| `reason_key` | string | Alasan yang stabil dan dapat dibaca mesin di balik rekomendasi tersebut, misalnya `core_page`, `changelog_history`, `legal_page` atau `locale_duplicate`. |

> **Eksplorasi adalah upaya terbaik.** Jika situs tidak dapat dibaca, responsnya tetap `200`, dengan `success: false`, daftar `pages` kosong, dan pesan `error`. Periksa `success` sebelum membaca `pages`.

`url` yang hilang akan mengembalikan `400`.

---

## Memperkirakan biaya impor

`POST /kb-sources/estimate-cost`

Menghitung berapa banyak kredit yang akan dikonsumsi oleh usulan impor, sebelum Anda berkomitmen. Halaman diambil dan dokumen dibaca untuk mengukur ukurannya, tetapi tidak ada yang diimpor dan perkiraan itu sendiri tidak menghabiskan kredit.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `urls` | Tidak | Alamat halaman yang sedang Anda pertimbangkan untuk diimpor. |
| `files` | Tidak | File yang sudah diunggah yang sedang Anda pertimbangkan. Setiap entri memerlukan `storage_path`, `filename`, dan `mime_type`. |
| `tier` | Tidak | Tingkat kualitas AI yang akan digunakan untuk impor, sehingga perkiraan sesuai dengan apa yang sebenarnya akan dibebankan kepada Anda. Kosongkan untuk tarif standar. |

Kirim `urls`, `files`, atau keduanya.

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

**Respons**

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

Setiap baris menggemakan kembali URL atau jalur penyimpanan di `ref` sehingga Anda dapat mencocokkannya dengan input Anda. Halaman atau file yang tidak dapat dibaca tetap mendapatkan baris, dihitung sebagai satu potongan, dengan `error` di atasnya.

---

## Menghentikan impor

`POST /kb-sources/cancel-import`

Menghentikan halaman yang masih menunggu dalam antrean impor — tombol "hentikan impor" untuk perayapan yang ternyata lebih besar dari yang Anda perkirakan. Membatalkan halaman yang menunggu tidak memakan biaya, karena halaman tersebut belum dibaca.

Halaman yang sudah diproses **tidak** dihentikan: pekerjaannya sedang berlangsung dan tetap dikenakan biaya, jadi prosesnya akan selesai. Respons akan melaporkan berapa banyak jumlahnya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `host` | Tidak | Hanya hentikan halaman yang menunggu di situs web ini (contohnya `docs.example.com`). Kosongkan untuk menghentikan setiap impor yang menunggu di akun. |

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

**Respons**

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

---

## Melanjutkan impor yang dijeda

`POST /kb-sources/resume-import`

Memulai ulang impor yang dijeda karena kunci AI Anda sendiri berhenti berfungsi.

> Memanggil ini **berarti** Anda setuju untuk menyelesaikan impor menggunakan kunci mana pun yang aktif saat ini — yang mungkin berarti menggunakan kredit platform jika kunci Anda sendiri masih tidak berfungsi.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `host` | Tidak | Hanya lanjutkan halaman yang dijeda di situs web ini. Kosongkan untuk melanjutkan semua yang dijeda. |

**cURL**

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

**Respons**

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

---

## Menemukan halaman baru di situs web

`POST /kb-sources/refresh-domain`

Menjelajahi situs web yang sudah pernah Anda impor dan hanya melaporkan halaman yang **belum** ada di basis pengetahuan Anda, masing-masing dengan rekomendasi yang sama seperti penemuan halaman. Tidak ada yang diimpor dan tidak ada yang diubah.

Dua tindak lanjut tersebut sengaja dipisahkan menjadi panggilan yang berbeda, jadi meninggalkan yang satu ini tidak memakan biaya:

- impor halaman baru yang Anda inginkan dengan [Impor banyak halaman sekaligus](#import-many-pages-at-once);
- baca ulang halaman yang sudah Anda miliki dengan [Segarkan setiap halaman di situs web](#refresh-every-page-on-a-website).

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `baseUrl` | Ya | Alamat apa pun di situs web, atau cukup host-nya saja. |
| `maxPages` | Tidak | Batas atas jumlah halaman yang akan dijelajahi. |

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

**Respons**

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

| Bidang | Tipe | Deskripsi |
|---|---|---|
| `discovered` | integer | Total berapa banyak halaman yang ditemukan di situs tersebut. |
| `new_pages` | array | Halaman yang belum ada di basis pengetahuan Anda. Tidak ada yang diantrekan untuk Anda — impor halaman yang Anda inginkan. |
| `new_urls_queued` | integer | Selalu `0`. Dipertahankan untuk kompatibilitas mundur; titik akhir ini tidak pernah mengantrekan apa pun. |
| `existing_refresh_queued` | integer | Berapa banyak halaman yang sudah Anda impor dari situs ini yang ditemukan siap untuk dibaca ulang. Tidak ada yang diantrekan oleh panggilan ini. |
| `batch_id` | string | Hanya muncul saat batch dibuat. |

Seperti penemuan, ini gagal dengan lembut: situs yang tidak dapat dibaca tetap mengembalikan `200`, dengan `success: false`, `new_pages` kosong, dan `error`. `baseUrl` yang hilang atau kosong mengembalikan `400`.

---

## Segarkan setiap halaman di situs web

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

Membaca ulang setiap halaman yang sudah Anda impor dari situs web, sehingga FAQ-nya mengikuti konten situs saat ini: bagian yang diubah diperbarui, bagian baru ditambahkan, dan bagian yang dihapus dibuang.

Ini mengantrekan pekerjaan dan segera kembali. Ikuti dengan [Lacak penyegaran situs web](#track-a-website-refresh), dan hentikan dengan [Hentikan penyegaran situs web](#stop-a-website-refresh).

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `baseUrl` | Ya | Alamat apa pun di situs web, atau cukup host-nya saja. |

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

**Respons**

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

---

## Lacak penyegaran situs web

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

Sejauh mana penyegaran situs web berlangsung, sehingga Anda dapat menampilkan progres seperti "221 dari 249".

**Parameter kueri**

| Parameter | Wajib | Deskripsi |
|---|---|---|
| `baseUrl` | Ya | Alamat apa pun di situs web, atau cukup host-nya saja. |

**cURL**

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

**Respons**

```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` adalah `null` ketika tidak ada penyegaran yang berjalan untuk situs web tersebut. Halaman yang selesai sejauh ini adalah `total` dikurangi `pending`. Pekerjaan `status` adalah salah satu dari `refreshing` (masih memproses halaman), `deduplicating` (tahap pembersihan di akhir), atau `completed`, `failed`, dan `cancelled` terakhir. Simpan `domainBatchId` — ini adalah apa yang Anda teruskan ke titik akhir pembatalan.

`baseUrl` yang hilang atau kosong mengembalikan `400`.

---

## Menghentikan penyegaran situs web

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

Menghentikan penyegaran situs web yang masih memproses halamannya. Halaman yang sudah selesai akan tetap mempertahankan konten yang diperbarui; halaman yang belum dimulai akan dibatalkan, dan halaman yang sedang dibaca ulang akan kembali ke status sebelumnya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `jobId` | Ya | `domainBatchId` yang dikembalikan oleh [Lacak penyegaran situs 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" }'
```

**Respons**

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

| Bidang | Tipe | Deskripsi |
|---|---|---|
| `status` | string | Status penyegaran setelah panggilan ini: `cancelled`, `deduplicating`, `completed`, atau `failed`. |
| `cancelled_units` | integer | Seberapa banyak pekerjaan yang masih tertunda saat pembatalan dilakukan. `0` pada pembatalan berulang. |
| `sources_reset` | integer | Halaman yang ditarik kembali dari pemrosesan dan dikembalikan ke `ready`. |
| `sources_cancelled` | integer | Halaman baru dari penyegaran ini yang masih dalam antrean dan sekarang dibatalkan. |

Membatalkan dua kali tidak akan menimbulkan masalah — panggilan kedua akan melaporkan status akhir yang sama. Setelah penyegaran beralih ke tahap pembersihan, proses tersebut tidak dapat lagi dihentikan, dan respons yang dikembalikan adalah `success: false` dan `reason: "already_finalizing"`. `jobId` yang tidak ditemukan akan mengembalikan `400`, dan pekerjaan yang tidak ada di akun Anda akan mengembalikan `404`.

---

## Menyegarkan satu sumber

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

Membaca ulang satu halaman web yang telah Anda impor dan menyelaraskan kembali FAQ-nya dengan konten halaman saat ini: bagian yang diubah akan diperbarui, bagian baru akan ditambahkan, dan bagian yang dihapus akan dibuang.

**cURL**

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

**Respons** — `202 Accepted`

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

Lakukan polling pada sumber hingga statusnya berubah dari `queued` dan `processing`. ID sumber yang tidak ada di akun Anda akan mengembalikan `404`.

---

## Memilih halaman yang paling relevan

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

Meminta AI untuk memilih lima halaman, dari daftar kandidat, yang paling mendeskripsikan suatu bisnis — digunakan saat membuat buku panduan kampanye dari situs web. Proses ini menggunakan kredit.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `urls` | Ya | Alamat halaman kandidat untuk dipilih, biasanya dari penemuan halaman. |
| `homeUrl` | Ya | Halaman beranda situs, digunakan sebagai konteks untuk pilihan tersebut. |

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

**Respons**

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

Ini adalah helper, bukan resource: jika gagal, ia tetap menjawab `200`, dengan `success: false`, daftar `pages` kosong, dan pesan `error`.

---

## Grup pengetahuan

**Grup pengetahuan** adalah kumpulan FAQ bernama — "Pengiriman dan pengembalian", "Onboarding" — yang dapat Anda terapkan ke Agen atau kampanye dalam satu panggilan. Grup ini menyimpan referensi, bukan salinan: FAQ itu sendiri tetap berada di pustaka tunggal Anda, jadi mengedit satu FAQ dengan [FAQs API](faqs.md) akan memperbaruinya di mana pun FAQ tersebut digunakan.

Menerapkan grup hanya akan **menambahkan** apa yang kurang, jadi menerapkan grup yang sama dua kali tidak akan menimbulkan masalah dan `added_count` akan kembali sebagai `0` pada kali kedua.

---

## Membuat grup pengetahuan

`POST /kb-groups`

Membuat sebuah grup. Grup dimulai dalam keadaan kosong — tambahkan FAQ ke dalamnya dengan [Menambahkan FAQ ke grup](#add-a-faq-to-a-group).

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `name` | Ya | Nama grup. |

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

**Respons** — `201 Created`

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

---

## Mengubah nama grup pengetahuan

`PUT /kb-groups/{groupId}`

Mengubah nama grup. FAQ di dalamnya tidak akan terpengaruh.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `name` | Ya | Nama baru untuk grup. |

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

**Respons**

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

---

## Menghapus grup pengetahuan

`DELETE /kb-groups/{groupId}`

Menghapus grup. Hanya bundelnya yang dihapus — FAQ di dalamnya tetap ada di pustaka Anda, dan apa pun yang sebelumnya telah menerapkan grup tersebut akan tetap memiliki FAQ tersebut.

**cURL**

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

**Respons**

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

---

## Menambahkan FAQ ke grup

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

Memasukkan FAQ yang sudah ada ke dalam grup. Ini hanya mengubah bundel — tindakan ini tidak melampirkan FAQ ke Agen mana pun secara mandiri; gunakan grup untuk melakukannya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `faq_id` | Ya | ID FAQ yang akan ditambahkan. |

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

**Respons**

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

---

## Menghapus FAQ dari grup

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

Mengeluarkan FAQ dari grup. FAQ itu sendiri tidak dihapus, dan Agen yang sebelumnya telah menerapkan grup tersebut akan tetap memilikinya.

**cURL**

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

**Respons**

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

---

## Menerapkan grup ke Agen

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

Menambahkan setiap FAQ dalam grup ke pengetahuan Agen AI dalam satu panggilan — cara cepat untuk memberikan kumpulan pengetahuan yang telah Anda kurasi kepada Agen baru.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `agent_id` | Ya | ID Agen AI yang akan diterapkan grup tersebut. |

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

**Respons**

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

`added_count` adalah jumlah FAQ yang sebenarnya ditambahkan — `0` jika grup kosong atau sudah diterapkan.

---

## Menerapkan grup ke kampanye

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

Versi kampanye klasik dari panggilan di atas. Pada akun berbasis Agen, gunakan [Menerapkan grup ke Agen](#apply-a-group-to-an-agent) sebagai gantinya.

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `campaign_id` | Ya | ID kampanye untuk menerapkan grup tersebut. |

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

**Respons**

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

---

## Kesalahan API Knowledge Base

Endpoint ini mengembalikan amplop kesalahan standar:

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

| Status | Kapan ini terjadi pada endpoint knowledge base |
|---|---|
| `400` | Bidang wajib tidak ada atau tidak valid — `url` kosong, `baseUrl` atau `jobId` yang hilang, lebih dari 100 URL dalam impor massal, lebih dari 2.000 ID dalam penghapusan massal, atau jenis file yang tidak dapat kami baca. |
| `402` | Kredit tidak cukup untuk menjalankan impor. Isi ulang dan coba lagi. |
| `403` | `storage_path` di luar folder unggahan Anda sendiri — atau paket Anda tidak menyertakan akses API. |
| `404` | Sumber, grup, FAQ, Agen, kampanye, atau pekerjaan penyegaran tidak ditemukan — entah karena tidak ada atau milik akun lain. |

> **Kegagalan ringan bukanlah kesalahan.** Penemuan (`discover-pages`, `refresh-domain`) dan pembantu pemilihan halaman menjawab `200` dengan `success: false` dan pesan `error` saat situs web tidak dapat dibaca, alih-alih menggagalkan permintaan. Selalu periksa `success` sebelum membaca data.

Kode bersama yang dapat dikembalikan oleh setiap endpoint — `401`, `403` (paket Anda tidak menyertakan akses API), `429` (batas kecepatan) dan `500` — tercantum beserta panduan percobaan ulang di [Kesalahan & Penomoran Halaman](errors-and-pagination.md).

---

## Terkait

- [API FAQ](faqs.md) — membaca, mengedit, dan menautkan FAQ yang dihasilkan sumber Anda.
- [Mengelola FAQ](../ai-automation/faq-management.md) — knowledge base yang sama di dasbor.
- [Agen AI](../ai-agents/ai-agents.md) — Agen yang Anda lampirkan sumber dan grupnya.
- [Akses API](../integrations/api-access.md) — buat kunci API Anda.
- [Autentikasi](authentication.md) — semua cara untuk mengirimkan kunci Anda.
