Download OpenAPI specification:
This document is the Marswave OpenAPI reference for user-facing endpoints.
Full integration guide: https://blog.listenhub.ai/openapi-docs-en
Uses API key authentication, format: Authorization: Bearer < your api key >
Retrieve your API key: Visit the API Keys settings page
Retrieve current user subscription status and credit usage information.
{- "code": 0,
- "message": "",
- "data": {
- "subscriptionStartedAt": 1718230400000,
- "subscriptionExpiresAt": 1720918800000,
- "usageAvailableMonthlyCredits": 80,
- "usageTotalMonthlyCredits": 100,
- "usageAvailablePermanentCredits": 50,
- "usageTotalPermanentCredits": 50,
- "usageAvailableLimitedTimeCredits": 20,
- "totalAvailableCredits": 150,
- "resetAt": 1721005200000,
- "platform": "web",
- "renewStatus": true,
- "paidStatus": true,
- "subscriptionPlan": {
- "name": "Pro Monthly",
- "duration": "monthly",
- "platform": "web"
}
}
}Retrieve available voices. When an API Key is provided, the response includes the user's accessible private voices; otherwise only public voices are returned.
| language | string Example: language=en/zh/ja Filter language type |
{- "code": 0,
- "message": "",
- "data": {
- "items": [
- {
- "name": "American Female",
- "speakerId": "speaker_001",
- "gender": "female",
- "language": "en"
}
]
}
}Create new podcast episode based on provided text and other settings.
| query | string Text to be synthesized |
Array of objects Optional, other sources | |
required | Array of objects [ 1 .. 2 ] items Required, voice type |
| language | string Enum: "en" "zh" "ja" Optional, en/zh/ja, language type. Default: en (English) |
| mode | string Enum: "deep" "quick" "debate" Generation mode deep: deep mode, quick: quick mode, debate: debate mode. Default: quick (quick mode) |
{- "query": "string",
- "sources": [
- {
- "type": "text",
- "content": "string"
}
], - "speakers": [
- {
- "speakerId": "string"
}
], - "language": "en",
- "mode": "deep"
}{- "code": 0,
- "message": "",
- "data": {
- "episodeId": "688c9a27348f001e707ba331"
}
}Query detailed information of specified Podcast episode, including blog text, audio content, etc.
| episodeId required | string Podcast episode unique identifier |
{- "code": 0,
- "message": "",
- "data": {
- "episodeId": "688c9a27348f001e707ba331",
- "createdAt": 1718230400,
- "message": "success",
- "failCode": 0,
- "processStatus": "success",
- "completedTime": 1718230400,
- "sourceProcessResult": {
- "content": "User-provided source text content",
- "references": [ ]
}, - "title": "My Podcast Title",
- "outline": "This is a podcast outline.",
- "scripts": [
- {
- "speakerId": "speaker-1",
- "speakerName": "Host A",
- "content": "This is the first segment content"
}
]
}
}Get outline or script text stream content of specified Podcast episode, returned in Server-Sent Events (SSE) format.
| episodeId required | string Podcast episode unique identifier |
| event required | string Enum: "script" "outline" Query event type (script or outline) |
Two-stage generation - Stage 1: Generate only podcast content (scripts, outline, etc.), without audio.
After generation completes, you can:
/v1/podcast/episodes/{episodeId}/audio to generate audio| query | string Text to be synthesized |
Array of objects Optional, other sources | |
required | Array of objects [ 1 .. 2 ] items Required, voice type |
| language required | string Enum: "en" "zh" "ja" Required, en/zh/ja, language type. Speaker language must match this parameter |
| mode | string Enum: "deep" "quick" "debate" Generation mode: deep (deep mode), quick (quick mode), debate (debate mode). Default: quick (quick mode) |
{- "query": "string",
- "sources": [
- {
- "type": "text",
- "content": "string"
}
], - "speakers": [
- {
- "speakerId": "string"
}
], - "language": "en",
- "mode": "deep"
}{- "code": 0,
- "message": "",
- "data": {
- "episodeId": "688c9a27348f001e707ba331",
- "status": "pending",
- "message": "Text content generation started. Audio generation can be triggered later."
}
}Two-stage generation - Stage 2: Generate audio based on existing content.
Prerequisites:
/v1/podcast/episodes/text-content to generate contentUse cases:
/v1/podcast/episodes/text-content to generate content| episodeId required | string Podcast episode unique identifier |
Array of objects Optional, custom scripts array (uses existing scripts if not provided). Podcast scripts must contain 1-2 different speakers. |
{- "scripts": [
- {
- "content": "Welcome to this episode",
- "speakerId": "speaker_001"
}, - {
- "content": "Today we're going to discuss an interesting topic",
- "speakerId": "speaker_002"
}
]
}{- "code": 0,
- "message": "",
- "data": {
- "success": true,
- "message": "Audio generation started",
- "episodeId": "688c9a27348f001e707ba331",
- "status": "pending"
}
}Create new flow speech episode based on provided text and other settings.
required | Array of objects = 1 items Required, source information |
required | Array of objects [ 1 .. 2 ] items Required, voice type |
| language | string Enum: "en" "zh" "ja" Optional, en/zh/ja, language type |
| mode | string Enum: "smart" "direct" Generation mode smart: AI-enhanced mode (fixes grammar, typos, etc.), direct: pass-through mode (no modifications, directly converts to speech) |
{- "sources": [
- {
- "type": "text",
- "content": "string",
- "uri": "string",
- "metadata": { }
}
], - "speakers": [
- {
- "speakerId": "string"
}
], - "language": "en",
- "mode": "smart"
}{- "code": 0,
- "message": "",
- "data": {
- "episodeId": "688c9a27348f001e707ba331"
}
}Query detailed information of specified Flowspeech episode, including text, audio content, etc.
| episodeId required | string Flowspeech episode unique identifier |
{- "code": 0,
- "message": "",
- "data": {
- "episodeId": "flowspeech_episode_001",
- "createdAt": 0,
- "message": "success",
- "failCode": 0,
- "processStatus": "success",
- "completedTime": 0,
- "sourceProcessResult": {
- "content": "User-provided source text content",
- "references": [ ]
}, - "title": "My Flowspeech Title",
- "outline": "This is a Flowspeech outline.",
- "scripts": "This is script content"
}
}Get outline or script text stream content of specified Flowspeech episode, returned in Server-Sent Events (SSE) format.
| episodeId required | string Flowspeech episode unique identifier |
| event required | string Enum: "script" "outline" Query event type (script or outline) |
id: 689ef06042a332af99cd5781 event: script data: {"code":0, "message":"", "data": {"chunk":"Suddenly turned into a giant watermark frame."}} id: 689ef06042a332af99cd5781 event: script data: {"code":0, "message":"", "data": {"chunk":"Every window of this century-old building"}} id: 689ef06042a332af99cd5781 event: script data: {"code":0, "message":"", "data": {"chunk":"[END]"}}
Generate audio directly from scripts without creating an Episode, supporting multi-speaker dialogue.
Features:
Use Cases:
Credit Calculation:
required | Array of objects non-empty Required, script array |
{- "scripts": [
- {
- "content": "Hello everyone, welcome to today's episode",
- "speakerId": "speaker_001"
}, - {
- "content": "Today we're going to talk about an interesting topic",
- "speakerId": "speaker_002"
}
]
}{- "code": 0,
- "message": "",
- "data": {
- "audioDuration": 1152,
- "taskId": "1eed39d387a046c0a1213e6b8f139d77",
- "credits": 12
}
}Text-to-speech interface that returns audio binary stream directly.
Features:
Use Cases:
Differences from /v1/speech:
/v1/tts: Streaming binary output, single speaker, real-time return/v1/speech: JSON response, multi-speaker support, synchronous URL returnCredit Calculation:
| input required | string Text content to be converted to speech |
| voice required | string Speaker ID (speakerId) |
| model | string Default: "flowtts" Model name (optional, default: flowtts). Note: This parameter is currently not processed, for compatibility only |
{- "input": "The weather is beautiful today, perfect for a walk outside.",
- "voice": "speaker_001",
- "model": "flowtts"
}| Code | Description | Suggested Action |
|---|---|---|
| 21007 | Invalid API key | Verify that the API key is configured correctly |
| 25002 | Resource not found | Check whether the requested resource ID exists |
| 25008 | Invalid episode status | Verify that text content generation is complete and contentStatus is text-success |
| 26004 | Insufficient credits | Review account credit balance, upgrade the plan, or contact support |
| 29003 | Invalid parameters | Validate request parameter formats and required fields |
| 29998 | Too many requests | Implement exponential backoff retries; wait 20-30 seconds between attempts |
| Code | Description | Applicable APIs |
|---|---|---|
| 91001 | Content too short | Podcast, FlowSpeech |
| 91002 | Content violates policy | Podcast, FlowSpeech |
| 91003 | Search failed | Podcast, FlowSpeech |
| 91004 | Unable to retrieve content | Podcast, FlowSpeech |
| 91005 | Unable to access URL content | Podcast, FlowSpeech |
| 91006 | Processing failed | Podcast, FlowSpeech |
| 91007 | File size too large | Podcast, FlowSpeech |
All errors are returned in HTTP 200 responses and differentiated by the code field:
{
"code": 21007,
"message": "Invalid user APIKey",
"data": {}
}
When the API returns a system error code, you usually need to fix the request parameters or inspect the account status.
When a polling endpoint returns success (code: 0) but data.failCode is present, the content generation has failed:
{
"code": 0,
"message": "",
"data": {
"episodeId": "xxx",
"processStatus": "failed",
"failCode": 91001,
"message": "Content is too short"
}
}