
# FAQs-API

FAQs sind die Frage-Antwort-Einträge, auf die Ihr KI-Bot bei der Beantwortung von Kundenanfragen zurückgreift. Jedes FAQ gehört zu Ihrem Konto und kann mit einer oder mehreren Kampagnen verknüpft werden, sodass dieselbe Antwort überall dort wiederverwendet werden kann, wo sie relevant ist. Mit der FAQs-API können Sie diese Bibliothek programmgesteuert verwalten – FAQs erstellen, aktualisieren, per Massenimport hochladen, neu anordnen und aus Ihrem eigenen Code heraus mit Kampagnen verknüpfen.

Alle unten aufgeführten Endpunkte beziehen sich auf die Basis-URL `https://api.youraiconnector.com/v1`. Jede Anfrage muss authentifiziert sein – siehe [API-Zugriff](../integrations/api-access.md) und [Authentifizierung](authentication.md). Der API-Zugriff ist eine kostenpflichtige Funktion; ohne diesen werden Anfragen mit einem `403` abgelehnt.

> **Wie der Bot ein FAQ verwendet:** Wenn Sie ein FAQ erstellen oder ändern, bereitet die Plattform im Hintergrund dessen Suchdaten vor (die verwendet werden, um das FAQ mit eingehenden Fragen abzugleichen). Dies dauert in der Regel nur wenige Sekunden, danach beginnt der Bot automatisch mit der Verwendung des Eintrags.


---

## Das FAQ-Objekt

Jedes FAQ, das von der API zurückgegeben wird, hat diese Struktur:

| Feld | Typ | Beschreibung |
|---|---|---|
| `id` | string | Die eindeutige Kennung des FAQ-Eintrags. |
| `question` | string | Die Kundenfrage, die dieser Eintrag beantwortet. |
| `answer` | string | Die Antwort, die der KI-Bot gibt. |
| `category` | string \| null | Optionales, frei wählbares Kategorielabel. |
| `tags` | string[] | Optionale Labels zur Organisation von FAQs. |
| `is_active` | boolean | Gibt an, ob der Bot dieses FAQ verwenden darf. Standardwert ist `true`. |
| `is_global` | boolean | Kennzeichnet das FAQ als nicht an eine bestimmte Kampagne oder einen Agenten gebunden. Dies bedeutet nicht, dass das FAQ überall gilt: Ein FAQ wird nur von den Kampagnen und Agenten verwendet, mit denen es verknüpft ist. Standardwert ist `false`. |
| `usage_count` | integer | Wie oft dieses FAQ in KI-Antworten verwendet wurde. |
| `order_index` | integer | Anzeigeposition dieses FAQs innerhalb seiner Kampagne. |
| `campaign_ids` | string[] | IDs der Kampagnen, mit denen dieses FAQ verknüpft ist. |
| `created_at` | string \| null | ISO 8601-Zeitstempel der Erstellung des FAQs. |
| `updated_at` | string \| null | ISO 8601-Zeitstempel der letzten Änderung. |

Die Felder, die Sie **festlegen** können, sind: `question`, `answer`, `is_active`, `is_global`, `category`, `tags` und `order_index`. Die Plattform verwaltet alles andere (Suchdaten, Nutzungszahlen, Zeitstempel); alle anderen Felder in Ihrem Anfrage-Body werden ignoriert.

---

## FAQs auflisten

`GET /faqs`

Gibt die FAQs in Ihrem Konto zurück, beginnend mit den neuesten. Optional können Sie nach einer einzelnen Kampagne oder nach dem Aktivitätsstatus filtern.

**Abfrageparameter**

