
NotebookLM-style のスライド書き出しは、各ページがすでに完成した視覚的なスライドになっている点で便利です。一方で、PDF ページは通常フラットなページであり、PowerPoint のオブジェクトモデルではありません。そのため編集が難しくなります。Codia Open API の pdf_to_ppt task は、この用途のために設計されています。入力は NotebookLM-style PDF、つまり各ページが全画面画像、スキャンされたスライド、またはスクリーンショット型ページであり、出力は編集可能な .pptx です。
この記事では、本番環境で使える統合パターンを順に説明します。
/v1/open/uploadsでローカルまたは非公開の NotebookLM-style PDF をアップロードする。- task 作成前に credits を見積もる。
- 統一 Task API で
pdf_to_ppttask を作成する。 - 高頻度ポーリングではなく webhook で最終結果を受け取る。
- task 履歴を一覧し、実行中 task をキャンセルし、生成された PPTX をダウンロードする。
例では Node.js を使います。多くの Web アプリケーションでは、ファイルアップロードをサーバールートで処理するためです。同じ HTTP 呼び出しは、Go、Python、Ruby、Java など、multipart と JSON を送信できる任意のバックエンドから利用できます。
完全な endpoint schema、リクエスト/レスポンスフィールド、最新の OpenAPI 仕様を確認する場合は、このガイドとあわせて Codia API Reference を開いてください。
NotebookLM-style PDF とは
現在の PDF to PPT パイプラインは、image-only PDF に最適化されています。各 PDF ページは 1 枚の全画面画像である必要があります。NotebookLM-style の書き出しページ、スクリーンショット型スライドデッキ、スキャンされたレポート、その他の静的なスライド画像が該当します。
複雑なテキストフロー PDF には向いていません。段落、ベクター図形、表、インラインオブジェクトを文書レイアウトとして解釈する用途ではありません。入力が通常のテキスト PDF の場合は、各ページを高解像度 PNG または JPEG にラスタライズし、それらの画像を image-only PDF として再パッケージしてください。これにより、コンバーターにとって扱いやすい「1 ページ = 1 スライド」の入力になります。
適した入力:
- NotebookLM-style PDF 書き出し
- スキャンまたはスクリーンショット型のスライドデッキ
- 1 ページが 1 スライドに対応する image-only PDF
- 編集可能な PPTX に変換したい静的なプレゼンテーションページ
注意が必要な入力:
- 段落が流れる長文 PDF
- 複雑なオブジェクト構造を持つベクター中心のレポート
- 文書ページとスライドページが混在する PDF
- 小さな文字が読めない低解像度スキャン
アーキテクチャ
Codia API key はサーバー側だけに置きます。ブラウザは PDF をあなたのバックエンドへアップロードし、バックエンドがそれを一度だけ Codia にアップロードします。以降の呼び出しでは、返却された不透明な upload_id を使います。
Browser
-> your server: multipart PDF upload
-> Codia /v1/open/uploads: multipart PDF upload
<- upload_id
-> Codia /v1/open/estimate: JSON with upload_id
-> Codia /v1/open/tasks: JSON with upload_id and callback_url
<- task_id
Codia
-> your webhook: terminal task event
Browser
-> your server: read task/result
-> download ppt_url when succeeded/v1/open/uploads は公開ファイル URL を返しません。短い保持期間を持つ、同じ user と API key にスコープされた不透明な upload_id を返します。これにより、アップロードエンドポイントが無料の公開ファイルホスティングになることを防ぎます。
Step 1: PDF をアップロードして upload_id を取得する
ローカルまたは非公開 PDF は、multipart/form-data で /v1/open/uploads に送信します。
curl 'https://api.codia.ai/v1/open/uploads' \
-H 'Authorization: Bearer {codia_api_key}' \
-F 'file=@./notebooklm-briefing.pdf'レスポンス例:
{
"code": 0,
"message": "ok",
"data": {
"upload_id": "upl_550e8400-e29b-41d4-a716-446655440000",
"filename": "notebooklm-briefing.pdf",
"size": 1234567,
"content_type": "application/pdf",
"expires_at": 1764086400
}
}Codia 管理のアップロードには upload_id を使います。PDF があなた自身のストレージでホストされ、Codia から到達可能な場合にのみ pdf_url を使ってください。
Step 2: task 作成前に credits を見積もる
pdf_to_ppt は変換ページごとに 13 credits です。page_no を指定した場合、見積もりは選択ページ数から決まります。page_no を省略した場合、サービスが PDF からページ数を解決します。
curl 'https://api.codia.ai/v1/open/estimate' \
-H 'Authorization: Bearer {codia_api_key}' \
-H 'Content-Type: application/json' \
--data '{
"operation": "pdf_to_ppt",
"input": {
"upload_id": "upl_550e8400-e29b-41d4-a716-446655440000",
"page_no": [0, 1, 2]
}
}'レスポンス例:
{
"code": 0,
"message": "ok",
"data": {
"operation": "pdf_to_ppt",
"page_count": 3,
"unit": "13 credits per page",
"credits": 39,
"available_credits": 120
}
}ページ番号は 0-based です。0 が PDF の最初のページです。
Step 3: pdf_to_ppt task を作成する
統一 Task API で task を作成します。サーバー側でタイムアウト後に再試行する可能性がある場合は、Idempotency-Key を送信してください。
curl 'https://api.codia.ai/v1/open/tasks' \
-H 'Authorization: Bearer {codia_api_key}' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: notebooklm-briefing-2026-05-29' \
--data '{
"operation": "pdf_to_ppt",
"input": {
"upload_id": "upl_550e8400-e29b-41d4-a716-446655440000",
"page_no": [0, 1, 2],
"title": "NotebookLM source briefing"
},
"callback_url": "https://your-app.example.com/webhooks/codia-task"
}'レスポンス例:
{
"code": 0,
"message": "ok",
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"operation": "pdf_to_ppt",
"status": "pending",
"created_at": 1780028799
}
}pending は task がキューに入っている状態です。processing は worker が処理を開始した状態です。終端状態は succeeded、failed、canceled です。
Step 4: webhook を受け取る
本番環境では、ブラウザのポーリングループより webhook を推奨します。Codia は task が終端状態に到達したときに callback_url へ POST します。
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post(
'/webhooks/codia-task',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = String(req.header('X-Codia-Signature') || '');
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.CODIA_WEBHOOK_SECRET!)
.update(req.body)
.digest('hex');
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) {
res.sendStatus(401);
return;
}
const event = JSON.parse(req.body.toString('utf8'));
if (event.operation === 'pdf_to_ppt' && event.status === 'succeeded') {
console.log('PPTX ready:', event.result?.ppt_url || event.ppt_url);
}
if (event.status === 'failed') {
console.error('Conversion failed:', event.error_code, event.error);
}
res.sendStatus(200);
},
);event は task_id をキーにして自分のデータベースへ保存してください。フロントエンドはあなたの API からその行を読み取り、Codia API key を公開せずに task UI を更新できます。
Step 5: status 取得または履歴一覧
主なフローは webhook で進めますが、status endpoint は管理画面、復旧、履歴表示に役立ちます。
curl 'https://api.codia.ai/v1/open/tasks/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer {codia_api_key}'実行中の PDF to PPT task を一覧する:
curl 'https://api.codia.ai/v1/open/tasks?operation=pdf_to_ppt&status=pending,processing&limit=20' \
-H 'Authorization: Bearer {codia_api_key}'cursor pagination で履歴を取得する:
curl 'https://api.codia.ai/v1/open/tasks?operation=pdf_to_ppt&limit=20&after=1780028799' \
-H 'Authorization: Bearer {codia_api_key}'task の所有権は、task を作成した API key にスコープされます。照会、一覧、キャンセル、webhook 照合には同じ key を使ってください。
Step 6: キャンセルと部分返金を扱う
pending または processing の task はキャンセルできます。
curl -X POST 'https://api.codia.ai/v1/open/tasks/550e8400-e29b-41d4-a716-446655440000/cancel' \
-H 'Authorization: Bearer {codia_api_key}'pdf_to_ppt では、まだ変換が完了していないページ分だけが返金されます。15 ページの NotebookLM-style PDF task で 10 ページが変換済みの場合、キャンセルすると 65 credits が返金され、130 credits は課金済みとして残ります。
{
"code": 0,
"message": "ok",
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"operation": "pdf_to_ppt",
"status": "canceled",
"credits_reserved": 195,
"credits_charged": 130,
"credits_refunded": 65
}
}task がまだ pending の場合は、予約された credits が全額返金されます。succeeded の task はキャンセルできません。
Step 7: 編集可能な PPTX をダウンロードする
task が成功したら、result.ppt_url を読み取り、速やかにファイルをダウンロードします。
{
"code": 0,
"message": "ok",
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"operation": "pdf_to_ppt",
"status": "succeeded",
"progress": 100,
"result": {
"ppt_url": "https://static.codia.ai/pptx/notebooklm-source-briefing.pptx",
"page_count": 3,
"pages": [
{
"index": 0,
"source_page": 0,
"editable": true,
"status": "editable",
"preview_url": "https://static.codia.ai/previews/page-0.png"
}
]
}
}
}PPTX はユーザーが最終的に必要とする成果物です。長期アクセスが必要な場合は自分のシステムに保存し、ユーザープロジェクトへ添付するか、PowerPoint、Keynote、Google Slides のワークフローへ渡してください。
Node.js ルート全体
次の最小 Express ルートは、ブラウザからのアップロードを受け取り、Codia task を作成します。Codia API key はサーバー側に保持され、ブラウザには送信されません。
import express from 'express';
import multer from 'multer';
import FormData from 'form-data';
import crypto from 'node:crypto';
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
const CODIA_API_BASE = 'https://api.codia.ai';
app.post('/api/notebooklm-pdf-to-pptx', upload.single('file'), async (req, res) => {
if (!req.file) {
res.status(400).json({ error: 'file is required' });
return;
}
const form = new FormData();
form.append('file', req.file.buffer, {
filename: req.file.originalname || 'notebooklm.pdf',
contentType: req.file.mimetype || 'application/pdf',
});
const uploadRsp = await fetch(`${CODIA_API_BASE}/v1/open/uploads`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CODIA_API_KEY}`,
...form.getHeaders(),
},
body: form as any,
}).then((r) => r.json());
if (uploadRsp.code !== 0) {
res.status(502).json(uploadRsp);
return;
}
const uploadId = uploadRsp.data.upload_id;
const idempotencyKey = crypto.randomUUID();
const taskRsp = await fetch(`${CODIA_API_BASE}/v1/open/tasks`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CODIA_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey,
},
body: JSON.stringify({
operation: 'pdf_to_ppt',
input: {
upload_id: uploadId,
title: req.body.title || req.file.originalname?.replace(/\.pdf$/i, ''),
},
callback_url: `${process.env.PUBLIC_APP_URL}/webhooks/codia-task`,
}),
}).then((r) => r.json());
if (taskRsp.code !== 0) {
res.status(502).json(taskRsp);
return;
}
res.status(202).json({
task_id: taskRsp.data.task_id,
status: taskRsp.data.status,
upload_id: uploadId,
});
});実際の本番コードでは、リクエストサイズ制限、MIME チェック、ユーザー所有権チェック、データベース永続化、構造化されたリトライ処理を追加してください。
運用チェックリスト
- 転送前にアップロードファイルが PDF であることを検証する。
CODIA_API_KEYと webhook secret はサーバー側に置く。- UI でコストプレビューが必要な場合は
/v1/open/estimateを使う。 - task 作成を再試行する場合は
Idempotency-Keyを使う。 - 終端状態の更新には
callback_urlを優先する。 task_id、status、ppt_url、課金フィールドを自分のデータベースに保存する。- 履歴ページには
GET /v1/open/tasksの cursor pagination を使う。 - NotebookLM-style image-only PDF が最も適していることを UI で明確に伝える。
FAQ
アップロードせず URL を渡せますか?
はい。PDF があなた自身のストレージでホストされている場合は、task 作成時に input.pdf_url を渡せます。ローカルまたは非公開 PDF を Codia にアップロードした場合は input.upload_id を使います。
/v1/open/uploads は公開ファイル URL を返しますか?
いいえ。不透明な upload_id を返します。公開ファイル URL ではありません。task service が内部で upload を解決し、user と API key によって所有権を検証します。
出力は本当に編集可能ですか?
目標は、テキスト、レイアウト、視覚要素が再構築された編集可能な PPTX です。密度の高いページや低品質のページは、image-only または部分的に編集可能な結果になることがあります。task result にはページごとの status が含まれるため、UI でどのページが編集可能か表示できます。
credits はどう課金されますか?
pdf_to_ppt は変換ページごとに 13 credits です。失敗した task は予約 credits が返金されます。キャンセルされた PDF to PPT task では、まだ変換されていないページ分が返金されます。
ポーリングは必要ですか?
本番のメインフローでは webhook を使ってください。GET /v1/open/tasks/{task_id} は復旧、管理画面、手動更新に適しています。