HappyHorse API 문서
애플리케이션에 HappyHorse 1.0 동영상 생성 API를 통합하는 전체 가이드입니다.
빠른 시작
curl -X POST 'https://happyhorse.app/api/generate' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "happyhorse-1.0/video",
"prompt": "A cinematic shot of mountains at sunrise",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9"
}'인증
모든 API 요청에는 Authorization 헤더에 Bearer 토큰이 필요합니다.
API 키 받기: 대시보드의 API Keys 페이지에서 API 키를 확인할 수 있습니다. → API 키 받기
Authorization: Bearer YOUR_API_KEYGenerate와 Status 작동 방식
HappyHorse 영상 작업은 비동기입니다. POST /api/generate로 작업을 만들고 반환된 task_id를 저장한 뒤, 최종 상태가 될 때까지 GET /api/status를 확인합니다.
작업 만들기
prompt, model, mode, duration, 선택 이미지들을 /api/generate로 보내세요. 성공하면 task_id가 즉시 반환됩니다.
상태 폴링
task_id로 /api/status를 호출하세요. status가 IN_PROGRESS인 동안 영상은 아직 렌더링 중이며 response는 null입니다.
결과 읽기
status가 SUCCESS가 되면 data.response.resultUrls[0]이 영상 URL입니다. FAILED가 되면 error_message를 보여주고 폴링을 중지하세요.
사용 가능한 모델
HappyHorse 1.0
HappyHorse 기반 고품질 AI 동영상 생성
| 유형 | 설명 | 길이 | 크레딧 |
|---|---|---|---|
pro (text-to-video) | Pro 품질 텍스트→동영상 | 3-15s | 54/s (no audio) · 80/s (with audio) |
pro (image-to-video) | Pro 품질 이미지→동영상 | 3-15s | 54/s (no audio) · 80/s (with audio) |
std (text-to-video) | 표준 품질 텍스트→동영상 | 3-15s | 40/s (no audio) · 60/s (with audio) |
std (image-to-video) | 표준 품질 이미지→동영상 | 3-15s | 40/s (no audio) · 60/s (with audio) |
API 엔드포인트
새 동영상 생성 작업을 만듭니다. model 필드는 'happyhorse-1.0/video'여야 합니다.
요청 본문
모델 이름, 'happyhorse-1.0/video'여야 합니다
생성할 동영상 설명 텍스트(최대 2500자). multi_shots가 true이면 필수 아님.
품질 모드: 'pro' 또는 'std'(기본: std) Defaults to std.
동영상 길이(초), 3~15. 멀티샷 모드에서는 최종 길이가 multi_prompt 합계로 결정되며, duration을 명시할 경우 각 샷 길이의 합과 같아야 합니다. Defaults to 5 / sum(multi_prompt).
출력 화면비(16:9, 9:16, 1:1) Defaults to 16:9.
이미지→동영상용 이미지 URL 배열
네이티브 오디오 생성 사용(기본: true). 멀티샷 요청에서는 이 필드를 true 또는 false로 명시해 주세요. Defaults to true.
프롬프트 준수 강도(0-1, 기본: 0.5). 높을수록 프롬프트에 더 충실합니다. Defaults to 0.5.
여러 프롬프트가 있는 멀티샷 모드 Defaults to false.
멀티샷 모드용 'prompt, duration' 객체 배열
요소 객체 배열. 프롬프트에는 해당 요소의 name 앞에 @를 붙여 참조(예: name이 element_dog이면 @element_dog). 각 요소: name, description, element_input_urls(2-4 이미지 URL). 작업당 최대 3개.
텍스트→동영상
{
"model": "happyhorse-1.0/video",
"prompt": "A majestic eagle soaring through clouds at sunset",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9",
"sound": true
}이미지→동영상
{
"model": "happyhorse-1.0/video",
"prompt": "The character slowly turns and smiles",
"mode": "pro",
"image_urls": ["https://example.com/my-image.jpg"],
"duration": 5
}멀티샷 동영상
{
"model": "happyhorse-1.0/video",
"mode": "pro",
"multi_shots": true,
"sound": true,
"duration": 10,
"multi_prompt": [
{ "prompt": "A woman walks into a coffee shop", "duration": 3 },
{ "prompt": "She orders a latte and sits by the window", "duration": 4 },
{ "prompt": "She looks outside and smiles", "duration": 3 }
],
"aspect_ratio": "16:9"
}응답
Task created successfully
{
"code": 200,
"message": "success",
"data": {
"task_id": "n92abc123hh10",
"status": "IN_PROGRESS"
}
}generate가 반환한 task_id로 동영상 생성 작업 상태를 확인합니다.
쿼리 매개변수
generate가 반환한 고유 작업 ID(n92 접두사)
요청 예시
curl -X GET 'https://happyhorse.app/api/status?task_id=n92abc123hh10' \
-H 'Authorization: Bearer YOUR_API_KEY'팁: response 필드에 resultUrls 배열이 있습니다. 동영상 URL은 data.response.resultUrls[0]에서 가져옵니다.
// Extract video URL after the task is complete
const task = payload.data;
const videoUrl = task.status === "SUCCESS"
? task.response?.resultUrls?.[0]
: null;응답
{
"code": 200,
"message": "success",
"data": {
"task_id": "n92abc123hh10",
"status": "SUCCESS",
"consumed_credits": 400,
"created_at": "2026-04-08T10:30:00Z",
"type": "text-to-video",
"request": {
"model": "happyhorse-1.0/video",
"prompt": "A majestic eagle soaring through clouds at sunset",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9"
},
"response": {
"resultUrls": [
"https://cdn.example.com/videos/abc123.mp4"
]
},
"error_message": null
}
}폴링 모범 사례
영상 생성에는 시간이 걸릴 수 있으니, 상태 확인은 빡빡한 반복 요청이 아니라 차분한 백그라운드 작업처럼 다루세요.
짧게 기다린 뒤 시작
첫 상태 확인 전 약 8-10초 기다린 뒤 10-20초마다 확인하세요. 더 자주 폴링해도 영상이 더 빨리 끝나지는 않습니다.
최종 상태에서 중지
SUCCESS와 FAILED는 최종 상태입니다. 둘 중 하나가 보이면 즉시 폴링을 멈추고 지원이나 나중 조회를 위해 task_id를 저장하세요.
클라이언트 타임아웃 사용
10-15분 후에는 active wait를 멈추고 사용자가 나중에 상태를 다시 확인할 수 있게 하세요. 브라우저 탭이 영원히 폴링하지 않게 하세요.
오류 시 천천히 재시도
429 또는 일시적인 네트워크 오류가 오면 다음 요청 전 더 오래 기다리세요. 401 또는 402는 API Key나 크레딧을 확인하도록 안내하세요.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function waitForHappyHorseVideo(taskId) {
const deadline = Date.now() + 15 * 60 * 1000;
let delayMs = 8000;
while (Date.now() < deadline) {
const res = await fetch(
`${BASE_URL}/api/status?task_id=${encodeURIComponent(taskId)}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
if (res.status === 429) {
await sleep(Math.min(delayMs * 2, 30000));
continue;
}
const payload = await res.json();
if (!res.ok) {
throw new Error(payload.message || `Status request failed: ${res.status}`);
}
const task = payload.data;
if (task.status === "SUCCESS") {
return task.response?.resultUrls?.[0];
}
if (task.status === "FAILED") {
throw new Error(task.error_message || "Generation failed");
}
await sleep(delayMs);
delayMs = Math.min(delayMs + 2000, 20000);
}
throw new Error("Timed out. Keep the task_id and check again later.");
}API 플레이그라운드
브라우저에서 바로 API를 테스트하세요. YOUR_API_KEY를 실제 키로 바꾸세요.
오류 코드
| HTTP 상태 | 코드 | 설명 |
|---|---|---|
| 400 잘못된 요청 | INVALID_PROMPT | 프롬프트가 잘못되었거나 비어 있습니다 |
| 400 잘못된 요청 | INVALID_DURATION | 지원 범위를 벗어난 길이(3~15초) |
| 400 잘못된 요청 | INVALID_MODEL | 모델은 'happyhorse-1.0/video'여야 합니다 |
| 401 인증되지 않음 | INVALID_API_KEY | API 키가 없거나 잘못되었습니다 |
| 402 결제 필요 | INSUFFICIENT_CREDITS | 이 작업에 크레딧이 부족합니다 |
| 429 요청 과다 | RATE_LIMITED | 요청이 너무 많습니다. 잠시 후 다시 시도하세요 |
| 500 내부 서버 오류 | INTERNAL_ERROR | 서버 오류입니다. 나중에 다시 시도하세요 |