| Parameter | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Nein | Gibt nur FAQs zurück, die mit dieser Kampagne verknüpft sind. |
| `is_active` | Nein | Gibt nur FAQs mit diesem Aktivitätsstatus zurück (`true` oder `false`). Dieser Filter wird pro Seite angewendet, daher kann eine Seite weniger Elemente enthalten als `limit`. |
| `limit` | Nein | Maximale Anzahl an FAQs pro Seite. Standardwert `50`, Maximum `100`. |
| `cursor` | Nein | Eine FAQ-ID, nach der fortgefahren werden soll. Übergeben Sie den `next_cursor`-Wert von der vorherigen Seite. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/faqs?campaign_id=campaign123&limit=50&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs?campaign_id=campaign123&limit=50",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.faqs, data.next_cursor);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/faqs",
    params={"campaign_id": "campaign123", "limit": 50},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["faqs"], data["next_cursor"])
```

**Antwort**

```json
{
  "success": true,
  "faqs": [
    {
      "id": "aBcD1234eFgH5678",
      "question": "How long does shipping take?",
      "answer": "Standard shipping takes 3-5 business days.",
      "category": "shipping",
      "tags": ["logistics", "delivery"],
      "is_active": true,
      "is_global": false,
      "usage_count": 12,
      "order_index": 0,
      "campaign_ids": ["campaign123"],
      "created_at": "2026-01-01T12:00:00.000Z",
      "updated_at": "2026-01-02T08:30:00.000Z"
    }
  ],
  "next_cursor": "aBcD1234eFgH5678"
}
```

Wenn `next_cursor` `null` ist, gibt es keine weiteren Ergebnisse.

---

## FAQ abrufen

`GET /faqs/{faqId}`

Gibt eine einzelne FAQ anhand ihrer ID zurück.

**cURL**

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

**JavaScript**

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

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
faq = res.json()["faq"]
```

**Antwort**

```json
{
  "success": true,
  "faq": {
    "id": "aBcD1234eFgH5678",
    "question": "How long does shipping take?",
    "answer": "Standard shipping takes 3-5 business days.",
    "category": "shipping",
    "tags": ["logistics"],
    "is_active": true,
    "is_global": false,
    "usage_count": 12,
    "order_index": 0,
    "campaign_ids": ["campaign123"],
    "created_at": "2026-01-01T12:00:00.000Z",
    "updated_at": "2026-01-02T08:30:00.000Z"
  }
}
```

---

## FAQ erstellen

`POST /faqs`

Erstellt eine neue FAQ und verknüpft sie mit einer Kampagne.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, mit der die neue FAQ verknüpft werden soll. |
| `question` | Ja | Die Kundenfrage, die dieser Eintrag beantwortet. |
| `answer` | Ja | Die Antwort, die der Bot geben soll. |
| `is_active` | Nein | Ob der Bot diese FAQ verwenden darf. Standardwert ist `true`. |
| `is_global` | Nein | Ob die FAQ für alle Kampagnen gilt. Standardwert ist `false`. |
| `category` | Nein | Ein frei wählbares Kategorielabel. |
| `tags` | Nein | Ein Array von Labels. |
| `order_index` | Nein | Anzeigeposition innerhalb der Kampagne. Standardwert ist `0`. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "campaign123",
    "question": "How long does shipping take?",
    "answer": "Standard shipping takes 3-5 business days.",
    "category": "shipping",
    "tags": ["logistics"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaign_id: "campaign123",
    question: "How long does shipping take?",
    answer: "Standard shipping takes 3-5 business days.",
    category: "shipping",
    tags: ["logistics"],
  }),
});
const { faq_id } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "campaign123",
        "question": "How long does shipping take?",
        "answer": "Standard shipping takes 3-5 business days.",
        "category": "shipping",
        "tags": ["logistics"],
    },
)
faq_id = res.json()["faq_id"]
```

**Antwort**

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

---

## FAQ aktualisieren

`PUT /faqs/{faqId}`

Aktualisiert eine FAQ teilweise. Nur die bereitgestellten beschreibbaren Felder werden geändert; alles andere behält seinen aktuellen Wert bei. Das Ändern von `question` oder `answer` aktualisiert automatisch die Suchdaten der FAQ im Hintergrund.

Wenn Sie `question` oder `answer` senden, müssen dies nicht leere Zeichenfolgen sein. Das Senden ohne erkannte beschreibbare Felder führt zu einer `400`.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ is_active: false }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"is_active": False},
)
data = res.json()
```

