콘텐츠로 이동

콘텐츠 API

콘텐츠 API는 서버용 비공개 키가 필요합니다.

Authorization: Bearer {SERVER_PRIVATE_API_KEY}
Accept: application/json
GET /api/public/v1/contents
이름필수타입설명
language선택stringko, en, ja. 기본값 ko
page선택integer페이지 번호. 기본값 1
limit선택integer페이지당 개수. 기본값 20, 최대 100
status선택stringpublish, pending, paused, in_review, banned
content_type선택stringvod, live, offline, digital_content
category_id선택integer특정 카테고리의 콘텐츠만 조회
category_ids선택array 또는 comma string여러 카테고리 중 하나에 속한 콘텐츠 조회
tag_id선택integer특정 태그의 콘텐츠만 조회
tag_ids선택array 또는 comma string여러 태그 중 하나가 붙은 콘텐츠 조회
search선택string콘텐츠명 검색
Terminal window
curl -X GET "https://{site_host}/api/public/v1/contents?content_type=vod&page=1" \
-H "Authorization: Bearer {SERVER_PRIVATE_API_KEY}" \
-H "Accept: application/json"
GET /api/public/v1/contents/{contentId}
이름필수타입설명
language선택stringko, en, ja. 기본값 ko
POST /api/public/v1/contents

application/json 또는 multipart/form-data로 전송합니다.

이름필수타입설명
content_type필수stringvod, live, offline, digital_content
title필수string콘텐츠명
description_html필수string콘텐츠 상세 HTML
category_ids필수array of integer카테고리 ID 목록
featured_image필수file 또는 string대표 이미지
status선택string기본값 pending
images선택array추가 이미지 목록
thumbnail_link선택string썸네일 링크
inventory_display_mode선택string재고 표시 방식
installment_month선택integer0부터 36
allow_link선택string외부 허용 링크
tag_ids선택array콘텐츠 태그 ID 목록. 현재 콘텐츠당 1개까지 선택 가능
options필수array콘텐츠 유형에 맞는 구매 옵션 목록
유형필수 필드설명
vodtitle, base_price, download_limit_days옵션은 정확히 1개이며 chapters도 1개 이상 필요합니다.
livetitle, base_price, start_at, end_at, access_urlaccess_url은 수강생에게 제공할 접속 링크입니다.
offlinetitle, base_price, start_at, end_at, location_textlocation_detail, capacity를 추가할 수 있습니다.
digital_contenttitle, base_price, download_limit_days, filesfiles에는 HTTPS URL, 기존 file_id, multipart 파일을 넣습니다.

VOD의 chapters에는 titleitems가 필요합니다. 각 item은 title, media_url, duration_text를 가집니다.

콘텐츠는 타입별로 payload shape가 달라집니다. 아래 예시 중 콘텐츠 유형에 맞는 payload를 사용합니다.

{
"content_type": "vod",
"title": "포토샵 입문 클래스",
"description_html": "<p>처음 시작하는 분들을 위한 강의입니다.</p>",
"status": "publish",
"category_ids": [11],
"tag_ids": [23],
"featured_image": "https://example.com/main.jpg",
"options": [
{
"title": "수강권",
"base_price": 39000,
"sale_price": 29000,
"is_on_sale": true,
"download_limit_days": 90
}
],
"chapters": [
{
"title": "1. 시작하기",
"items": [
{
"title": "강의 소개",
"media_url": "https://video.example.com/intro.mp4",
"duration_text": "08:30"
}
]
}
]
}
{
"content_type": "offline",
"title": "브랜드 포지셔닝 워크숍",
"description_html": "<p>오프라인 워크숍입니다.</p>",
"status": "publish",
"category_ids": [11],
"featured_image": "https://example.com/offline.jpg",
"options": [
{
"title": "7월 12일 토요일 14:00",
"base_price": 99000,
"sale_price": 99000,
"start_at": "2026-07-12 14:00:00",
"end_at": "2026-07-12 18:00:00",
"location_text": "서울 성수동"
}
]
}
{
"content_type": "live",
"title": "라이브 광고 런칭 세션",
"description_html": "<p>실시간 라이브 세션입니다.</p>",
"status": "publish",
"category_ids": [11],
"featured_image": "https://example.com/live.jpg",
"options": [
{
"title": "8월 3일 일요일 20:00",
"base_price": 59000,
"sale_price": 59000,
"start_at": "2026-08-03 20:00:00",
"end_at": "2026-08-03 22:00:00",
"access_url": "https://meet.example.com/live-session"
}
]
}
{
"content_type": "digital_content",
"title": "SEO 토픽 클러스터 가이드",
"description_html": "<p>다운로드형 디지털 자료입니다.</p>",
"status": "publish",
"category_ids": [11],
"featured_image": "https://example.com/digital.jpg",
"options": [
{
"title": "파일 다운로드",
"base_price": 29000,
"sale_price": 29000,
"download_limit_days": 90,
"files": [
"https://files.example.com/seo-topic-cluster-guide.pdf"
]
}
]
}

