튜토리얼
hiapi API로 grok-imagine-quality/image-to-image 사용하는 방법: curl, Python 및 사용 가능한 요청
이 가이드에서는 hiapi 통합 작업 API를 통해 grok-imagine-quality/image-to-image(Grok Imagine 시리즈 중 더 높은 충실도의 티어)를 사용하여 기존 이미지를 변환하는 방법을 보여줍니다. 원본 이미지와 텍스트 프롬프트를 제출하고, 결과를 폴링하여 가져온 뒤, 생성된 이미지를 다운로드합니다. 아래의 모든 요청 및 응답 구조는 실시간 API와 대조하여 검증되었습니다.
필요한 준비물
- hiapi API 키 — 대시보드에서 생성하세요.
- 원본으로 사용할 공개적으로 접근 가능한 이미지 URL 1~3개. 플랫폼이 서버 측에서 입력 미디어를 가져와 정규화하므로 로컬 파일 경로와 base64 페이로드는 사용할 수 없습니다 — 먼저 이미지를 API가 접근할 수 있는 위치에 호스팅하세요.
이게 전부입니다. SDK는 필요 없습니다. 작업 API는 일반 HTTPS + JSON입니다.
요청 모드
grok-imagine-quality/image-to-image는 비동기 작업 엔드포인트에서 실행됩니다: POST /v1/tasks로 작업을 생성한 뒤 완료될 때까지 GET /v1/tasks/<taskId>를 폴링하거나(또는 콜백을 등록하거나) 하면 됩니다.
입력 스키마는 엄격합니다 — 알 수 없는 필드는 400으로 거부됩니다:
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
prompt |
string | ✅ | 원본 이미지에 무엇을 할지 |
image_urls |
string[] | ✅ | 원본/참조 이미지의 공개 URL 1~3개 |
aspect_ratio |
string | – | 다음 중 하나: auto, 2:1, 20:9, 19.5:9, 16:9, 4:3, 3:2, 1:1, 2:3, 3:4, 9:16, 9:19.5, 9:20, 1:2 |
resolution |
string | – | 1k 또는 2k — 소문자 (1K는 400을 반환함) |
output_format |
string | – | jpeg, png 또는 webp |
없는 것에 주목하세요: size도, n도, seed도, strength나 consistency 조절 키도 없습니다. 출력이 원본 이미지를 얼마나 따르는지는 프롬프트와 전달한 참조 이미지로 제어됩니다 — 아래 FAQ를 참고하세요.
최소 동작 예제(curl)
작업 생성:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-imagine-quality/image-to-image",
"input": {
"prompt": "Turn this product photo into a clean studio shot on a light gray background with soft shadows",
"image_urls": ["https://your-cdn.example.com/source.jpg"],
"aspect_ratio": "1:1",
"resolution": "2k",
"output_format": "png"
}
}'
성공적으로 생성되면 작업 ID가 반환됩니다:
{
"code": 200,
"data": {
"taskId": "task_xxxxxxxxxxxx"
}
}
작업이 최종 상태에 도달할 때까지 폴링합니다:
curl https://api.hiapi.ai/v1/tasks/task_xxxxxxxxxxxx \
-H "Authorization: Bearer sk-<your-key>"
실행 중에는 data.status가 진행 중 상태이며, 완료되면 success로 바뀌고 이미지는 data.output에 위치합니다:
{
"code": 200,
"data": {
"taskId": "task_xxxxxxxxxxxx",
"status": "success",
"output": [
{
"url": "https://.../result.png?...&expireAt=...",
"expireAt": 1760000000
}
]
}
}
⚠️ 출력 URL은 임시입니다(expireAt 참고). 작업이 성공하면 즉시 바이트를 다운로드하여 자체 스토리지에 저장하세요 — 결과 URL을 핫링크하지 마세요.
작업이 실패하면 data.status는 fail이 되고 data.error에 code와 message가 담깁니다.
Python: 생성, 폴링, 다운로드
requests만 사용하는 완전한 스크립트:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def create_task(prompt: str, image_urls: list[str]) -> str:
payload = {
"model": "grok-imagine-quality/image-to-image",
"input": {
"prompt": prompt,
"image_urls": image_urls, # 1-3 public URLs
"aspect_ratio": "1:1",
"resolution": "2k", # lowercase: "1k" or "2k"
"output_format": "png",
},
}
r = requests.post(API_BASE, headers=HEADERS, json=payload, timeout=60)
data = r.json()
task_id = (data.get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create failed: {data}")
return task_id
def wait_task(task_id: str, timeout_s: int = 600, poll_interval: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_interval)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="Turn this product photo into a clean studio shot on a light gray background",
image_urls=["https://your-cdn.example.com/source.jpg"],
)
print("task:", task_id)
task = wait_task(task_id)
url = task["output"][0]["url"]
# The output URL expires -- download immediately and persist yourself
img = requests.get(url, timeout=120).content
with open("result.png", "wb") as f:
f.write(img)
print(f"saved result.png ({len(img)} bytes)")
프로덕션 환경 고려 사항
폴링 대신 콜백 사용
일회성 스크립트를 넘어서는 모든 경우에는 콜백을 등록하고 폴링 루프를 건너뛰세요. 최상위 callback 객체를 추가합니다(model, input과 동일한 레벨):
{
"model": "grok-imagine-quality/image-to-image",
"input": { "...": "..." },
"callback": {
"url": "https://your-app.example.com/hooks/hiapi",
"when": "final"
}
}
when은 "final"만 지원합니다 — 작업이 최종 상태(success 또는 fail)에 도달하면 정확히 한 번의 POST를 받게 됩니다. 경험칙:
- 폴링은 프로세스가 어차피 살아 있는 CLI, 노트북, 배치 작업에 적합합니다. 3~5초마다 폴링하세요. 1초 미만 간격으로 몰아치지 마세요.
- 콜백은 웹 백엔드에 더 적합합니다: 대기 중인 연결도 없고, 생성 중에 작업 스레드가 묶여 있지도 않습니다. 웹훅 본문을 맹신하지 말고 서버 측에서
GET /v1/tasks/<taskId>를 다시 호출해 페이로드를 검증하세요.
멱등성
작업 생성 자체는 멱등하지 않습니다 — 프로세스가 POST /v1/tasks 이후, taskId를 영속화하기 전에 크래시하면 재시도 시 두 번째 작업이 생성(및 과금)됩니다. 기다리기를 시작하기 전에 taskId를 내부 작업 ID를 키로 하여 자체 스토리지에 영속화하고, 재시작 시 재생성하지 말고 저장된 taskId를 폴링하여 복구하세요.
오류 처리
실제로 마주치게 될 오류들:
401permission_denied— API 키가 유효하지 않거나 이 모델에 대한 접근 권한이 없습니다. 응답 본문에는 지원팀에 보낼 수 있는request_id가 포함됩니다:{ "error": { "code": "permission_denied", "message": "This API key cannot use the selected model. ...", "request_id": "2026...", "type": "hiapi_error" } }400INVALID_REQUEST— 스키마 위반이며 정확한 메시지가 함께 제공됩니다. 이 모델의 실제 예시:prompt: missing required field "prompt"— 필수 필드를 빠뜨렸습니다.image_urls: maxItems: got 12, want 3— 참조 이미지가 너무 많습니다(최대 3개).resolution: value must be one of '1k', '2k'—1K/4K를 보냈습니다.additional properties 'seed' not allowed— 이 모델이 허용하지 않는 필드를 전달했습니다.
최종
fail상태 — 작업은 접수되었지만 생성이 실패했습니다(예: 원본 URL을 가져올 수 없음).data.error.message를 확인하고 입력을 수정한 뒤 새 작업을 생성하세요.
5xx 및 네트워크 오류에는 백오프 재시도를 사용하고, 400은 재시도하지 마세요 — 페이로드를 수정하기 전에는 동일하게 실패합니다.
품질 티어 선택(그리고 '일관성'은 어떻게 되나요?)
hiapi의 Grok Imagine 시리즈는 티어와 모달리티에 따라 별도의 모델 ID로 나뉩니다. 이미지 대 이미지의 경우 다음을 선택할 수 있습니다:
grok-imagine-quality/image-to-image— 이 문서에서 다루는 고충실도 티어; 더 느리지만 디테일 보존이 더 좋습니다.grok-imagine/image-to-image— 표준 티어; 요청 스키마는 동일하며 이미지당 더 빠르고 저렴합니다.
티어가 곧 모델 ID입니다 — input 내부에 quality 파라미터는 없습니다(보내면 400 additional properties 'quality' not allowed가 반환됨). 두 티어의 이미지당 가격은 가격 페이지에서 확인하세요.
관련 문서
- grok-imagine-quality/image-to-image 모델 페이지 — 플레이그라운드 및 가격
- grok-imagine/text-to-image 사용 방법 — 먼저 원본 이미지를 처음부터 생성하기
- grok-imagine/image-to-video 사용 방법 — 결과에 움직임 더하기
- hiapi 문서 — 인증, 작업 API 및 플랫폼의 나머지 부분
자주 묻는 질문
일관성이나 강도 파라미터가 있나요?
없습니다. 입력 스키마는 prompt, image_urls, aspect_ratio, resolution, output_format만 허용하며, 그 외의 것은 400으로 거부됩니다. 출력이 원본 이미지를 얼마나 따를지 제어하려면 프롬프트에 반드시 유지해야 할 내용을 명확히 명시하고("제품과 라벨은 동일하게 유지하고 배경만 변경"), image_urls로 최대 3개의 참조 이미지를 전달하세요.
로컬 파일을 업로드하거나 base64를 보낼 수 있나요?
직접은 안 됩니다 — image_urls는 URL을 받고 플랫폼이 서버 측에서 가져옵니다. 파일을 공개적으로 접근 가능한 스토리지(S3, R2, CDN)에 업로드하고 해당 URL을 전달하세요.
원본 이미지를 몇 개까지 전달할 수 있나요?
1~3개입니다. 빈 배열은 minItems: got 0, want 1로 실패하고, 3개를 초과하면 maxItems로 실패합니다.
어떤 해상도와 종횡비가 지원되나요?
resolution은 1k 또는 2k입니다(소문자만). aspect_ratio는 2:1부터 1:2까지 14개 값을 지원하며, auto, 16:9, 1:1, 9:16 및 모바일에 적합한 9:19.5/9:20이 포함됩니다.
출력 URL은 얼마나 유효한가요?
각 출력에는 expireAt 타임스탬프가 있습니다. 결과를 일시적인 것으로 간주하세요: 작업이 성공하면 즉시 바이트를 다운로드하여 직접 저장하세요.
여러 변형을 생성하려면 어떻게 하나요?
n 파라미터는 없습니다 — 변형마다 작업을 하나씩 생성하세요. 작업은 독립적으로 실행되므로 여러 개를 병렬로 제출할 수 있습니다.
키가 올바른데 401 permission_denied는 무슨 뜻인가요?
키는 존재하지만 이 모델을 사용할 수 없습니다(요금제 또는 권한 범위). 대시보드에서 키의 모델 권한을 확인하거나, 오류 응답 본문의 request_id를 사용해 지원팀에 문의하세요.
관련 글
모든 아티클 보기 →-
튜토리얼
HiAPI API로 hailuo-2.3-fast/image-to-video 호출하는 방법: curl과 Python 실전
빠르고 저렴한 이미지-투-비디오 등급의 첫 실행 요청 — 모델 ID부터 MP4 다운로드까지
-
튜토리얼
HiAPI API로 hailuo-2.3/text-to-video를 호출하는 방법: curl, Python 및 실행 가능한 요청 예시
-
튜토리얼
HiAPI에서 Kandinsky 6.0 Pro 텍스트-투-비디오 사용하기: curl 및 Python 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드