
# 常见问题解答 (FAQs) API

常见问题解答 (FAQs) 是您的 AI 机器人回复客户时所引用的问答条目。每个 FAQ 都归属于您的账户，并可关联到一个或多个营销活动，因此相同的答案可以在所有相关的地方重复使用。FAQs API 让您可以以编程方式管理该库——通过您自己的代码创建、更新、批量导入、重新排序 FAQ 并将其关联到营销活动。

以下所有端点均相对于基础 URL `https://api.youraiconnector.com/v1`。每个请求都必须经过身份验证——请参阅 [API 访问](../integrations/api-access.md) 和 [身份验证](authentication.md)。API 访问是一项付费功能；如果没有该权限，请求将被 `403` 拒绝。

> **机器人如何使用 FAQ：** 当您创建或更改 FAQ 时，平台会在后台准备其搜索数据（用于将 FAQ 与传入的问题进行匹配）。此过程通常在几秒钟内完成，之后机器人会自动开始使用该条目。


---

## FAQ 对象

API 返回的每个 FAQ 都具有以下结构：

| 字段 | 类型 | 描述 |
|---|---|---|
| `id` | string | FAQ 的唯一标识符。 |
| `question` | string | 此条目所回答的客户问题。 |
| `answer` | string | AI 机器人给出的回答。 |
| `category` | string \| null | 可选的自由格式类别标签。 |
| `tags` | string[] | 用于组织 FAQ 的可选标签。 |
| `is_active` | boolean | 是否允许机器人使用此 FAQ。默认为 `true`。 |
| `is_global` | boolean | 标记该 FAQ 不绑定于特定的营销活动或智能体。这并不意味着该 FAQ 适用于所有地方：FAQ 仅由与其关联的营销活动和智能体使用。默认为 `false`。 |
| `usage_count` | integer | 此 FAQ 在 AI 回复中被使用的次数。 |
| `order_index` | integer | 此 FAQ 在其所属营销活动中的显示位置。 |
| `campaign_ids` | string[] | 此 FAQ 所关联的营销活动的 ID。 |
| `created_at` | string \| null | FAQ 创建时间的 ISO 8601 时间戳。 |
| `updated_at` | string \| null | 最后一次更改的 ISO 8601 时间戳。 |

您可以 **设置** 的字段包括：`question`、`answer`、`is_active`、`is_global`、`category`、`tags` 和 `order_index`。平台负责管理所有其他内容（搜索数据、使用计数、时间戳）；请求正文中的任何其他字段都将被忽略。

---

## 列出 FAQ

`GET /faqs`

返回您账户中的 FAQ，按最新顺序排列。可选择按单个营销活动或活动状态进行过滤。

**查询参数**

| 参数 | 必需 | 描述 |
|---|---|---|
| `campaign_id` | 否 | 仅返回关联到此营销活动的 FAQ。 |
| `is_active` | 否 | 仅返回具有此活动状态（`true` 或 `false`）的 FAQ。此过滤器按页应用，因此一页包含的项目可能少于 `limit`。 |
| `limit` | 否 | 每页的最大 FAQ 数。默认 `50`，最大 `100`。 |
| `cursor` | 否 | 用于继续获取的 FAQ ID。传入上一页的 `next_cursor` 值。 |

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

**响应**

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

当 `next_cursor` 为 `null` 时，表示没有更多结果。

---

## 获取常见问题解答 (FAQ)

`GET /faqs/{faqId}`

根据 ID 返回单个常见问题解答。

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

**响应**

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

`POST /faqs`

创建一个新的常见问题解答并将其关联到某个营销活动。

**请求字段**

| 字段 | 必填 | 描述 |
|---|---|---|
| `campaign_id` | 是 | 要关联新常见问题解答的营销活动。 |
| `question` | 是 | 此条目回答的客户问题。 |
| `answer` | 是 | 机器人应给出的回答。 |
| `is_active` | 否 | 机器人是否可以使用此常见问题解答。默认为 `true`。 |
| `is_global` | 否 | 该常见问题解答是否适用于所有营销活动。默认为 `false`。 |
| `category` | 否 | 自由格式的类别标签。 |
| `tags` | 否 | 标签数组。 |
| `order_index` | 否 | 在营销活动中的显示位置。默认为 `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"]
```

**响应**

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

---

## 更新常见问题解答 (FAQ)

`PUT /faqs/{faqId}`

