# PPT 生成与导出

从创建任务到查询、导出、下载和删除的完整接入流程。

异步生成演示文稿，再导出 PPTX 文件。创建任务成功与文件生成完成是两个阶段，需要分别处理。

示例使用[总览](https://openapi.felo.ai/zh-CN/docs/data-api/guides/felo-overview.md)中配置的 `FELO_API_KEY`。调用使用**平台余额**，不使用 Felo Pro 积分。响应示例仅展示结构，实际内容和可选字段会变化。

## 完整流程与标识

1. 创建生成任务，保存 `task_id`、`ppt_business_id` 和 `expires_at`。
2. 使用 `task_id` 轮询生成状态。
3. 使用 `task_id` 读取生成结果。
4. 使用 `ppt_business_id` 发起 PPTX 导出。
5. 查询导出状态，完成后下载文件。
6. 按需提前删除演示文稿。

路径中的 `{business_id}` 指返回的 **`ppt_business_id`**，不是 `task_id`、`resource_id` 或 `livedoc_short_id`。全流程使用同一个 API 账户。下面示例中的 ID 都需要替换为真实返回值。

## 1. 创建演示文稿

`POST /api/v1/data/ppts`

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `query` | string | 是 | 生成要求，1–25,000 字符 |
| `stream_protocol` | string | 否 | 默认 `message_center_v1`，通常无需修改 |
| `ppt_config` | object | 否 | 可选配置；当前实现读取 `ai_theme_id` |
| `livedoc_short_id` | string | 否 | 已有上下文 ID，最长 100 字符；需通过原生 API 的归属与有效期检查 |
| `resource_ids` | string[] | 否 | 最多 100 个 UUID 资源 ID，同样受上下文权限检查约束 |

首次接入建议不传上下文和配置字段。通过 `/v2` 创建的上下文，不代表可以直接在此复用。

```bash
curl -sS --request POST "https://openapi.felo.ai/api/v1/data/ppts" \
  -H "Authorization: Bearer $FELO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"面向软件开发者，生成一份介绍检索增强生成的 5 页中文演示文稿。"}'
```

HTTP 200，标识直接位于根层级：

```json
{
  "task_id":"example-task-id",
  "ppt_business_id":"example-ppt-id",
  "livedoc_short_id":"example-livedoc-id",
  "expires_at":"2026-11-13T00:00:00Z"
}
```

可能还会返回 `resource_id`、`stream_key`、`thread_short_id` 等标识。创建成功仅表示任务已接受，不表示生成完成。提示词里的页数是生成要求，计费以实际生成页数为准。

```bash
TASK_ID="example-task-id"
PPT_ID="example-ppt-id"
```

### 使用 SSE 读取生成过程

如果创建响应返回 `stream_key`，可以使用同一账户的 API Key 立即连接原生流接口。没有 `stream_key` 时，继续使用下面的任务状态和结果查询流程。

```bash
curl -N 'https://openapi.felo.ai/api/v1/data/conversations/stream/YOUR_STREAM_KEY?format=structured' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: text/event-stream'
```

| 查询参数 | 说明 |
|---|---|
| `format` | `raw`（默认）保留 `content` 字符串；`structured` 将可解析的 JSON 转为对象或数组 |
| `offset` | 可选的上游恢复位置，用于断线重连；不要自行用事件数量推算 |

读取完整 SSE 事件后解析外层 JSON，再处理 `content`。业务事件 `answer` 的文本位于 `data.text`，`finished` 表示流中的生成过程完成；同时处理上游可能发送的 `done`、`[DONE]` 和 `error`。无完成信号就断线时，先查询任务状态。

解析规则和客户端示例与 [SuperAgent 的 SSE 格式](https://openapi.felo.ai/zh-CN/docs/api-reference/superagent.md#2-消费-sse-流)相同，调用时使用本节的 `/api/v1/data/conversations/stream/{stream_key}` 地址。流结束后仍需查询任务结果，导出 PPTX 使用后面的独立流程。此接口不会让 `/api/v1/data/chat` 支持 `stream: true`。

## 2. 查询生成状态

`GET /api/v1/data/tasks/{task_id}/status`

```bash
curl -sS --request GET "https://openapi.felo.ai/api/v1/data/tasks/$TASK_ID/status" \
  -H "Authorization: Bearer $FELO_API_KEY"
```

返回根层级的 `status` 字符串，例如 `RUNNING` 或 `COMPLETED`。建议每隔 2–5 秒查询一次，并设置最长等待时间。完成后再读取结果；失败或遇到未识别状态时，不要直接视为成功。客户端停止轮询不会取消任务。

```json
{"status":"COMPLETED"}
```

## 3. 获取生成结果

`POST /api/v1/data/tasks/{task_id}/historical`

注意这里是 **POST**，无需 JSON 请求体。

```bash
curl -sS --request POST "https://openapi.felo.ai/api/v1/data/tasks/$TASK_ID/historical" \
  -H "Authorization: Bearer $FELO_API_KEY"
```

```json
{
  "task_id":"example-task-id",
  "task_status":"COMPLETED",
  "history_data":{},
  "error_message":null
}
```

先判断 `task_status`，再使用 `history_data`。历史内容会随任务变化，也可能为空。`ai_page_html`、`thread_short_id` 是可选字段。此接口不保证直接返回 PPTX 下载地址，下载文件需要下一步导出。

## 4. 发起 PPTX 导出

`POST /api/v1/data/ppts/{business_id}/export`

```bash
curl -sS --request POST "https://openapi.felo.ai/api/v1/data/ppts/$PPT_ID/export" \
  -H "Authorization: Bearer $FELO_API_KEY"
```

```json
{"status":"PROCESSING","download_url":null,"expires_at":null}
```

请先确认生成完成。同一导出进行中，重复 POST 会复用该任务；导出完成后再次 POST 会新建导出，可能再次计费。查询状态和刷新下载链接都应使用 GET。

## 5. 查询导出状态并下载

`GET /api/v1/data/ppts/{business_id}/export`

```bash
curl -sS --request GET "https://openapi.felo.ai/api/v1/data/ppts/$PPT_ID/export" \
  -H "Authorization: Bearer $FELO_API_KEY"
```

| 状态 | 下一步 |
|---|---|
| `NOT_STARTED` | 发起一次导出 |
| `PROCESSING` | 等待后继续 GET 查询 |
| `COMPLETED` | 读取 `download_url` 并下载 |
| `FAILED` | 查看错误和任务情况，再决定是否重新导出 |

```json
{
  "status":"COMPLETED",
  "download_url":"https://example.com/presentation.pptx?signature=example",
  "expires_at":"2026-11-06T00:30:00Z"
}
```

示例地址仅展示结构，请使用真实返回的签名链接。下载链接有效期为 **30 分钟**；只要演示文稿仍有效，GET 查询导出状态即可获取新的链接。请及时保存文件，不要把 Felo API Key 发送给文件下载域名。

## 6. 删除演示文稿

`DELETE /api/v1/data/ppts/{business_id}`

```bash
curl -sS --request DELETE "https://openapi.felo.ai/api/v1/data/ppts/$PPT_ID" \
  -H "Authorization: Bearer $FELO_API_KEY"
```

成功返回 **HTTP 204，响应体为空**，不要继续解析 JSON。生成尚未结束时删除会返回 409。

## 有效期、归属与计费

- 演示文稿在**创建七天后过期**，查询和导出不会延长有效期。创建响应和导出响应中的 `expires_at` 分别表示文稿到期时间与下载链接到期时间。
- 只能访问当前 API 账户创建的任务和文稿。资源不存在或无权访问可能返回 404；过期或已删除可能返回 410，清理后也可能返回 404。
- 生成按实际页数计费（`ppt.generate`）。按页定价时，创建先预留十页费用，生成成功后按实际产出结算并释放未使用部分。即使提示词只要求五页，提交时仍需满足预留额度。
- 导出单独按请求计费（`ppt.export`）。生成状态、生成结果、导出状态查询以及删除均不新增费用。
- 遇到超时，优先查询已保存的任务，不要立即再创建一份。详见[计费与错误处理](https://openapi.felo.ai/zh-CN/docs/data-api/guides/felo-billing.md)。
