cURL · 고스트 마네킹 API
고스트 마네킹 API cURL 사용
한 줄 요약
PHOTTA_API_KEY를 환경변수로 export하고, 문서에 명시된 JSON 본문과 함께 https://api.photta.app/api/v1/api/v1/ghost-mannequin 로 POST 요청을 보내 generation ID를 확보한 뒤, data.status가 completed가 될 때까지 3초마다 /api/v1/ghost-mannequin/{id} 로 GET 요청 루프를 실행하세요. jq와 함께 사용해 출력 URL을 추출할 수 있습니다.
- 일반적인 소요 시간: 1.5–4 min
- 크레딧: 2K에서 4 크레딧 · 4K에서 5 크레딧
- 처리 방식: 비동기, 폴링
- 제한 사항: 600 requests/min
- 인증: Bearer 키
이 페이지의 모든 수치는 다음 출처를 기반으로 합니다: Photta API 문서 · 확인 완료
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/ghost-mannequin", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}),
});
const { data } = await res.json(); // data.id, data.status
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/ghost-mannequin/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } });
const { data } = await res.json();
if (data.status === "completed") return data.output_url;
if (data.status === "failed") throw new Error(data.error_message ?? "generation failed");
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error("timed out after 6 minutes");
}import os, requests
res = requests.post(
"https://api.photta.app/api/v1/ghost-mannequin",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/ghost-mannequin/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")한눈에 보기
한눈에 보기
- 엔드포인트
- POST /api/v1/ghost-mannequin
- 인증
- Bearer API 키
- 처리 방식
- 비동기 — 상태 엔드포인트 폴링
- 일반적인 소요 시간
- 1.5–4 min
- 크레딧
- 2K에서 4 크레딧 · 4K에서 5 크레딧
- 화면비
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- 입력 제한
- 이미지당 최대 10 MB; JPEG, PNG, WebP
- 멱등성
- 아니요
동작 원리
curl과 jq 외에 다른 의존성이 전혀 없는 5단계 셸 프로세스.
단계 1
가입 및 키 발급
ai.photta.app으로 이동하여 Developers 탭을 열고, Generate API key를 클릭하세요. 프로덕션 키는 `photta_live_`로 시작합니다.
단계 2
키 export
이후의 모든 curl 호출이 키를 자동으로 참조할 수 있도록 셸 프로필이나 `.envrc` 파일에 `export PHOTTA_API_KEY="photta_live_xxx"`를 추가하세요.
curl --version # macOS, Linux, WSL and Windows 10+ ship it export PHOTTA_API_KEY="photta_live_xxxxx"단계 3
기본 URL 고정
`export PHOTTA_BASE_URL="https://api.photta.app/api/v1"`을 설정해 curl 명령어를 간결하게 유지하세요.
export PHOTTA_BASE_URL="https://api.photta.app/api/v1" export AUTH_HEADER="Authorization: Bearer $PHOTTA_API_KEY"단계 4
제출 및 폴링
`$PHOTTA_BASE_URL/api/v1/ghost-mannequin`로 POST 요청을 보내 ID를 받은 다음, 3초마다 `curl $PHOTTA_BASE_URL/api/v1/ghost-mannequin/{id}`를 반복 실행합니다. 응답을 jq로 파이프하여 `.data.status`를 깔끔하게 추출하세요.
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \ -H "Authorization: Bearer $PHOTTA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg", "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg", "image_side": "front", "angle": "side", "style": "3d", "background_color": "white", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "closed front, cream interior lining", "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67" }') ID=$(echo "$RESPONSE" | jq -r '.data.id') # $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed". for i in $(seq 1 120); do RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY") STATUS=$(echo "$RESULT" | jq -r '.data.status') [ "$STATUS" = "completed" ] && break [ "$STATUS" = "failed" ] && echo "generation failed" && exit 1 sleep 3 done echo "$RESULT" | jq -r '.data.output_url'단계 5
결과 저장
작업이 완료되면 jq로 `.data.output_url`을 추출하고 `curl -o`를 사용해 바이트 데이터를 로컬 스토리지로 저장하세요. 다음 파이프라인 단계를 진행할 준비가 끝납니다.
오류
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
case "$STATUS_CODE" in
402) echo "insufficient_credits_error — top up before retrying" ;;
429) echo "rate_limit_error — wait the Retry-After seconds (30 by default)" ;;
4??) echo "$BODY" | jq '.error.type, .error.message' ;;
5??) echo "api_error — retry with backoff" ;;
esac제한 사항
- API 키당 분당 600회 요청 (고정 윈도우 방식이며, 제한은 모든 요금제에서 동일합니다)
- 429 응답에는 Retry-After: 30초 헤더가 포함됩니다
- 이미지당 최대 10 MB
- 지원 형식: JPEG, PNG, WebP
- 요금제별 동시 배치 수: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- 폴링 전용 — API는 웹훅을 전송하지 않습니다.
cURL이 여전히 API를 검증하는 가장 빠른 방법인 이유
- 설치 불필요 — cURL은 모든 주요 OS에 기본 내장되어 있습니다
- jq와 결합하여 스크립트 기반 파이프라인(CI, cron, 셸 훅) 구성 가능
- 코드로 연동하기 전에 엔드포인트를 스모크 테스트하는 가장 빠른 방법
- 이 페이지의 모든 명령어는 POSIX 셸에 바로 붙여넣어 실행할 수 있습니다
지원하지 않는 작업
- 폴링 루프가 터미널을 차단하므로, 병렬 워커가 필요하다면 Node나 Python으로 전환하세요
- 완료 신호는 폴링이 유일하며, API는 웹훅을 전송하지 않습니다
- Windows 명령 프롬프트 사용자는 WSL 또는 PowerShell의 curl.exe를 실행해야 합니다
개발자가 자주 묻는 질문
Photta CLI 도구가 있나요?
아직은 없습니다. 하지만 cURL과 15줄짜리 bash 래퍼만으로도 대부분의 작업을 처리할 수 있습니다. 모든 언어에서 서브프로세스를 실행할 수 있고 셸이 CI 파이프라인의 공통분모이기 때문에, 문서에서는 cURL 중심의 예제를 우선시합니다.
API를 사용하려면 jq가 필수인가요?
반드시 그렇지는 않지만, 스크립트 기반 파이프라인에서는 사용하는 편이 훨씬 수월합니다. jq를 사용하면 JSON 응답을 직접 파싱하지 않고도 `.data.id`, `.data.status`, `.data.output_url`을 바로 추출할 수 있습니다. macOS에서는 `brew install jq`로, Debian/Ubuntu에서는 `apt install jq`로 설치하세요.
curl에서 인증은 어떻게 하나요?
모든 요청에 `-H "Authorization: Bearer $PHOTTA_API_KEY"`를 추가하세요. 키는 환경 변수에 보관하고, 커밋 대상 스크립트에 인라인으로 하드코딩하지 마세요. `curl --oauth2-bearer`도 작동하지만, 문서와 로그상으로는 명시적인 헤더 형식이 더 명확합니다.
프로덕션 환경에서 curl 기반 스크립트를 사용해도 되나요?
일회성 배치 백필이나 cron 작업의 경우 가능합니다. 실제로 수천 개의 팀이 이 방식으로 카탈로그 백필을 처리합니다. 다만 장기 실행 애플리케이션의 경우 적절한 에러 처리, 재시도, 관측성을 확보할 수 있는 정식 프로그래밍 언어를 사용하는 것이 좋습니다. 요청 형태가 동일하므로 Node나 Python으로 포팅하더라도 이 페이지의 curl 예제는 그대로 유효합니다.
bash 루프에서 폴링은 어떻게 구현하나요?
루프 본문에서 상태를 확인하도록 `for i in $(seq 1 120); do … ; sleep 3; done` 형태를 사용하세요. `.data.status`가 `completed` 또는 `failed`가 되면 루프를 빠져나옵니다. 이 페이지의 코드 샘플은 멈춘 작업으로 인해 스크립트가 무한 대기하지 않도록 엄격한 상한선을 둔 정확한 패턴을 보여줍니다.
curl에서 에러 응답은 어떻게 확인하나요?
`curl -w "\n%{http_code}"`를 사용하여 JSON 본문과 함께 HTTP 상태 코드를 캡처하세요. 상태 코드에 따라 분기 처리합니다. 크레딧 부족은 402, rate limit은 429(Retry-After 값을 준수), 일시적인 서버 오류는 5xx입니다. 에러 본문에는 항상 `error.code` 및 `error.message` 필드가 포함됩니다.
관련 페이지
Node.js
Node.js 환경의 고스트 마네킹 API
네이티브 fetch를 사용하여 Node.js 백엔드에서 Photta의 고스트 마네킹 API 기능을 호출하세요. SDK는 필요 없습니다: 키를 저장하고 작업을 제출한 뒤 결과를 폴링하면 됩니다.
읽기Python
Python 환경의 고스트 마네킹 API
requests 라이브러리를 사용하여 Python에서 Photta의 고스트 마네킹 API를 호출하세요. 30줄짜리 래퍼이자 httpx를 통한 비동기 지원이 가능하며, Django, FastAPI, Celery에서 원활하게 동작합니다.
읽기기능
고스트 마네킹 API 투명 마네킹 제품 사진용
AI 고스트 마네킹 엔드포인트. 의류 사진에서 마네킹을 제거하고 내부 디테일을 보존합니다. 3D 또는 플랫레이, 배치 처리 지원, 2K 기준 4 credits.
읽기빌드
카탈로그용 고스트 마네킹 추출 자동화
야간 카탈로그 자동화 레시피: 어제의 상품 업데이트 추출, Photta 고스트 마네킹 API로 배치 제출, 상위 배치 폴링, 데이터베이스에 영구 저장.
읽기빠른 시작
5분 안에 첫 번째 Photta 이미지를 생성하세요.
회원가입, API 키 생성, 첫 cURL 호출 실행, 완료될 때까지 폴링, 결과 저장까지. 엔드투엔드로 문서화된 5단계 가이드입니다.
읽기레퍼런스
Photta API 가격 정책
2K 및 4K에서 각 Photta API endpoint에 소요되는 크레딧 비용, 과금 및 환불 방식, 그리고 무료 endpoint 목록입니다. 이미지당 별도의 현금 가격은 없습니다.
읽기
이 페이지의 모든 수치는 다음 출처를 기반으로 합니다: Photta API 문서 · 확인 완료
5분 만에 API 체험하기
Photta API 키를 발급받고 위 cURL 스니펫을 붙여넣기만 하면, 커피가 다 내려지기도 전에 첫 번째 모델 착용 컷을 받아볼 수 있습니다.
- 1.5–4 min
- 2K에서 4 크레딧 · 4K에서 5 크레딧
- 비동기, 폴링
- 600 requests/min
- Bearer 키