**Antwort**

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

---

## FAQ löschen

`DELETE /faqs/{faqId}`

Löscht eine FAQ dauerhaft. Übergeben Sie optional `campaign_id` als Abfrageparameter, um die FAQ auch aus der FAQ-Liste dieser Kampagne zu entfernen.

**Abfrageparameter**

| Parameter | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Nein | Entfernt auch die FAQ aus der FAQ-Liste dieser Kampagne. |

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678?campaign_id=campaign123&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678?campaign_id=campaign123",
  { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678",
    params={"campaign_id": "campaign123"},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

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

---

## FAQs massenhaft löschen

`POST /faqs/bulk-delete`

Löscht bis zu 500 FAQs in einer einzigen Anfrage. Wenn `campaign_id` angegeben ist, werden die gelöschten FAQs auch aus der FAQ-Liste dieser Kampagne entfernt.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `faq_ids` | Ja | Ein nicht leeres Array von FAQ-IDs, die gelöscht werden sollen (max. 500). |
| `campaign_id` | Nein | Entfernt die gelöschten FAQs auch aus der FAQ-Liste dieser Kampagne. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/bulk-delete?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "faq_ids": ["faqId1", "faqId2"], "campaign_id": "campaign123" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/bulk-delete", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    faq_ids: ["faqId1", "faqId2"],
    campaign_id: "campaign123",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/bulk-delete",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"faq_ids": ["faqId1", "faqId2"], "campaign_id": "campaign123"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "deleted_count": 2
}
```

---

## FAQ-Import

`POST /faqs/import`

Importieren Sie bis zu 500 FAQs in einem Vorgang und verknüpfen Sie diese mit einer Kampagne. Elemente, deren `question` mit einer bestehenden FAQ in Ihrer Bibliothek übereinstimmt (Groß-/Kleinschreibung wird ignoriert), **aktualisieren** diese FAQ, anstatt ein Duplikat zu erstellen.

> **Performance-Tipp:** Der Abgleich von Duplikaten durchsucht Ihre gesamte FAQ-Bibliothek. Sehr große Bibliotheken verlangsamen daher den Import. Bevorzugen Sie weniger, dafür größere Importe gegenüber vielen kleinen.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, mit der alle importierten FAQs verknüpft werden. |
| `faqs` | Ja | Ein nicht leeres Array von FAQ-Elementen (max. 500). Jedes Element muss ein nicht leeres `question` und `answer` enthalten; es kann zudem `is_active`, `is_global`, `category`, `tags` und `order_index` enthalten. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "campaign123",
    "faqs": [
      { "question": "Do you ship internationally?", "answer": "Yes, we ship to most countries worldwide." },
      { "question": "What is your return policy?", "answer": "You can return any item within 30 days." }
    ]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/import", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaign_id: "campaign123",
    faqs: [
      {
        question: "Do you ship internationally?",
        answer: "Yes, we ship to most countries worldwide.",
      },
      {
        question: "What is your return policy?",
        answer: "You can return any item within 30 days.",
      },
    ],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/import",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "campaign123",
        "faqs": [
            {"question": "Do you ship internationally?", "answer": "Yes, we ship to most countries worldwide."},
            {"question": "What is your return policy?", "answer": "You can return any item within 30 days."},
        ],
    },
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "faq_ids": ["aBcD1234eFgH5678", "iJkL9012mNoP3456"],
  "imported_count": 2
}
```

`faq_ids` sind die erstellten oder aktualisierten FAQ-IDs in der Reihenfolge, in der Sie sie bereitgestellt haben.

---

## FAQs neu anordnen

`POST /faqs/reorder`

