Slides
Generate AI-powered presentation slides with visuals and voiceover scripts, ready for meetings and reports.
Slides mode generates professional presentation-style content with AI visuals and voiceover scripts — ideal for meetings, business reports, and conference talks.
| Detail | |
|---|---|
| Visual style | PPT layouts (grid, process flow, big number hero) |
| Page 1 | Presentation title page |
| Best for | Meeting presentations, business reports, conference talks |
To export as a PPT file, use the ListenHub platform directly — PPT export is not available via the OpenAPI.
Create Slides Episode
POST /v1/storybook/episodes
Create a slides episode with AI-generated presentation visuals and voiceover scripts.
sources accepts at most 1 item. speakers accepts at most 1 item.
curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sources": [
{"type": "text", "content": "Q3 revenue grew 45% year-over-year, driven by expansion in APAC markets..."}
],
"speakers": [
{"speakerId": "<SPEAKER_ID>"}
],
"language": "en",
"mode": "slides"
}'const response = await fetch('https://api.marswave.ai/openapi/v1/storybook/episodes', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
sources: [{ type: 'text', content: 'Q3 revenue grew 45% year-over-year, driven by expansion in APAC markets...' }],
speakers: [{ speakerId: '<SPEAKER_ID>' }],
language: 'en',
mode: 'slides',
}),
});
const data = await response.json();
console.log(data);import os, requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/storybook/episodes',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'sources': [{'type': 'text', 'content': 'Q3 revenue grew 45% year-over-year, driven by expansion in APAC markets...'}],
'speakers': [{'speakerId': '<SPEAKER_ID>'}],
'language': 'en',
'mode': 'slides',
}
)
print(response.json())Response:
{
"code": 0,
"message": "",
"data": {
"episodeId": "{episodeId}"
}
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| sources | array(1) | Yes | Content source. Max 1 item. |
| sources[].type | string | Yes | "text" or "url" |
| sources[].content | string | Yes | Text content or URL |
| sources[].uri | string | No | Source URI |
| sources[].metadata | object | No | Source metadata |
| speakers | array(1) | Yes | Voice config. Max 1 item. |
| speakers[].speakerId | string | Yes | Speaker ID (see Speakers) |
| language | string | No | Language code (e.g. "en", "zh") |
| mode | string | Yes | Must be "slides" |
| style | string | No | Visual style ID |
Query Episode Status
GET /v1/storybook/episodes/{episodeId}
Poll with the returned episodeId until processStatus is success.
curl "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/storybook/episodes/${episodeId}`,
{ headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const data = await response.json();
console.log('Status:', data.data.processStatus);import os, requests
response = requests.get(
f'https://api.marswave.ai/openapi/v1/storybook/episodes/{episode_id}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
data = response.json()
print('Status:', data['data']['processStatus'])Response (when processStatus is success):
{
"code": 0,
"message": "",
"data": {
"episodeId": "{episodeId}",
"createdAt": 1700000000,
"mode": "slides",
"processStatus": "success",
"credits": 30,
"title": "Q3 Business Review",
"cover": "https://assets.listenhub.ai/covers/{episodeId}.png",
"audioUrl": "https://assets.listenhub.ai/storybook/{episodeId}.mp3",
"audioDuration": 180,
"videoUrl": "",
"videoStatus": "not_generated",
"pages": [
{
"text": "Welcome to the Q3 business review. This quarter saw remarkable growth...",
"pageNumber": 1,
"imageUrl": "https://assets.listenhub.ai/pages/{episodeId}-1.png",
"audioTimestamp": 0
},
{
"text": "Revenue grew 45% year-over-year, primarily driven by APAC expansion...",
"pageNumber": 2,
"imageUrl": "https://assets.listenhub.ai/pages/{episodeId}-2.png",
"audioTimestamp": 25.3
}
]
}
}Slides + voiceover scripts: Each item in pages[] contains an imageUrl (slide visual) and text (voiceover script, ~80–100 words per slide). Download these to build your own presentations or remix the content.
processStatus
| Value | Meaning |
|---|---|
pending | Processing |
success | Complete |
fail | Failed (check failCode) |
videoStatus
| Value | Meaning |
|---|---|
not_generated | Video not yet triggered |
pending | Video generating |
success | Video ready (videoUrl available) |
fail | Video generation failed |
Generation typically takes 2–5 minutes. Recommended polling: wait 60 seconds, then poll every 10 seconds.
Generate Video
POST /v1/storybook/episodes/{episodeId}/video
Trigger video generation for a completed slides episode. processStatus must be success.
Wait until processStatus is success before calling this endpoint.
curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}/video" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/storybook/episodes/${episodeId}/video`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
}
);
console.log(await response.json());import os, requests
response = requests.post(
f'https://api.marswave.ai/openapi/v1/storybook/episodes/{episode_id}/video',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
print(response.json())Response:
{
"code": 0,
"message": "",
"data": {
"success": true
}
}After triggering, poll GET /v1/storybook/episodes/{episodeId} until videoStatus is success.
Complete Workflow
Create Slides Episode
Call POST /v1/storybook/episodes with mode: "slides", your source, and speaker. Save the returned episodeId.
Poll for Completion
Poll GET /v1/storybook/episodes/{episodeId} every 10 seconds (after an initial 60-second wait) until processStatus is success.
Use Slides + Scripts (Optional)
The pages[] array contains slide visuals (imageUrl) and voiceover scripts (text). Download these to build your own presentations without generating a video.
Generate Video
Call POST /v1/storybook/episodes/{episodeId}/video to combine slides into a narrated video.
Poll Video Status
Poll until videoStatus is success. The videoUrl field contains the download link.