部分更新常见问题解答。仅更改提供的可写字段；其他所有内容保持其当前值。更改 `question` 或 `answer` 会在后台自动刷新常见问题解答的搜索数据。

如果您发送 `question` 或 `answer`，它们必须是非空字符串。如果不发送任何可识别的可写字段，将返回 `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()
```

**响应**

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

---

## 删除常见问题解答 (FAQ)

`DELETE /faqs/{faqId}`

永久删除常见问题解答。可选择将 `campaign_id` 作为查询参数传递，以同时从该营销活动的常见问题解答列表中移除此条目。

**查询参数**

| 参数 | 必需 | 描述 |
|---|---|---|
| `campaign_id` | 否 | 同时从该营销活动的常见问题列表中移除常见问题。 |

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

**响应**

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

---

## 批量删除常见问题

`POST /faqs/bulk-delete`

在单个请求中最多删除 500 个常见问题。当提供 `campaign_id` 时，被删除的常见问题也会从该营销活动的常见问题列表中移除。

**请求字段**

| 字段 | 必需 | 描述 |
|---|---|---|
| `faq_ids` | 是 | 要删除的常见问题 ID 的非空数组（最多 500 个）。 |
| `campaign_id` | 否 | 同时从该营销活动的常见问题列表中移除被删除的常见问题。 |

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

**响应**

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

---

## 导入常见问题

`POST /faqs/import`

批量导入最多 500 个常见问题，并将它们全部关联到一个营销活动。其 `question` 与库中现有常见问题匹配（不区分大小写）的项目将**更新**该常见问题，而不是创建重复项。

> **性能提示：** 重复项匹配会扫描您的整个常见问题库，因此非常大的库会使导入变慢。建议进行少量的大规模导入，而不是多次小规模导入。

**请求字段**

| 字段 | 必需 | 描述 |
|---|---|---|
| `campaign_id` | 是 | 所有导入的常见问题所关联的营销活动。 |
| `faqs` | 是 | 常见问题项的非空数组（最多 500 个）。每个项必须具有非空的 `question` 和 `answer`；它还可以包含 `is_active`、`is_global`、`category`、`tags` 和 `order_index`。 |

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

**响应**

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

`faq_ids` 是创建或更新的常见问题 ID，顺序与您提供的顺序一致。

---

## 重新排序常见问题

`POST /faqs/reorder`