Legt die Anzeigereihenfolge der FAQs einer Kampagne fest. Geben Sie die **vollständige** Liste der FAQ-IDs in der gewünschten Reihenfolge an; die Position jeder FAQ wird entsprechend ihrer Stelle im Array aktualisiert.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, deren FAQs neu sortiert werden. |
| `ordered_faq_ids` | Ja | Ein nicht leeres Array aller FAQ-IDs der Kampagne in der gewünschten Anzeigereihenfolge (max. 500). |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/reorder?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "campaign123",
    "ordered_faq_ids": ["faqId2", "faqId1", "faqId3"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/reorder", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaign_id: "campaign123",
    ordered_faq_ids: ["faqId2", "faqId1", "faqId3"],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/reorder",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "campaign123",
        "ordered_faq_ids": ["faqId2", "faqId1", "faqId3"],
    },
)
data = res.json()
```

**Antwort**

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

Wenn die Kampagne oder eine der FAQ-IDs nicht in Ihrem Konto gefunden wird, gibt die Anfrage `404 One or more FAQs were not found` zurück.

---

## FAQ mit einer Kampagne verknüpfen

`POST /faqs/{faqId}/link`

Verknüpft eine bestehende FAQ mit einer zusätzlichen Kampagne. Eine FAQ kann von beliebig vielen Kampagnen geteilt werden, sodass dieselbe Antwort nur einmal gepflegt werden muss.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, mit der die FAQ verknüpft werden soll. |

**cURL**

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

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/link",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ campaign_id: "campaign456" }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/link",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"campaign_id": "campaign456"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "faq_id": "aBcD1234eFgH5678",
  "campaign_id": "campaign456"
}
```

---

## FAQ von einer Kampagne entknüpfen

`POST /faqs/{faqId}/unlink`

Entfernt eine FAQ aus einer Kampagne, ohne die FAQ selbst zu löschen. Die FAQ bleibt in Ihrer Bibliothek und ist weiterhin mit allen anderen Kampagnen verknüpft.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, aus der die FAQ entfernt werden soll. |

**cURL**

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

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/unlink",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ campaign_id: "campaign456" }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/unlink",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"campaign_id": "campaign456"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "faq_id": "aBcD1234eFgH5678",
  "campaign_id": "campaign456"
}
```

---

## Suchdaten einer FAQ neu erstellen

`POST /faqs/{faqId}/rebuild-embeddings`

Reiht eine Neuerstellung der Daten ein, die der KI-Bot verwendet, um diese FAQ zu finden (seine semantischen und Keyword-Suchdaten). Dies ist nützlich, wenn eine FAQ nicht wie erwartet in Antworten berücksichtigt wird. Die Neuerstellung läuft im Hintergrund und ist normalerweise innerhalb weniger Sekunden abgeschlossen; die FAQ kann vorübergehend von KI-Antworten ausgeschlossen sein, während sie neu erstellt wird.

Dieser Endpunkt gibt `202 Accepted` zurück, da die Arbeit nach dem Senden der Antwort fortgesetzt wird. Der `status` ist immer `"processing"` — rufen Sie die FAQ später erneut ab, wenn Sie den Abschluss bestätigen müssen.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/rebuild-embeddings?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/rebuild-embeddings",
  { method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/rebuild-embeddings",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "faq_id": "aBcD1234eFgH5678",
  "status": "processing"
}
```

---

## KI-gestützte FAQ-Verwaltung

Die folgenden Endpunkte gehen über einfaches CRUD hinaus: Sie rufen dieselben KI-Assistenz-Tools auf, die auch der FAQ-Editor im Dashboard verwendet – sie finden Duplikate, generieren Einträge aus einem Dokument und ordnen FAQs offenen Wissenslücken zu. Die Request-Bodies in diesem Set verwenden `camelCase`-Feldnamen (`campaignId`, `taskId`, `sourceIds`...), die den Request-Formaten der App entsprechen, anstatt der `snake_case`, die an anderer Stelle auf dieser Seite verwendet werden – kopieren Sie die folgenden Beispiele, anstatt Feldnamen zu erraten.

### Eine FAQ in eine kampagnenspezifische Kopie umwandeln

