개발자 API는 현재 베타 단계이며 언제든 변경될 수 있습니다. 현 단계에서는 개인 테스트와 체험에 더 적합하며, 프로덕션 환경에서의 사용은 아직 권장하지 않습니다.
현재 배포에서 활성화된 기능 59개를 REST로 호출하거나 MCP 호환 AI 도구에서 바로 사용할 수 있습니다. 활성 구독이 필요합니다.
Codex MCP, REST, Claude Code, Cursor 및 수동 MCP 클라이언트는 전용 API 키를 사용합니다. Codex는 정적 Authorization 헤더를 사용자 구성에 저장합니다. 키를 채팅이나 셸 기록으로 보내지 마세요.
모든 요청은 구독 계정에 연결된 API 키로 인증됩니다.
Authorization: Bearer YOUR_API_KEY구독이 만료되면 403이 반환되고 갱신 후 기존 Key를 다시 사용할 수 있습니다. VidMage에 한 번 로그인하여 해결되는 401은 ACCOUNT_SESSION_REFRESH_REQUIRED뿐입니다. 다른 401은 각 복구 절차를 따르세요.
유효 시간이 짧고 크기가 고정된 URL을 사용해 로컬 이미지, 동영상 또는 오디오를 스토리지에 직접 업로드합니다. 파일 바이트는 VidMage 애플리케이션 서버를 거치지 않습니다.
curl -X POST "https://vidmage.ai/api/v1/files/upload" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "capability": "video-upscaler", "parameter": "videoURL", "duration": 7.25, "fileName": "input.mp4", "localPath": "./input.mp4", "contentType": "video/mp4", "fileSize": 12345678 }'
# -> { "uploadCommand": "curl ...", "fileUrl": "https://..." }
# Run uploadCommand once, then use fileUrl in the generation request.# ~/.codex/config.toml
# Direct, persistent user-level MCP registration; this is not a plugin install.
# Replace any existing [mcp_servers.vidmage] table; do not append a duplicate.
[mcp_servers.vidmage]
url = "https://vidmage.ai/api/mcp"
http_headers = { Authorization = "Bearer YOUR_API_KEY" }
enabled = true
required = true
startup_timeout_sec = 30
tool_timeout_sec = 120
# Save this file, then confirm persistence with: codex mcp get vidmage
# Restrict the user-level file after saving: chmod 600 ~/.codex/config.toml
# Diagnose this direct server from VidMage startup errors; a remote Plugins catalog 401 is unrelated.
# Fully restart Codex, create a new task, and call list_capabilities.먼저 list_capabilities을 호출하세요. 생성 시 새롭고 안정적인 idempotencyKey를 사용하고 submit_task는 정확히 한 번만 호출한 다음 동일한 taskId를 폴링하세요. 응답을 잃었다면 먼저 get_recent_tasks를 호출하고, 동일한 제출의 전송 재시도에만 원래 키를 재사용하세요.
list_models → estimate_model_credits모든 요청은 구독 계정에 연결된 API 키로 인증됩니다.
list_capabilities (텍스트 이미지 생성)
→ describe_capability
→ submit_task + 새롭고 안정적인 idempotencyKey (한 번만)
→ get_task_result (동일 작업 폴링)
→ get_recent_tasks (제출 응답을 잃은 경우에만)
→ 네이티브 이미지 결과모든 AI 작업은 비동기로 처리됩니다. 각 기능에는 두 가지 엔드포인트가 있습니다.
| 엔드포인트 | 설명 |
|---|---|
| GET /api/v1/capabilities | 모든 요청은 구독 계정에 연결된 API 키로 인증됩니다. |
| GET /api/v1/openapi.json | 모든 요청은 구독 계정에 연결된 API 키로 인증됩니다. |
| POST /api/v1/files/upload | 로컬 미디어 파일을 위한 제한된 임시 직접 업로드 URL을 만듭니다. |
| GET /api/v1/tasks/recent | 시간 초과, 연결 끊김 또는 응답 손실 후 최근 작업 ID를 복구합니다. |
| POST /api/v1/<capability>/submit | 작업을 시작하고 작업 ID를 즉시 반환합니다. |
| POST /api/v1/<capability>/query | ID로 작업 상태를 확인하고 완료 시 결과 URL을 반환합니다. |
curl -X POST "https://vidmage.ai/api/v1/face-swap/submit" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"targetImageUrl":"https://vidmage.ai/assets/images/samples/blue-eyed-woman-sunlight.webp","referenceFaceImageUrl":"https://vidmage.ai/assets/images/samples/smiling-man-sweater.webp"}'
# -> { "success": true, "taskId": "...", "creditsRequired": ..., "creditsConsumed": 0, "usageDeferred": true }curl -X POST "https://vidmage.ai/api/v1/face-swap/query" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "taskId": "TASK_ID_FROM_SUBMIT" }'
# -> { "success": true, "data": { "status": "...", "imageUrl": "https://..." } }기능 카탈로그와 OpenAPI 3.1 문서는 실제 요청 검증에 사용되는 동일한 계약에서 생성됩니다. Postman, Insomnia, Bruno 또는 API 클라이언트 생성기에 가져올 수 있습니다.
curl -H "Authorization: Bearer YOUR_API_KEY" "https://vidmage.ai/api/v1/capabilities"curl -H "Authorization: Bearer YOUR_API_KEY" "https://vidmage.ai/api/v1/openapi.json" --output vidmage-openapi.jsoncurl -H "Authorization: Bearer YOUR_API_KEY" "https://vidmage.ai/api/v1/tasks/recent?limit=10"아래 예제는 작업을 한 번만 제출하고 완료될 때까지 동일한 작업 ID를 조회합니다. 같은 제출을 재시도할 때는 idempotency key를 변경하지 마세요.
const submitResponse = await fetch('https://vidmage.ai/api/v1/face-swap/submit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDMAGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"targetImageUrl": "https://vidmage.ai/assets/images/samples/blue-eyed-woman-sunlight.webp",
"referenceFaceImageUrl": "https://vidmage.ai/assets/images/samples/smiling-man-sweater.webp"
}),
})
const submitted = await submitResponse.json()
if (!submitResponse.ok || !submitted.success) {
throw new Error(submitted.message ?? submitted.error ?? 'Task submission failed')
}
const taskId = submitted["taskId"]
if (!taskId) throw new Error('Submit succeeded without a task id')
while (true) {
await new Promise(resolve => setTimeout(resolve, 5000))
const queryResponse = await fetch('https://vidmage.ai/api/v1/face-swap/query', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDMAGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ taskId: taskId }),
})
const queried = await queryResponse.json()
if (!queryResponse.ok || !queried.success) {
throw new Error(queried.message ?? queried.error ?? 'Task query failed')
}
const data = queried.data ?? queried
const status = String(data.status ?? '').toLowerCase()
if (['success', 'succeeded', 'completed'].includes(status)) {
console.log(queried.result ?? queried["imageUrl"] ?? data["imageUrl"])
break
}
if (['failed', 'error'].includes(status)) {
throw new Error(data.errorDetail ?? data.error ?? 'Task failed')
}
}import os
import time
import requests
submit_response = requests.post(
"https://vidmage.ai/api/v1/face-swap/submit",
headers={
"Authorization": f"Bearer {os.environ['VIDMAGE_API_KEY']}",
},
json={
"targetImageUrl": "https://vidmage.ai/assets/images/samples/blue-eyed-woman-sunlight.webp",
"referenceFaceImageUrl": "https://vidmage.ai/assets/images/samples/smiling-man-sweater.webp",
},
timeout=60,
)
submitted = submit_response.json()
if not submit_response.ok or not submitted.get("success"):
raise RuntimeError(submitted.get("message") or submitted.get("error") or "Task submission failed")
task_id = submitted["taskId"]
if not task_id:
raise RuntimeError("Submit succeeded without a task id")
while True:
time.sleep(5)
query_response = requests.post(
"https://vidmage.ai/api/v1/face-swap/query",
headers={"Authorization": f"Bearer {os.environ['VIDMAGE_API_KEY']}"},
json={"taskId": task_id},
timeout=60,
)
queried = query_response.json()
if not query_response.ok or not queried.get("success"):
raise RuntimeError(queried.get("message") or queried.get("error") or "Task query failed")
data = queried.get("data") or queried
status = str(data.get("status") or "").lower()
if status in {"success", "succeeded", "completed"}:
print(queried.get("result") or queried.get("imageUrl") or data.get("imageUrl"))
break
if status in {"failed", "error"}:
raise RuntimeError(data.get("errorDetail") or data.get("error") or "Task failed")HTTP 상태로 흐름을 제어하고 errorType에 따라 복구 작업을 수행하세요. 모든 REST 응답에는 추적과 지원을 위한 X-Request-Id가 포함됩니다.
| 상태 | 주요 errorType | 권장 조치 |
|---|---|---|
| 400 | INVALID_JSON / VALIDATION_ERROR | details에 표시된 필드를 수정하세요. 동일한 입력으로 재시도하지 마세요. |
| 401 | AUTHENTICATION_REQUIRED | VidMage에 자격 증명이 전달되지 않았습니다. Codex 사용자 구성 또는 대상 클라이언트에 Authorization을 추가하고, 채팅에서 Key를 요청하거나 붙여 넣지 마세요. |
| 401 | AUTHORIZATION_HEADER_INVALID | Authorization Header를 정확히 Bearer <API_KEY>로 수정하세요. 작업은 제출되지 않았습니다. |
| 401 | API_KEY_INVALID_OR_REVOKED | 새 API 키를 만들고 기존 구성의 Authorization만 교체하세요. Codex를 재시작하고 새 작업에서 확인하세요. |
| 401 | API_KEY_INVALID_CREDENTIAL | 새 API 키를 만들고 대상 클라이언트의 자격 증명을 교체하세요. 기존 자격 증명은 복호화할 수 없습니다. |
| 401 | ACCOUNT_SESSION_REFRESH_REQUIRED | VidMage에 한 번 로그인하세요. 기존 API 키에 포함된 백엔드 계정 자격 증명이 갱신되며 클라이언트 구성은 변경되지 않습니다. |
| 401 REST | NEED_API_KEY | REST 호환용으로만 사용됩니다. API 키를 제공하세요. |
| 402 | NEED_PURCHASE_CREDITS | 크레딧을 추가하거나 비용이 낮은 작업을 선택하세요. |
| 403 | NEED_SUBSCRIBE | 계정 구독을 시작하거나 갱신하세요. |
| 404 | CAPABILITY_NOT_ENABLED | 기능 목록을 다시 가져오세요. 현재 배포에서 기능이 비활성화되었거나 제공되지 않을 수 있습니다. |
| 409 | UPLOAD_NOT_READY / IDEMPOTENCY_CONFLICT / IDEMPOTENCY_IN_PROGRESS | 제출이 처리 중이면 안내된 시간만큼 기다리고 동일한 idempotencyKey를 재사용하세요. 다른 생성 요청에만 새 키를 만드세요. |
| 410 | UPLOAD_EXPIRED | 새 임시 업로드를 만드세요. 이전 파일 URL이 만료되었습니다. |
| 429 | RATE_LIMITED | Retry-After만큼 기다린 뒤 최대 지연이 설정된 지수 백오프로 재시도하세요. |
| 503 | CREDENTIAL_STORAGE_UNAVAILABLE | Retry-After를 따르고 한 번만 재시도하세요. 계속 실패하면 중단하고 requestId를 보고한 뒤 운영자에게 Developers MySQL readiness 복구를 요청하세요. API 키를 유지하고 다시 제출하지 마세요. |
| 503 / MCP | SUBMISSION_OUTCOME_UNKNOWN / BILLING_OUTCOME_UNKNOWN / REFUND_OUTCOME_UNKNOWN | 먼저 recovery를 따르세요. GET_RECENT_TASKS는 get_recent_tasks 호출, QUERY_TASK_ID_OR_CONTACT_SUPPORT는 동일한 taskId 조회 또는 지원팀 문의, CONTACT_SUPPORT_WITH_IDEMPOTENCY_KEY_AND_BUSINESS_ID는 idempotencyKey와 businessId를 포함한 지원팀 문의를 뜻합니다. 새 idempotencyKey 생성, 재제출 또는 중복 환불을 절대 하지 마세요. |
| 503 / MCP | TASK_PERSISTENCE_UNCERTAIN | taskId를 보관하고 작업을 다시 제출하지 마세요. 문제가 계속되면 taskId와 함께 지원팀에 문의하세요. |
| MCP | TASK_QUERY_INTERRUPTED | 동일한 taskId 폴링을 재개하세요. 다른 작업을 제출하지 마세요. |
| MCP | RESULT_MISSING | 동일한 taskId를 계속 폴링하고 작업을 다시 제출하지 마세요. |
| 404 / MCP | TASK_NOT_FOUND | 재시도 전에 get_recent_tasks를 호출하고 유료 작업을 다시 제출하지 마세요. |
| 502 / MCP | BILLING_INVARIANT_FAILED | 재시도, API 키 교체, 원래 Idempotency-Key 변경 또는 재제출을 하지 마세요. taskId가 있으면 해당 값, capability, 원래 Idempotency-Key를 지원팀에 전달하고 REST에서는 X-Request-Id도 함께 전달하세요. |
| 5xx | *_SERVICE_UNAVAILABLE / UPSTREAM_* | 그 밖의 5xx 오류는 제한된 지수 백오프로 재시도하고 작업 ID를 보관하세요. 이 규칙은 CREDENTIAL_STORAGE_UNAVAILABLE에는 적용되지 않습니다. |
아래 매개변수는 submit 요청의 본문입니다. query 조회에는 동일한 작업 ID 필드를 사용하세요.