# PPT 생성 및 내보내기

프레젠테이션을 만들고, 진행 상황을 확인하고, PPTX를 내보내며, 수명을 관리합니다.

프레젠테이션을 비동기로 생성한 다음 PPTX 파일을 내보내세요. 생성과 내보내기 단계를 분리하세요. 생성된 작업은 아직 완성된 파일이 아닙니다.

모든 예시는 [개요](https://openapi.felo.ai/ko/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 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/ko/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가 반환됩니다.

## 수명, 소유권 및 청구

- 프레젠테이션은 **생성 후 7일**에 만료됩니다. 조회와 내보내기는 이 기간을 연장하지 않습니다. 프레젠테이션 `expires_at`과 서명된 다운로드 URL `expires_at`은 서로 다른 수명을 나타냅니다.
- 생성한 API 계정만 자신의 작업과 프레젠테이션에 접근할 수 있습니다. 누락되었거나 접근할 수 없는 리소스는 404를 반환할 수 있으며, 만료되었거나 삭제된 리소스는 410을 반환하거나 정리 후 404가 될 수 있습니다.
- 생성은 생성된 페이지당(`ppt.generate`) 과금됩니다. 페이지 가격 책정에서는 생성 시 10페이지 가격을 예약한 다음 실제 성공 출력으로 정산하고 사용되지 않은 예약분을 해제합니다. 프롬프트가 더 적은 페이지를 요청하더라도 계정에는 예약에 충분한 가용 잔액이 있어야 합니다.
- 내보내기는 별도의 요청 가격(`ppt.export`)이 있습니다. 상태 조회, 결과 조회, export-status 조회, 삭제는 새 요금을 발생시키지 않습니다.
- 타임아웃 후에는 새 프레젠테이션을 만들지 말고 저장된 작업을 조회하세요. [청구 및 오류](https://openapi.felo.ai/ko/docs/data-api/guides/felo-billing.md)를 참조하세요.