`POST /faqs/{faqId}/fork-for-campaign`

Erstellt eine neue FAQ, die eine Kopie einer bestehenden ist, auf eine einzelne Kampagne beschränkt ist und diese Kampagne mit der neuen Kopie anstelle des Originals verknüpft. Verwenden Sie dies, wenn Sie eine Antwort für eine Kampagne anpassen möchten, ohne sie überall dort zu ändern, wo die ursprüngliche FAQ verwendet wird. Die ursprüngliche FAQ bleibt erhalten – sie verliert lediglich die Verknüpfung zu dieser Kampagne.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaign_id` | Ja | Die Kampagne, auf die die neue Kopie beschränkt werden soll und von der die ursprüngliche FAQ entkoppelt wird. |
| `question` | Ja | Die Frage für die neue, kampagnenspezifische Kopie. |
| `answer` | Ja | Die Antwort für die neue, kampagnenspezifische Kopie. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/fork-for-campaign?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "campaign456",
    "question": "How long does shipping take to the EU?",
    "answer": "For EU orders, shipping takes 7-10 business days."
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/fork-for-campaign",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      campaign_id: "campaign456",
      question: "How long does shipping take to the EU?",
      answer: "For EU orders, shipping takes 7-10 business days.",
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/aBcD1234eFgH5678/fork-for-campaign",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "campaign456",
        "question": "How long does shipping take to the EU?",
        "answer": "For EU orders, shipping takes 7-10 business days.",
    },
)
data = res.json()
```

**Antwort** — `201 Created`

```json
{
  "success": true,
  "faq_id": "nEwFaQiD9012mNoP",
  "campaign_id": "campaign456",
  "original_faq_id": "aBcD1234eFgH5678"
}
```

### Nahezu identische FAQs finden

`POST /faqs/dedupe`

Startet einen Hintergrundjob, der Ihre FAQ-Bibliothek nach nahezu identischen und sich überschneidenden Einträgen durchsucht und diese zusammenführt oder entfernt, sofern das System sich sicher ist. Nützlich nach einem Massenimport oder nachdem mehrere Runden KI-generierter FAQs zu Überschneidungen in der Bibliothek geführt haben. Es kann immer nur ein Deduplizierungs-Job pro Konto gleichzeitig ausgeführt werden – der Start eines zweiten Jobs, während einer noch läuft, gibt `409` zurück.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `sourceIds` | Nein | Array von Wissensdatenbank-Quell-IDs, auf die die Deduplizierung beschränkt werden soll. Lassen Sie dies weg, um Ihre gesamte FAQ-Bibliothek zu scannen. |

