콘텐츠 추출
웹 기사, Twitter/X 프로필과 트윗, YouTube 동영상, 위챗 공식 계정 게시물 등 URL에서 텍스트 콘텐츠를 비동기로 추출합니다.
콘텐츠 추출
임의의 URL에서 텍스트 콘텐츠를 비동기로 추출합니다. URL을 제출해 작업을 생성한 뒤, 결과를 폴링(polling)해서 가져옵니다.
지원 소스
X / Twitter
프로필 페이지와 개별 트윗 — 공개 계정의 최근 게시물을 가져오거나, 트윗 하나를 전체 맥락과 함께 추출합니다.
YouTube
공개된 YouTube 동영상 URL에서 자막 텍스트와 메타데이터를 추출합니다.
위챗 공식 계정
위챗 공식 계정 게시물(mp.weixin.qq.com)의 기사 본문을 추출합니다.
웹 기사
공개적으로 접근 가능한 모든 웹 페이지 — 기사 본문, 메타데이터, 참조 링크.
활용 사례
- 팟캐스트 소재 수집 -- 기사, 트윗, 위챗 게시물을 추출해 팟캐스트 생성의 입력으로 사용합니다
- 콘텐츠 요약 --
summarize로 장문 콘텐츠 가져오기와 요약 생성을 한 번의 호출로 처리합니다 - 소셜 미디어 모니터링 -- 주요 계정의 트윗을 일괄 추출합니다
- 리서치 집계 -- 여러 URL에서 콘텐츠를 수집하고 구조화합니다
추출 작업 생성
POST /v1/content/extract
작업 제출은 논블로킹입니다. 엔드포인트는 요청을 검증하고 크레딧을 예약한 뒤 추출을 시작하고, 즉시 taskId를 반환합니다. 결과는 작업 상태 조회로 가져옵니다.
요청 예시:
curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": {
"type": "url",
"uri": "https://example.com/article"
}
}'const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
type: 'url',
uri: 'https://example.com/article',
},
}),
});
const data = await response.json();
const taskId = data.data.taskId;
console.log('Task ID:', taskId);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/content/extract',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'source': {
'type': 'url',
'uri': 'https://example.com/article',
}
}
)
data = response.json()
task_id = data['data']['taskId']
print('Task ID:', task_id)옵션 지정(요약 + 최대 길이):
summarize: true로 설정하면 추출된 텍스트가 AI 요약으로 압축되고, maxLength로 반환되는 문자 수의 상한을 정할 수 있습니다.
curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": {
"type": "url",
"uri": "https://example.com/long-article"
},
"options": {
"summarize": true,
"maxLength": 5000
}
}'const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
type: 'url',
uri: 'https://example.com/long-article',
},
options: {
summarize: true,
maxLength: 5000,
},
}),
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/content/extract',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'source': {
'type': 'url',
'uri': 'https://example.com/long-article',
},
'options': {
'summarize': True,
'maxLength': 5000,
},
}
)
data = response.json()
print(data)Twitter/X 프로필 URL(트윗 개수 지정):
# For Twitter/X profile URLs, use the twitter option to control how many tweets to fetch
curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": {
"type": "url",
"uri": "https://x.com/elonmusk"
},
"options": {
"twitter": {
"count": 50
}
}
}'const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
type: 'url',
uri: 'https://x.com/elonmusk',
},
options: {
twitter: {
count: 50,
},
},
}),
});
const data = await response.json();
console.log(data);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/content/extract',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'source': {
'type': 'url',
'uri': 'https://x.com/elonmusk',
},
'options': {
'twitter': {
'count': 50,
},
},
}
)
data = response.json()
print(data)위챗 공식 계정 기사:
curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": {
"type": "url",
"uri": "https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX"
}
}'const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
type: 'url',
uri: 'https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX',
},
}),
});
const data = await response.json();
const taskId = data.data.taskId;import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/content/extract',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'source': {
'type': 'url',
'uri': 'https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX',
}
}
)
data = response.json()
task_id = data['data']['taskId']요청 본문:
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
source | object | 예 | 추출 대상 소스 |
source.type | string | 예 | "url"이어야 합니다 |
source.uri | string | 예 | 콘텐츠를 추출할 URL |
options | object | 아니요 | 추출 옵션(기본값 {}) |
options.summarize | boolean | 아니요 | 추출된 텍스트에 대한 AI 요약 생성(기본값 false) |
options.maxLength | integer | 아니요 | 콘텐츠 최대 길이(문자 수, 기본값 100000, 최소 1, 최대 500000) |
options.twitter | object | 아니요 | Twitter/X 전용 옵션 |
options.twitter.count | integer | 아니요 | 프로필 URL에서 가져올 트윗 개수(1–100, 기본값 20) |
응답 예시:
{
"code": 0,
"message": "success",
"data": {
"taskId": "67f6a1b2c3d4e5f6a7b8c9d0"
}
}taskId는 24자리 16진수 문자열입니다. 아래의 상태 조회 엔드포인트에 전달하세요.
작업 상태 조회
GET /v1/content/extract/{taskId}
status가 completed 또는 failed가 될 때까지 이 엔드포인트를 폴링합니다. 작업이 진행 중인 동안 응답에는 상태만 담기며, 추출된 콘텐츠는 추출과 크레딧 정산이 끝날 때까지 반환되지 않습니다.
요청 예시:
curl -X GET "https://api.marswave.ai/openapi/v1/content/extract/67f6a1b2c3d4e5f6a7b8c9d0" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const result = await fetch(`https://api.marswave.ai/openapi/v1/content/extract/${taskId}`, {
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
},
});
const data = await result.json();
console.log('Status:', data.data.status);import os
import requests
result = requests.get(
f'https://api.marswave.ai/openapi/v1/content/extract/{task_id}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
data = result.json()
print('Status:', data['data']['status'])경로 파라미터:
| 필드 | 타입 | 설명 |
|---|---|---|
taskId | string | 생성 엔드포인트가 반환한 24자리 16진수 문자열 |
처리 중일 때의 응답(status: "processing"):
{
"code": 0,
"message": "success",
"data": {
"taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
"status": "processing",
"createdAt": 1744200000000
}
}작업이 완료되기 전까지 data 객체(추출된 콘텐츠)는 반환되지 않습니다.
완료 시의 응답(status: "completed"):
{
"code": 0,
"message": "success",
"data": {
"taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
"status": "completed",
"createdAt": 1744200000000,
"data": {
"content": "The extracted article text content...",
"metadata": {
"title": "Article Title",
"author": "Author Name"
},
"references": [
"https://example.com/related-article"
]
},
"credits": 100
}
}실패 시의 응답(status: "failed"):
{
"code": 0,
"message": "success",
"data": {
"taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
"status": "failed",
"createdAt": 1744200000000,
"failCode": 1001,
"message": "Failed to extract content from URL"
}
}응답 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
taskId | string | 작업 식별자 |
status | string | processing, completed, failed 중 하나 |
createdAt | integer | 생성 시각, 13자리 밀리초 단위 epoch 타임스탬프 |
data | object | 추출된 콘텐츠. status가 completed일 때만 포함됩니다 |
data.content | string | 추출된 텍스트 콘텐츠(summarize: true인 경우 요약본) |
data.metadata | object | 제목, 작성자 등 페이지 메타데이터 |
data.references | array | 콘텐츠에서 발견된 참조 URL |
credits | integer | 소비된 크레딧(status가 completed일 때 포함) |
failCode | integer | 에러 코드(status가 failed일 때 포함) |
message | string | 에러 설명(status가 failed일 때 포함) |
참고 사항
Twitter/X 프로필 URL:
- 소스 URL이 Twitter/X 프로필(예:
https://x.com/username)이면 API가 최근 트윗을 가져옵니다. options.twitter.count로 가져올 트윗 개수를 지정합니다(1–100, 기본값20).- Twitter 이외의 URL에서는 이 옵션이 무시됩니다.
위챗 공식 계정:
- 전체
mp.weixin.qq.com/s/...기사 URL을 사용하세요. - 추출된 콘텐츠에는 기사 본문과 메타데이터가 포함됩니다.
작업 라이프사이클:
| 상태 | 설명 |
|---|---|
processing | 추출 진행 중 |
completed | 콘텐츠 추출 성공 |
failed | 추출 실패 -- failCode와 message를 확인하세요 |
폴링 권장 설정:
- 최초 대기: 작업 생성 후 5초
- 폴링 간격: 5초
- 일반적인 완료 시간: URL 복잡도에 따라 10-30초
크레딧:
콘텐츠 추출은 작업이 시작될 때 크레딧을 예약하고, 콘텐츠 길이가 확정되면 실제 금액으로 정산합니다. 완료 응답의 credits 필드가 최종 청구 금액을 나타냅니다.
| 규칙 | 상세 |
|---|---|
| 선차감 | 작업이 시작될 때 소액이 예약됩니다 |
| 실제 청구 | 추출된 콘텐츠의 문자 수를 기준으로 하며, maxLength를 상한으로 합니다 |
| 실패 시 환불 | 추출이 실패하면 예약된 크레딧이 전액 환불됩니다 |
콘텐츠 추출 자체에는 견적 엔드포인트가 없습니다. 최종 credits 값은 콘텐츠 길이가 확정된 뒤에야 알 수 있습니다. 실시간 잔액은 GET /v1/user/subscription으로 확인하고, 크레딧과 기능의 대응 관계는 크레딧 및 요금을 참고하세요.