API 레퍼런스
프로그래밍 방식으로 AI 동영상을 생성합니다. 프롬프트를 제출하고, 완료를 폴링하고, 직접 동영상 URL을 받으세요 — 모두 REST로.
기본 URL: https://yoh.app로그인하기 전까지 코드 예시에는 플레이스홀더 가 사용됩니다.
빠른 시작
세 번의 API 호출로 첫 번째 동영상 만들기: 생성 → 폴링 → 다운로드.
curl -X POST https://yoh.app/api/v1/stories/generate \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "A dragon teaches a young knight how to fly", "aspectRatio": "16:9" }'{
"jobId": "cmnk8wu2q0001q3vpmqv93nmy",
"status": "queued",
"pollUrl": "/api/v1/stories/jobs/cmnk8wu2q0001q3vpmqv93nmy"
}curl https://yoh.app/api/v1/stories/jobs/cmnk8wu2q0001q3vpmqv93nmy \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"{
"status": "completed", "progress": 100,
"storyId": "cmnk8xxnx000004lbd7siief7",
"videoUrl": "https://cdn.example.com/video/clip.mp4",
"error": null
}완성! videoUrl은 즉시 다운로드, 스트리밍 또는 공유할 수 있는 공개 접근 URL입니다.
인증
모든 API 요청은 스킴을 사용하여 헤더에 API 키를 포함해야 합니다.
Authorization: Bearer sk_live_YOUR_API_KEYAPI 키는 로 시작합니다. 에서 키를 생성하고 관리할 수 있습니다.
API 키를 비밀로 유지하세요. 클라이언트 측 코드나 공개 저장소에 노출하지 마세요. 키가 유출된 경우 즉시 API 키 페이지에서 취소하세요.
범위 및 크레딧
각 API 키에는 접근할 수 있는 엔드포인트를 제어하는 하나 이상의 범위가 부여됩니다. 스토리 생성은 작업당 크레딧을 소비합니다. 모든 재시도 후 작업이 실패하면 크레딧이 환불됩니다.
| 범위 | 접근 권한 부여 |
|---|---|
| stories:generate | POST /api/v1/stories/generate, POST /api/v1/series-assets/ensure-character-image |
| stories:read | GET /api/v1/stories, GET /api/v1/stories/:id, GET /api/v1/stories/jobs/:id |
| assets:read | GET .../characters, .../scenes, .../items, .../clips |
동영상 생성
동영상 생성 작업 큐 추가
/api/v1/stories/generatescope: stories:generate프롬프트를 제출하고 즉시 를 반환합니다. 동영상은 비동기로 생성됩니다. 을 폴링하여 진행 상황을 추적하세요.
요청 본문
| 필드 | 타입 | 상태 | 설명 |
|---|---|---|---|
prompt | string | 필수 | 스토리 설명, 최대 5000자. |
aspectRatio | string | 선택 | , , , 중 하나. 기본값: . |
renderVideo | boolean | 선택 | — 첫 번째 AI 클립 반환 (빠름, ~10분). — Remotion을 통해 모든 클립을 하나의 합성 MP4로 렌더링 (~12–15분). |
title | string | 선택 | 스토리의 표시 이름. |
contentType | string | 선택 | 스토리 형식 카테고리. cinematic_story, news_analysis, music_video, persona_channel, youtube_clone, ad_spot 중 하나. 기본값: cinematic_story. |
locale | string | 선택 | 언어 코드 (예: , ). 기본값: . |
seriesId | string | 선택 | 일관된 캐릭터 비주얼을 위해 기존 시리즈에 연결합니다. |
응답 202 Accepted
{ "jobId": "cmnk8wu2q0001q3vpmqv93nmy", "status": "queued", "pollUrl": "/api/v1/stories/jobs/..." }작업 폴링
작업 상태 가져오기
/api/v1/stories/jobs/:jobIdscope: stories:read호출 후 이 엔드포인트를 폴링합니다. 스토리 길이와 활성화 여부에 따라 작업은 보통 8–15분이 소요됩니다. 마다 폴링하는 것을 권장합니다.
작업 상태 생명주기
queuedgenerating_storygenerating_videosrendering_videocompleted또는failed응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
jobId | string | 고유 작업 식별자. |
status | string | 현재 상태. 위의 생명주기 참조. |
progress | number | 완료 백분율을 나타내는 0–100 정수. |
storyId | string|null | 스토리 생성 완료 후 설정. 에셋 가져오기에 사용. |
renderVideo | boolean | 합성 최종 MP4가 요청되었는지 여부. |
videoUrl | string|null | 상태가 completed일 때의 절대 동영상 URL. 합성 MP4(renderVideo: true) 또는 첫 번째 클립의 AI 동영상(renderVideo: false). |
error | string|null | 실패 시 사람이 읽을 수 있는 오류 메시지. 성공 시 항상 null. |
createdAt / startedAt / completedAt | string (ISO) | 타임스탬프. |
스토리
스토리 목록
/api/v1/storiesscope: stories:read스토리의 페이지 목록을 반환합니다.
쿼리 파라미터
| 파라미터 | 기본값 | 설명 |
|---|---|---|
page | 1 | 페이지 번호 (≥ 1). |
limit | 20 | 페이지당 결과 수 (1–100). |
status | — | 스토리 상태로 필터링. |
스토리 가져오기
/api/v1/stories/:storyIdscope: stories:read캐릭터, 장면, 아이템, 클립의 수를 포함한 단일 스토리의 전체 메타데이터를 반환합니다.
{
"id": "cmnk9cibl0004q3vpijkqfwl4",
"title": "A robot chef cooks in a futuristic kitchen",
"status": "completed", "aspectRatio": "9:16", "locale": "en",
"counts": { "characters": 3, "scenes": 4, "items": 6, "clips": 6 },
"createdAt": "2026-04-04T11:37:04.662Z"
}에셋 개요
작업이 완료되면 작업이 반환한 를 사용하여 스토리에 대해 생성된 모든 에셋을 가져올 수 있습니다. 모든 에셋 엔드포인트에는 범위가 필요합니다.
GET /api/v1/stories/:id/characters캐릭터 — 이름, 설명, 역할, imageUrl, 음성 정보
GET /api/v1/stories/:id/scenes장면 — 설명, 시간대, 날씨, 조명, imageUrl
GET /api/v1/stories/:id/items소품 / 아이템 — 설명, 중요도, imageUrl
GET /api/v1/stories/:id/clips클립 — 내레이션, 시간, videoUrl, imageUrl, audioUrl
캐릭터
캐릭터 목록
/api/v1/stories/:storyId/charactersscope: assets:read{
"data": [{
"id": "char_abc123", "name": "Chef Axon", "role": "protagonist",
"description": "A robot chef with a warm personality",
"imageUrl": "https://cdn.example.com/characters/chef-axon.jpg",
"voiceName": "Neutral-EN", "order": 0
}]
}클립 및 동영상
클립 목록
/api/v1/stories/:storyId/clipsscope: assets:read각 클립은 AI 생성 동영상, 정지 이미지, 오디오가 있는 장면 세그먼트입니다. 모든 URL 필드는 절대 경로이며 공개 접근 가능합니다.
{
"data": [{
"id": "clip_001", "order": 0, "narration": "In the year 2157...",
"duration": 8,
"videoUrl": "https://cdn.example.com/generated/video/clip1.mp4",
"imageUrl": "https://cdn.example.com/generated/image/clip1.jpg",
"audioUrl": null, "status": "completed"
}]
}가 false인 경우, 작업의 은 첫 번째 클립의 동영상을 가리킵니다. 이 엔드포인트를 사용하여 각 클립의 동영상 URL을 가져오세요.
시리즈 에셋
시리즈에 캐릭터 이미지 등록
/api/v1/series-assets/ensure-character-imagescope: stories:generate시리즈에 대한 캐릭터 참조 이미지를 업로드하고 저장하여 AI가 해당 시리즈의 모든 스토리에서 일관된 외모를 사용할 수 있도록 합니다. 이 작업은 입니다 — 동일한 캐릭터 이름으로 여러 번 호출해도 안전합니다.
| 필드 | 타입 | 설명 |
|---|---|---|
seriesId | string | 캐릭터를 연결할 시리즈의 ID. |
characterName | string | 캐릭터 이름 (시리즈 내 고유 키로 사용). |
imageUrl | string | 캐릭터 참조 이미지의 공개 접근 가능한 URL. |
API 키 관리
API 키 관리 엔드포인트는 API 키가 아닌 (로그인한 사용자 쿠키)를 사용합니다. 브라우저 기반 워크플로에는 를 사용하거나, 유효한 세션으로 백엔드에서 프로그래밍 방식으로 이 엔드포인트를 호출하세요.
API 키 목록
/api/v1/api-keysscope: session{
"data": [{
"id": "key_abc123", "name": "Production",
"keyPrefix": "sk_live_7WH3",
"scopes": ["stories:generate", "stories:read", "assets:read"],
"revokedAt": null, "createdAt": "2026-04-03T10:00:00.000Z"
}]
}API 키 생성
/api/v1/api-keysscope: session// Response — full key shown once
{
"id": "key_abc123",
"key": "sk_live_...",
"name": "My integration",
"keyPrefix": "sk_live_7WH3",
"scopes": ["stories:generate", "stories:read", "assets:read"]
}API 키 취소
/api/v1/api-keys/:idscope: session{ "id": "key_abc123", "revoked": true }오류
모든 오류는 기계 판독 가능한 를 포함하는 객체가 있는 일관된 JSON 형태를 반환합니다.
{ "error": { "code": "insufficient_credits", "message": "...", "status": 402 } }| HTTP | 코드 | 의미 |
|---|---|---|
| 401 | unauthorized | API 키가 없거나 유효하지 않습니다. |
| 403 | forbidden | API 키에 필요한 범위가 없습니다. |
| 404 | not_found | 요청한 리소스가 존재하지 않습니다. |
| 400 | bad_request | 잘못된 요청 본문 또는 파라미터. |
| 402 | insufficient_credits | 이 작업을 수행할 크레딧이 부족합니다. |
| 429 | rate_limited | 요청이 너무 많습니다. Retry-After 헤더를 확인하세요. |
| 500 | internal_error | 예기치 않은 서버 오류. |
속도 제한: 생성 엔드포인트는 읽기 엔드포인트보다 더 엄격한 속도 제한이 있습니다. 제한에 도달하면 응답에 기다릴 초 수를 포함하는 헤더가 포함됩니다. 실패한 작업(모든 재시도 후)은 차감된 25 크레딧을 자동으로 환불합니다.