**cURL**

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

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/dedupe", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/dedupe",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={},
)
data = res.json()
```

**Antwort** — `202 Accepted`

```json
{
  "success": true,
  "job_id": "dedupJob_aBc123"
}
```

Der Job läuft im Hintergrund und dauert bei einer großen Bibliothek normalerweise einige Minuten. Es gibt keinen separaten Status-Endpunkt – rufen Sie nach einer kurzen Wartezeit erneut [`GET /faqs`](#list-faqs) auf, um zu sehen, was sich geändert hat. Wenn Sie mit der Überprüfung des Ergebnisses fertig sind, rufen Sie den unten stehenden Dismiss-Endpunkt auf, um es zu löschen.

### Ein Ergebnis der Duplikatprüfung verwerfen

`POST /faqs/dedupe/dismiss`

Löscht den abgeschlossenen Deduplizierungs-Job, sodass er nicht mehr als aktives Ergebnis angezeigt wird. Idempotent – kann sicher aufgerufen werden, auch wenn es nichts zu verwerfen gibt. Gibt `409` zurück, wenn der Job noch `queued` oder `processing` ist (Sie können einen Lauf, der noch nicht abgeschlossen ist, nicht verwerfen).

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/dedupe/dismiss?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/dedupe/dismiss", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/dedupe/dismiss",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

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

### FAQs aus hochgeladenen Dokumenten generieren

`POST /faqs/generate-from-documents`

Liest ein oder mehrere Dokumente, die sich bereits im Dateispeicher Ihres Kontos befinden, und lässt die KI FAQs aus deren Inhalt entwerfen. Dabei werden die Entwürfe mit Ihrer bestehenden Bibliothek abgeglichen, sodass Einträge wiederverwendet oder aktualisiert werden, anstatt Duplikate zu erstellen. Die Ergebnisse werden **nicht** sofort geschrieben – sie werden als ausstehender Änderungssatz für die Kampagne gespeichert, damit Sie diese überprüfen und anschließend mit [Überprüfte FAQ-Änderungen anwenden](#apply-reviewed-faq-changes) weiter unten übernehmen (oder verwerfen) können. Dies kostet Credits, da es sich um einen KI-Generierungsvorgang für den Dokumententext handelt.

Dieser Endpunkt überträgt die Datei nicht: `storagePath` muss auf eine Datei verweisen, die sich bereits in Ihrem eigenen Upload-Ordner (`users/{your user id}/uploads/`) befindet; dies folgt derselben Konvention wie [Ein hochgeladenes Dokument importieren](knowledge-base.md#import-an-uploaded-document) in der Knowledge-Base-API.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaignId` | Ja | Die Kampagne, für die die generierten FAQs vorgeschlagen werden. |
| `uploadedFiles` | Ja | Nicht leeres Array von zu lesenden Dateien, jeweils `{ storagePath, fileName, mimeType }`. `storagePath` muss mit `users/{your user id}/uploads/` beginnen. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/generate-from-documents?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignId": "campaign123",
    "uploadedFiles": [
      { "storagePath": "users/abc123uid/uploads/handbook.pdf", "fileName": "handbook.pdf", "mimeType": "application/pdf" }
    ]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/generate-from-documents", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaignId: "campaign123",
    uploadedFiles: [
      { storagePath: "users/abc123uid/uploads/handbook.pdf", fileName: "handbook.pdf", mimeType: "application/pdf" },
    ],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/generate-from-documents",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaignId": "campaign123",
        "uploadedFiles": [
            {"storagePath": "users/abc123uid/uploads/handbook.pdf", "fileName": "handbook.pdf", "mimeType": "application/pdf"},
        ],
    },
)
data = res.json()
```

**Antwort** — `202 Accepted`

```json
{
  "success": true,
  "faqCount": 6,
  "reusedCount": 2,
  "modifiedCount": 1,
  "newCount": 3
}
```

`faqCount` ist die Gesamtzahl der vorgeschlagenen Änderungen, die auf eine Überprüfung warten; `reusedCount`, `modifiedCount` und `newCount` unterteilen dies in FAQs, die unverändert mit einem bestehenden Eintrag übereinstimmten, solche, die die KI zur Bearbeitung vorschlägt, und völlig neue. Hochgeladene Dateien werden nach Abschluss der Verarbeitung aus dem Speicher gelöscht, unabhängig davon, ob der Vorgang erfolgreich war oder nicht.

### Überprüfte FAQ-Änderungen anwenden

`POST /faqs/apply-optimization`

Wendet einen ausstehenden Satz von KI-vorgeschlagenen FAQ-Änderungen an (oder verwirft ihn) – die Art, die durch [FAQs aus Dokumenten generieren](#generate-faqs-from-uploaded-documents) oben oder durch die FAQ-Optimierungsprüfung im Dashboard erstellt wurde. Sie wählen genau aus, welche vorgeschlagenen Änderungen akzeptiert werden sollen; alles, was Sie nicht erwähnen, bleibt unberührt (eine ausgelassene Änderung wird niemals als Ablehnung behandelt, die etwas löscht).

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `campaignId` | Eines von beiden | Die Kampagne, deren ausstehende FAQ-Änderungen angewendet werden. |
| `agentId` | Eines von beiden | Der KI-Agent, dessen ausstehende FAQ-Änderungen auf einem Agent-nativen Konto angewendet werden. Geben Sie genau eines von `campaignId` / `agentId` an, niemals beide. |
| `acceptedChanges` | Ja | Array der Änderungen, die Sie akzeptieren, jeweils `{ action, faq_id?, faq_ref_path?, question?, answer?, edit_scope? }`. `action` ist eines von `keep`, `remove`, `add_from_library`, `create_new`, `modify`. Senden Sie ein leeres Array, um den ausstehenden Satz zu verwerfen, ohne etwas anzuwenden. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/apply-optimization?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignId": "campaign123",
    "acceptedChanges": [
      { "action": "create_new", "question": "Do you ship to the EU?", "answer": "Yes, EU shipping takes 7-10 business days." },
      { "action": "remove", "faq_ref_path": "users/abc123uid/faqs/oldFaqId" }
    ]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/apply-optimization", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaignId: "campaign123",
    acceptedChanges: [
      { action: "create_new", question: "Do you ship to the EU?", answer: "Yes, EU shipping takes 7-10 business days." },
      { action: "remove", faq_ref_path: "users/abc123uid/faqs/oldFaqId" },
    ],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/apply-optimization",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaignId": "campaign123",
        "acceptedChanges": [
            {"action": "create_new", "question": "Do you ship to the EU?", "answer": "Yes, EU shipping takes 7-10 business days."},
            {"action": "remove", "faq_ref_path": "users/abc123uid/faqs/oldFaqId"},
        ],
    },
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "message": "Applied 2 FAQ changes",
  "faq_count": 7
}
```