设置营销活动常见问题的显示顺序。请提供所需顺序的 FAQ ID **完整**列表；每个 FAQ 的位置将更新以匹配其在数组中的顺序。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `campaign_id` | 是 | 要重新排序常见问题的营销活动。 |
| `ordered_faq_ids` | 是 | 包含营销活动中所有 FAQ ID 的非空数组，按所需显示顺序排列（最多 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()
```

**响应**

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

如果您的账户中找不到该营销活动或任何 FAQ ID，请求将返回 `404 One or more FAQs were not found`。

---

## 将常见问题关联到营销活动

`POST /faqs/{faqId}/link`

将现有的常见问题关联到额外的营销活动。一个常见问题可以被任意数量的营销活动共享，因此相同的答案只需维护一次。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `campaign_id` | 是 | 要关联常见问题的营销活动。 |

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

**响应**

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

---

## 从营销活动中取消关联常见问题

`POST /faqs/{faqId}/unlink`

从营销活动中移除常见问题，但不会删除该常见问题本身。该常见问题将保留在您的库中，并保持与其他营销活动的关联。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `campaign_id` | 是 | 要从中移除常见问题的营销活动。 |

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

**响应**

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

---

## 重建常见问题解答的搜索数据

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

将 AI 机器人用于查找此常见问题解答的数据（其语义和关键字搜索数据）加入重建队列。如果常见问题解答未按预期出现在回复中，此操作非常有用。重建过程在后台运行，通常在几秒钟内完成；在重建期间，该常见问题解答可能会暂时从 AI 回复中排除。

此端点返回 `202 Accepted`，因为工作会在响应发送后继续进行。该 `status` 始终为 `"processing"` —— 如果需要确认完成情况，请稍后重新获取该常见问题解答。

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

**响应**

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

---

## AI 辅助的常见问题解答管理

以下端点不仅仅是简单的 CRUD 操作：它们调用了仪表板 FAQ 编辑器所使用的 AI 辅助工具——用于查找重复项、从文档生成条目，以及将 FAQ 与开放的知识缺口任务进行匹配。此集合中的请求体使用 `camelCase` 字段名称（`campaignId`、`taskId`、`sourceIds`...），这与应用程序自身的请求格式相匹配，而不是本页面其他地方使用的 `snake_case`——请复制下方的示例，而不是猜测字段名称。

### 将 FAQ 分叉为仅限营销活动的副本

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

创建一个现有 FAQ 的副本，将其限定在单个营销活动中，并将该营销活动重新链接到新副本，而不是原始 FAQ。当您想要为某个营销活动自定义答案，而不更改原始 FAQ 在其他地方的使用情况时，请使用此功能。原始 FAQ 将保留在原处——它只会失去与此营销活动的链接。

**请求字段**

| 字段 | 必需 | 描述 |
|---|---|---|
| `campaign_id` | 是 | 要将新副本限定于此，并从原始 FAQ 重新链接的营销活动。 |
| `question` | 是 | 新的、特定于营销活动的副本的问题。 |
| `answer` | 是 | 新的、特定于营销活动的副本的答案。 |

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

**响应** — `201 Created`

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

### 查找近似重复的 FAQ

`POST /faqs/dedupe`

启动一个后台作业，扫描您的 FAQ 库以查找近似重复和重叠的条目，并在确信的情况下合并或删除它们。这在批量导入后，或在多轮 AI 生成的 FAQ 导致库中出现重叠后非常有用。每个账户一次只能运行一个去重作业——在作业仍在运行时启动第二个作业将返回 `409`。

**请求字段**

| 字段 | 必需 | 描述 |
|---|---|---|
| `sourceIds` | 否 | 用于限定去重范围的知识库源 ID 数组。省略此项则扫描整个 FAQ 库。 |

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

**响应** — `202 Accepted`

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

该作业在后台运行，对于大型库通常需要几分钟。没有单独的状态端点——稍等片刻后重新获取 [`GET /faqs`](#list-faqs) 以查看更改内容。查看结果后，调用下方的消除端点以清除它。

### 消除重复检查结果

`POST /faqs/dedupe/dismiss`

清除已完成的去重作业，使其不再显示为活动结果。幂等操作——即使没有可消除的内容也可以安全调用。如果作业仍处于 `queued` 或 `processing` 状态，则返回 `409`（您无法消除尚未完成的运行）。

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

**响应**

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

### 从上传的文档生成常见问题解答 (FAQ)

`POST /faqs/generate-from-documents`

读取您账户文件存储中已有的一个或多个文档，并让 AI 根据其内容起草常见问题解答。系统会将草稿与您现有的库进行比对，以便复用或更新条目，而不是创建重复内容。结果**不会**立即写入，而是作为待处理的变更集存储在营销活动中供您审阅，随后通过下方的 [应用已审阅的 FAQ 变更](#apply-reviewed-faq-changes) 进行应用（或丢弃）。此操作会消耗积分，因为这是对文档文本进行的一次 AI 生成处理。

此端点不携带文件：`storagePath` 必须指向您自己上传文件夹 (`users/{your user id}/uploads/`) 下已有的文件，这与知识库 API 中的 [导入已上传文档](knowledge-base.md#import-an-uploaded-document) 遵循相同的约定。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `campaignId` | 是 | 生成的 FAQ 所属的营销活动。 |
| `uploadedFiles` | 是 | 要读取的文件组成的非空数组，每个元素为 `{ storagePath, fileName, mimeType }`。`storagePath` 必须以 `users/{your user id}/uploads/` 开头。 |

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

**响应** — `202 Accepted`

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

`faqCount` 是等待审阅的拟议变更总数；`reusedCount`、`modifiedCount` 和 `newCount` 将其细分为：与现有条目匹配且未更改的 FAQ、AI 建议编辑的 FAQ，以及全新的 FAQ。无论处理是否成功，上传的文件在处理完成后都会从存储中删除。

### 应用已审阅的 FAQ 变更

`POST /faqs/apply-optimization`

应用（或丢弃）一组 AI 拟议的待处理 FAQ 变更——即上述 [从文档生成 FAQ](#generate-faqs-from-uploaded-documents) 或仪表板 FAQ 优化审阅所产生的变更。您可以精确选择要接受哪些拟议变更；未提及的任何内容都将保持不变（省略的变更绝不会被视为删除某项内容的拒绝操作）。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `campaignId` | 二选一 | 正在应用待处理 FAQ 变更的营销活动。 |
| `agentId` | 二选一 | 在代理原生账户上，正在应用待处理 FAQ 变更的 AI 代理。请准确提供 `campaignId` / `agentId` 中的一个，切勿同时提供。 |
| `acceptedChanges` | 是 | 您接受的变更数组，每个元素为 `{ action, faq_id?, faq_ref_path?, question?, answer?, edit_scope? }`。`action` 是 `keep`、`remove`、`add_from_library`、`create_new`、`modify` 之一。发送空数组可丢弃待处理集而不应用任何内容。 |

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

**响应**

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

`faq_count` 是应用后营销活动（或代理）关联的 FAQ 总数。如果没有待处理的变更集可应用，响应为 `{ "success": true, "message": "No pending FAQ changes to apply" }`。

### 查找与任务相似的 FAQ

`POST /faqs/similar-for-task`

根据知识缺口任务的问题，按相关性对您的 FAQ 库进行排序——这与仪表板“使用现有 FAQ”选择器背后的查找逻辑相同。只读。 `taskId` 必须指向类型为 `faq_update` 的任务。

此端点始终返回 `200`，即使在遇到预期失败（例如未知任务）时也是如此 — 请检查正文中的 `success` 而不是 HTTP 状态码。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `taskId` | 是 | 要查找匹配项的 `faq_update` 任务。 |
| `limit` | 否 | 返回的最大匹配数。默认为 20，上限为 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()
```

