ListenHubOpenAPI
API 레퍼런스

콘텐츠 추출

웹 기사, 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']

요청 본문:

필드타입필수설명
sourceobject추출 대상 소스
source.typestring"url"이어야 합니다
source.uristring콘텐츠를 추출할 URL
optionsobject아니요추출 옵션(기본값 {})
options.summarizeboolean아니요추출된 텍스트에 대한 AI 요약 생성(기본값 false)
options.maxLengthinteger아니요콘텐츠 최대 길이(문자 수, 기본값 100000, 최소 1, 최대 500000)
options.twitterobject아니요Twitter/X 전용 옵션
options.twitter.countinteger아니요프로필 URL에서 가져올 트윗 개수(1100, 기본값 20)

응답 예시:

{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": "67f6a1b2c3d4e5f6a7b8c9d0"
  }
}

taskId는 24자리 16진수 문자열입니다. 아래의 상태 조회 엔드포인트에 전달하세요.


작업 상태 조회

GET /v1/content/extract/{taskId}

statuscompleted 또는 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'])

경로 파라미터:

필드타입설명
taskIdstring생성 엔드포인트가 반환한 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"
  }
}

응답 필드:

필드타입설명
taskIdstring작업 식별자
statusstringprocessing, completed, failed 중 하나
createdAtinteger생성 시각, 13자리 밀리초 단위 epoch 타임스탬프
dataobject추출된 콘텐츠. statuscompleted일 때만 포함됩니다
data.contentstring추출된 텍스트 콘텐츠(summarize: true인 경우 요약본)
data.metadataobject제목, 작성자 등 페이지 메타데이터
data.referencesarray콘텐츠에서 발견된 참조 URL
creditsinteger소비된 크레딧(statuscompleted일 때 포함)
failCodeinteger에러 코드(statusfailed일 때 포함)
messagestring에러 설명(statusfailed일 때 포함)

참고 사항

Twitter/X 프로필 URL:

  • 소스 URL이 Twitter/X 프로필(예: https://x.com/username)이면 API가 최근 트윗을 가져옵니다.
  • options.twitter.count로 가져올 트윗 개수를 지정합니다(1100, 기본값 20).
  • Twitter 이외의 URL에서는 이 옵션이 무시됩니다.

위챗 공식 계정:

  • 전체 mp.weixin.qq.com/s/... 기사 URL을 사용하세요.
  • 추출된 콘텐츠에는 기사 본문과 메타데이터가 포함됩니다.

작업 라이프사이클:

상태설명
processing추출 진행 중
completed콘텐츠 추출 성공
failed추출 실패 -- failCodemessage를 확인하세요

폴링 권장 설정:

  • 최초 대기: 작업 생성 후 5초
  • 폴링 간격: 5초
  • 일반적인 완료 시간: URL 복잡도에 따라 10-30초

크레딧:

콘텐츠 추출은 작업이 시작될 때 크레딧을 예약하고, 콘텐츠 길이가 확정되면 실제 금액으로 정산합니다. 완료 응답의 credits 필드가 최종 청구 금액을 나타냅니다.

규칙상세
선차감작업이 시작될 때 소액이 예약됩니다
실제 청구추출된 콘텐츠의 문자 수를 기준으로 하며, maxLength를 상한으로 합니다
실패 시 환불추출이 실패하면 예약된 크레딧이 전액 환불됩니다

콘텐츠 추출 자체에는 견적 엔드포인트가 없습니다. 최종 credits 값은 콘텐츠 길이가 확정된 뒤에야 알 수 있습니다. 실시간 잔액은 GET /v1/user/subscription으로 확인하고, 크레딧과 기능의 대응 관계는 크레딧 및 요금을 참고하세요.


이 페이지의 내용