`faq_count` ist die Gesamtzahl der verknüpften FAQs der Kampagne (oder des Agenten) nach der Anwendung. Wenn kein ausstehender Änderungssatz zum Anwenden vorhanden war, lautet die Antwort `{ "success": true, "message": "No pending FAQ changes to apply" }`.

### FAQs finden, die einer Aufgabe ähneln

`POST /faqs/similar-for-task`

Bewertet Ihre FAQ-Bibliothek nach Relevanz für die Frage einer Wissenslücken-Aufgabe – dieselbe Suche, die hinter der Auswahl "Vorhandene FAQ verwenden" im Dashboard steht. Nur lesend. `taskId` muss auf eine Aufgabe vom Typ `faq_update` verweisen.

Dieser Endpunkt antwortet immer mit `200`, selbst bei einem erwarteten Fehler wie einer unbekannten Aufgabe – prüfen Sie `success` im Body anstelle des HTTP-Status.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `taskId` | Ja | Die `faq_update` Aufgabe, für die Übereinstimmungen gesucht werden sollen. |
| `limit` | Nein | Maximale Anzahl der zurückzugebenden Übereinstimmungen. Standardwert ist 20, maximal 50. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/similar-for-task?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "taskId": "task789", "limit": 10 }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/similar-for-task", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ taskId: "task789", limit: 10 }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/similar-for-task",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"taskId": "task789", "limit": 10},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "data": {
    "task_id": "task789",
    "matches": [
      {
        "faq_id": "aBcD1234eFgH5678",
        "question": "How long does shipping take?",
        "answer": "Standard shipping takes 3-5 business days.",
        "category": "shipping",
        "created_at": "2026-01-01T12:00:00.000Z",
        "similarity": 0.81,
        "embedding_similarity": 0.81,
        "keyword_similarity": 0.6,
        "bm25_score": 4.2,
        "distance": 0.19
      }
    ]
  }
}
```

Übereinstimmungen werden nach `similarity` sortiert (semantische Übereinstimmung, falls verfügbar, ansonsten Schlüsselwort-Überschneidung), beginnend mit der besten. Bei einem Soft-Fehler ist die Struktur `{ "success": false, "error": "...", "error_code": 404 }` – `error_code` spiegelt wider, was der HTTP-Status normalerweise wäre.

### Eine Aufgabe mit einem bestehenden FAQ lösen

`POST /faqs/resolve-task`

Löst eine Wissenslücken-Aufgabe, indem sie mit einem bereits vorhandenen FAQ verknüpft wird (anstatt ein neues zu schreiben), sendet die Antwort dieses FAQs an den Kontakt, der die Lücke ausgelöst hat, und markiert die Aufgabe als abgeschlossen. Verwenden Sie dies, nachdem [Ähnliche FAQs zu einer Aufgabe finden](#find-faqs-similar-to-a-task) ein bestehendes FAQ ergeben hat, das die Frage bereits abdeckt.

Wie der obige Endpunkt antwortet dieser immer mit `200` – prüfen Sie `success` im Body.

**Anfragefelder**

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `taskId` | Ja | Die `faq_update` Aufgabe, die gelöst werden soll. |
| `faqId` | Ja | Das bestehende FAQ, das verknüpft und als Antwort gesendet werden soll. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/faqs/resolve-task?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "taskId": "task789", "faqId": "aBcD1234eFgH5678" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/faqs/resolve-task", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ taskId: "task789", faqId: "aBcD1234eFgH5678" }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/faqs/resolve-task",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"taskId": "task789", "faqId": "aBcD1234eFgH5678"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "data": {
    "task_id": "task789",
    "faq_id": "aBcD1234eFgH5678",
    "follow_up_status": "published"
  }
}
```