**响应**

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

匹配项按 `similarity` 排序（优先语义匹配，其次关键词重叠），最佳匹配在前。在软失败时，其结构为 `{ "success": false, "error": "...", "error_code": 404 }` — `error_code` 反映了通常的 HTTP 状态码。

### 使用现有常见问题解答 (FAQ) 解决任务

`POST /faqs/resolve-task`

通过将知识缺口任务链接到您已有的 FAQ（而不是编写新的 FAQ）来解决该任务，将该 FAQ 的答案发送给触发缺口的联系人，并将任务标记为已完成。在 [查找与任务相似的 FAQ](#find-faqs-similar-to-a-task) 找到涵盖该问题的现有 FAQ 后，请使用此端点。

与上面的端点一样，此端点始终返回 `200` — 请检查正文中的 `success`。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `taskId` | 是 | 要解决的 `faq_update` 任务。 |
| `faqId` | 是 | 要链接并作为答案发送的现有 FAQ。 |

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

**响应**

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

`follow_up_status` 会告知您联系人后续跟进的情况：`published`（立即发送）、`queued`（AI 正在回复该联系人，因此稍后发送）、`skipped_no_contact`（任务没有关联的联系人）或 `skipped_no_campaign`（没有可用于发送的营销活动）。

---

## 常见问题解答 (FAQ) API 错误

FAQ 端点返回标准的错误信封：

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

| 状态 | 在 FAQ 端点上发生时 |
|---|---|
| `400` | 缺少必填字段或字段无效（例如 `question` 为空、缺少 `campaign_id` 或批量请求中超过 500 个项目）。 |
| `404` | 未找到 FAQ 或营销活动 — 它们不存在或属于其他账户。 |
| `409` | 在去重作业已处于 `queued`/`processing` 状态时调用了 `POST /faqs/dedupe`，或者在作业尚未完成时调用了 `POST /faqs/dedupe/dismiss`。 |

每个端点都可能返回的共享代码 — `401`, `403`（您的套餐不包含 API 访问权限）, `429`（速率限制）和 `500` — 及其重试指南列在 [错误与分页](errors-and-pagination.md) 中。

`POST /faqs/similar-for-task` 和 `POST /faqs/resolve-task` 是本页面上的两个例外：即使在预期失败（未知任务、错误的任务类型）时，它们也会返回 `200`，并将实际状态放入正文的 `error_code` 中 — 请参阅上面的各个端点说明。

---

## 相关内容

- [营销活动 API](campaigns.md) — 您 FAQ 所链接到的营销活动。
- [知识库 API](knowledge-base.md) — 自动将网站和文档导入 FAQ，并将 FAQ 捆绑到可重用的知识组中。
- [API 访问](../integrations/api-access.md) — 生成您的 API 密钥。
- [身份验证](authentication.md) — 传递密钥的所有方式。
