# PPT 生成與匯出

建立簡報、輪詢進度、匯出 PPTX，並管理其生命週期。

非同步生成簡報，然後匯出為 PPTX 檔案。請將生成與匯出步驟分開：已建立的任務還不是完成的檔案。

所有範例都使用來自[總覽](https://openapi.felo.ai/zh-TW/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 array | 否 | 最多 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":"Create a 5-slide introduction to retrieval augmented generation for software developers."}'
```

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 金鑰連線。如果沒有回傳 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-TW/docs/api-reference/superagent.md#2-消費-sse-串流) 中的解析規則與用戶端範例，並搭配本節的 `/api/v1/data/conversations/stream/{stream_key}` URL。串流結束後請讀取任務結果；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
}
```

在使用 `history_data` 之前請先讀取 `task_status`。歷史負載可依任務而異，且可能為 null。`ai_page_html` 與 `thread_short_id` 為選填。此回應不是保證可直接下載 PPTX 的 URL；請改用匯出。

## 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 會重用它。在完成後再次開始另一個匯出會建立新的匯出，並可能再產生一次費用。請使用 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"
}
```

範例 URL 僅供說明。請使用回應中的實際簽名 URL。它的有效時間為 **30 分鐘**；在簡報仍可用的期間，GET 匯出狀態可以回傳新的連結。請在其有效期內儲存檔案。不要將你的 Felo API 金鑰傳送給檔案下載主機。

## 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` 與簽名下載 URL 的 `expires_at` 代表不同的有效期間。
- 只有建立該任務的 API 帳戶可以存取其任務與簡報。缺少或無法存取的資源可能回傳 404；已過期或已刪除的資源可能回傳 410，或在清理後回傳 404。
- 生成會依每個生成頁面計費（`ppt.generate`）。在頁面計價下，建立時會預留 10 頁的費用，然後結算實際成功輸出並釋放未使用的預留金額。即使提示詞要求的頁數較少，你的帳戶也需要有足夠的可用餘額來完成這項預留。
- 匯出有獨立的請求價格（`ppt.export`）。狀態查詢、結果查詢、匯出狀態查詢與刪除都不會產生新費用。
- 發生逾時後，請查詢已儲存的任務，而不是再建立另一份簡報。請參閱[計費與錯誤](https://openapi.felo.ai/zh-TW/docs/data-api/guides/felo-billing.md)。