`follow_up_status` gibt an, was mit der Kontakt-Nachverfolgung passiert ist: `published` (sofort gesendet), `queued` (die KI antwortete bereits diesem Kontakt, daher wird sie als Nächstes gesendet), `skipped_no_contact` (die Aufgabe hat keinen verknüpften Kontakt) oder `skipped_no_campaign` (keine Kampagne, über die sie gesendet werden könnte).

---

## FAQs API-Fehler

FAQ-Endpunkte geben den Standard-Fehler-Envelope zurück:

```json
{
  "success": false,
  "error": "FAQ not found"
}
```

| Status | Wann dies bei einem FAQ-Endpunkt auftritt |
|---|---|
| `400` | Ein erforderliches Feld fehlt oder ist ungültig (zum Beispiel ein leeres `question`, ein fehlendes `campaign_id` oder mehr als 500 Elemente in einer Sammelanfrage). |
| `404` | Das FAQ oder die Kampagne wurde nicht gefunden – entweder existiert es nicht oder es gehört zu einem anderen Konto. |
| `409` | `POST /faqs/dedupe` wurde aufgerufen, während ein Deduplizierungsauftrag bereits `queued`/`processing` ist, oder `POST /faqs/dedupe/dismiss` wurde aufgerufen, während der Auftrag noch nicht abgeschlossen ist. |

Die gemeinsamen Codes, die jeder Endpunkt zurückgeben kann — `401`, `403` (Ihr Plan beinhaltet keinen API-Zugriff), `429` (Ratenbegrenzung) und `500` — sind zusammen mit Hinweisen zur Wiederholung unter [Fehler & Paginierung](errors-and-pagination.md) aufgeführt.

`POST /faqs/similar-for-task` und `POST /faqs/resolve-task` sind die zwei Ausnahmen auf dieser Seite: Sie antworten mit `200`, selbst bei einem erwarteten Fehler (unbekannte Aufgabe, falscher Aufgabentyp), und setzen stattdessen den tatsächlichen Status in das Feld `error_code` des Bodys – siehe die jeweiligen Endpunkte oben.

---

## Verwandte Themen

- [Kampagnen-API](campaigns.md) – die Kampagnen, mit denen Ihre FAQs verknüpft sind.
- [Wissensdatenbank-API](knowledge-base.md) – importieren Sie Websites und Dokumente automatisch in FAQs und bündeln Sie FAQs in wiederverwendbare Wissensgruppen.
- [API-Zugriff](../integrations/api-access.md) – generieren Sie Ihren API-Schlüssel.
- [Authentifizierung](authentication.md) – alle Möglichkeiten, Ihren Schlüssel zu übermitteln.