핵심 규칙:

  • content_type은 생성 후 변경하지 않습니다.
  • category_ids는 배열입니다.
  • 처음 연동할 때는 featured_image에 HTTPS 이미지 URL을 보내는 방식이 가장 단순합니다. 파일 업로드가 필요하면 multipart/form-data 예시를 사용합니다.
  • 모든 콘텐츠 유형은 options를 최소 1개 이상 보냅니다. VOD는 옵션이 정확히 1개여야 합니다.
  • offline, live, digital_content는 구매 옵션이 사실상 핵심 데이터입니다.
Terminal window
curl -X POST "https://{site_host}/api/public/v1/contents" \
-H "Authorization: Bearer {SERVER_PRIVATE_API_KEY}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"content_type": "vod",
"title": "포토샵 입문 클래스",
"description_html": "<p>처음 시작하는 분들을 위한 강의입니다.</p>",
"status": "publish",
"category_ids": [11],
"tag_ids": [23],
"featured_image": "https://example.com/main.jpg",
"options": [{
"title": "수강권",
"base_price": 39000,
"download_limit_days": 90
}],
"chapters": [{
"title": "1. 시작하기",
"items": [{
"title": "강의 소개",
"media_url": "https://video.example.com/intro.mp4",
"duration_text": "08:30"
}]
}]
}'

대표 이미지를 파일로 올릴 때는 아래처럼 시작할 수 있습니다.

Terminal window
curl -X POST "https://{site_host}/api/public/v1/contents" \
-H "Authorization: Bearer {SERVER_PRIVATE_API_KEY}" \
-H "Accept: application/json" \
-F "content_type=vod" \
-F "title=포토샵 입문 클래스" \
-F "description_html=<p>처음 시작하는 분들을 위한 강의입니다.</p>" \
-F "category_ids[]=11" \
-F "featured_image=@/absolute/path/main.jpg"
PUT /api/public/v1/contents/{contentId}

전달한 필드만 업데이트합니다. 전달하지 않은 필드는 기존 값을 유지합니다.

  • content_type 변경은 지원하지 않습니다.
  • 수정 요청은 대상 콘텐츠의 현재 유형을 기준으로 검증합니다.
  • 오프라인 콘텐츠에 VOD 전용 chapters 구조를 보내면 422 오류가 반환될 수 있습니다.
  • featured_image를 보내면 대표 이미지가 교체됩니다.
  • images를 보내면 추가 이미지 전체가 교체됩니다.
  • category_ids를 보내면 카테고리 전체가 교체됩니다.
  • tag_ids를 보내면 콘텐츠 태그가 교체됩니다. 빈 배열을 보내면 태그가 제거됩니다.
  • options를 보내면 해당 타입의 옵션 구조가 동기화됩니다.
  • VOD에서 chapters를 보내면 챕터/아이템 구조가 동기화됩니다.
Terminal window
curl -X PUT "https://{site_host}/api/public/v1/contents/4321" \
-H "Authorization: Bearer {SERVER_PRIVATE_API_KEY}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"title": "포토샵 입문 클래스 v2",
"status": "publish",
"category_ids": [11, 12],
"tag_ids": [23]
}'
{
"title": "포토샵 입문 클래스 v2",
"status": "publish",
"category_ids": [11, 12],
"tag_ids": [23]
}

수정 규칙:

  • content_type 변경은 하지 않습니다.
  • category_ids, tag_ids, images, options, chapters는 보내면 전체 교체로 처리됩니다.
  • offline/live에 VOD용 chapters를 보내지 않습니다.
필드설명
content_id콘텐츠 ID
title콘텐츠명
description_html콘텐츠 상세 HTML
content_type콘텐츠 유형
status콘텐츠 상태
language언어 코드
category_ids카테고리 ID 목록
categories카테고리 상세 목록
tag_ids연결된 콘텐츠 태그 ID
featured_image대표 이미지
images추가 이미지
base_price기본가
sale_price할인가
is_on_sale할인 여부
is_free무료 여부
options구매 옵션
chaptersVOD 챕터 구조
created_at생성 일시
updated_at수정 일시

End-to-end 예시: 콘텐츠 서버 연동

섹션 제목: “End-to-end 예시: 콘텐츠 서버 연동”
  1. GET /api/public/v1/content-categories/search?query=포토샵으로 카테고리 ID를 찾습니다.
  2. 자체 CMS 데이터의 content_type을 먼저 확정합니다.
  3. 타입에 맞는 canonical payload를 만듭니다.
  4. 새 콘텐츠면 POST /api/public/v1/contents
  5. 기존 콘텐츠면 PUT /api/public/v1/contents/{contentId}
  6. 생성/수정 후 자체 시스템에 Runmoa content id를 매핑 저장합니다.
  • private API key 누락 또는 오타
  • 다른 사이트용 key 사용
  • 권한 없는 환경에서 호출
  • content_type과 payload 구조가 맞지 않음
  • 잘못된 category_ids
  • 이미지 형식 오류
  • offline/live 일정 필드 누락
  • vod 챕터 구조 불일치

422 응답을 받으면 content_type에 맞게 payload shape를 수정한 뒤 다시 호출합니다.