빠른 시작
API 키를 발급받고 5분 안에 첫 호출을 완료하세요.
사전 준비
API 키 발급받기:
- API 키 설정 페이지로 이동합니다
- API 키 만들기를 클릭합니다
- API 키를 복사해 안전한 곳에 보관합니다
API 키는 생성 시점에 한 번만 표시됩니다. 즉시 복사해서 안전한 위치에 저장하세요.
환경 변수 설정하기:
API 키를 환경 변수로 저장하세요. 이 가이드의 모든 코드 예제는 이 환경 변수를 참조합니다:
# Add to ~/.zshrc or ~/.bashrc to persist across sessions
export LISTENHUB_API_KEY="your_api_key_here"그 밖의 설정 방법은 인증을 참고하세요.
첫 호출 해보기
API 키 확인
간단한 요청을 보내 API 키가 정상적으로 동작하는지 확인합니다:
curl -X GET "https://api.marswave.ai/openapi/v1/speakers/list?language=en" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch('https://api.marswave.ai/openapi/v1/speakers/list?language=en', {
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
},
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.get(
'https://api.marswave.ai/openapi/v1/speakers/list',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
params={'language': 'en'}
)
data = response.json()
print(data)성공 응답:
{
"code": 0,
"message": "",
"data": {
"items": [
{
"name": "Ethan",
"speakerId": "EN-Man-General-01",
"demoAudioUrl": "https://example.com/demo-ethan.mp3",
"gender": "male",
"language": "en"
},
{
"name": "Sophia",
"speakerId": "EN-Woman-General-01",
"demoAudioUrl": "https://example.com/demo-sophia.mp3",
"gender": "female",
"language": "en"
}
]
}
}첫 팟캐스트 만들기
quick 모드로 화자 한 명짜리 에피소드를 생성합니다:
curl -X POST "https://api.marswave.ai/openapi/v1/podcast/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Give a concise introduction to the history of artificial intelligence.",
"speakers": [{"speakerId": "EN-Man-General-01"}],
"language": "en",
"mode": "quick"
}'const response = await fetch('https://api.marswave.ai/openapi/v1/podcast/episodes', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'Give a concise introduction to the history of artificial intelligence.',
speakers: [{ speakerId: 'EN-Man-General-01' }],
language: 'en',
mode: 'quick',
}),
});
const data = await response.json();
console.log('Episode ID:', data.data.episodeId);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/podcast/episodes',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'query': 'Give a concise introduction to the history of artificial intelligence.',
'speakers': [{'speakerId': 'EN-Man-General-01'}],
'language': 'en',
'mode': 'quick',
}
)
data = response.json()
print('Episode ID:', data['data']['episodeId'])성공 응답:
{
"code": 0,
"message": "",
"data": {
"episodeId": "{episodeId}"
}
}팟캐스트 생성은 비동기로 처리됩니다. episodeId는 생성 진행 상황을 추적할 때 사용하는 식별자입니다.
생성 결과 조회
반환된 episodeId로 상태를 폴링(polling)합니다:
curl -X GET "https://api.marswave.ai/openapi/v1/podcast/episodes/{episodeId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
'https://api.marswave.ai/openapi/v1/podcast/episodes/{episodeId}',
{
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
}
);
const data = await response.json();
console.log('Status:', data.data.processStatus);import os
import requests
response = requests.get(
'https://api.marswave.ai/openapi/v1/podcast/episodes/{episodeId}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
data = response.json()
print('Status:', data['data']['processStatus'])처리 중일 때의 응답(processStatus가 pending):
{
"code": 0,
"message": "",
"data": {
"episodeId": "{episodeId}",
"createdAt": 1760517419993,
"failCode": 0,
"processStatus": "pending",
"credits": 0,
"sourceProcessResult": {
"content": "Give a concise introduction to the history of artificial intelligence.",
"references": []
},
"title": "",
"outline": "",
"cover": "https://static.listenhub.ai/listenhub_default_cover061802.png",
"audioUrl": "",
"scripts": []
}
}완료된 뒤의 응답(processStatus가 success):
{
"code": 0,
"message": "",
"data": {
"episodeId": "{episodeId}",
"createdAt": 1760517752411,
"failCode": 0,
"processStatus": "success",
"credits": 27,
"sourceProcessResult": {
"content": "Give a concise introduction to the history of artificial intelligence.",
"references": []
},
"title": "A Brief History of Artificial Intelligence",
"outline": "...",
"cover": "https://static.listenhub.ai/listenhub_default_cover061804.png",
"audioUrl": "https://assets.listenhub.ai/listenhub-public-prod/podcast/{episodeId}.mp3",
"scripts": [
{
"speakerId": "EN-Man-General-01",
"speakerName": "Ethan",
"content": "Artificial intelligence has evolved from symbolic logic to modern large models..."
}
]
}
}processStatus가 success로 바뀌면 audioUrl 필드에 최종 MP3 오디오 URL이 담깁니다.
폴링 모범 사례
팟캐스트 생성에는 보통 1-4분이 걸립니다. 권장 폴링 전략: 첫 조회 전에 60초를 기다린 다음, 10초마다 조회.
async function pollEpisodeResult(episodeId, apiKey, timeout = 300000) {
const url = `https://api.marswave.ai/openapi/v1/podcast/episodes/${episodeId}`;
const headers = { 'Authorization': `Bearer ${apiKey}` };
const startTime = Date.now();
// Generation takes time, wait 60 seconds first
await new Promise(resolve => setTimeout(resolve, 60000));
while (Date.now() - startTime < timeout) {
const response = await fetch(url, { headers });
const data = await response.json();
if (data.code !== 0) throw new Error(`API error: ${data.message}`);
const status = data.data.processStatus;
if (status === 'success') return data.data;
if (status === 'failed') throw new Error(`Generation failed: ${data.data.message}`);
await new Promise(resolve => setTimeout(resolve, 10000));
}
throw new Error('Episode generation timeout');
}import time
import os
import requests
def poll_episode_result(episode_id, api_key, timeout=300):
"""Poll episode result until completion. Default timeout is 5 minutes."""
url = f"https://api.marswave.ai/openapi/v1/podcast/episodes/{episode_id}"
headers = {"Authorization": f"Bearer {api_key}"}
start_time = time.time()
# Generation takes time, wait 60 seconds first
time.sleep(60)
while time.time() - start_time < timeout:
response = requests.get(url, headers=headers)
data = response.json()
if data["code"] != 0:
raise Exception(f"API error: {data['message']}")
status = data["data"]["processStatus"]
if status == "success":
return data["data"]
if status == "failed":
raise Exception(f"Generation failed: {data['data'].get('message')}")
time.sleep(10)
raise TimeoutError("Episode generation timeout")다음 단계
- 핵심 개념 — 에피소드(episode), 화자(speaker), 생성 모드 알아보기
- 팟캐스트 생성 API — 전체 요청 파라미터와 응답 필드
- 텍스트 음성 변환 API — 텍스트를 자연스러운 음성으로 변환