ListenHubOpenAPI
API Reference

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 stylePPT layouts (grid, process flow, big number hero)
Page 1Presentation title page
Best forMeeting 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

ParameterTypeRequiredDescription
sourcesarray(1)YesContent source. Max 1 item.
sources[].typestringYes"text" or "url"
sources[].contentstringYesText content or URL
sources[].uristringNoSource URI
sources[].metadataobjectNoSource metadata
speakersarray(1)YesVoice config. Max 1 item.
speakers[].speakerIdstringYesSpeaker ID (see Speakers)
languagestringNoLanguage code (e.g. "en", "zh")
modestringYesMust be "slides"
stylestringNoVisual 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

ValueMeaning
pendingProcessing
successComplete
failFailed (check failCode)

videoStatus

ValueMeaning
not_generatedVideo not yet triggered
pendingVideo generating
successVideo ready (videoUrl available)
failVideo 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.

On this page