튜토리얼
HiAPI API로 imagen4-ultra를 사용하는 방법: curl 및 Python 예제
HiAPI에서 고품질 텍스트-이미지 생성을 위한 완전한 요청 실습
HiAPI의 imagen4-ultra가 제공하는 것
imagen4-ultra는 HiAPI의 고품질 텍스트-이미지 모델입니다. 프롬프트를 보내면 생성된 이미지를 받을 수 있습니다. 개발자에게 실용적인 이유는 플랫폼의 다른 모든 모델과 마찬가지로 통일된 HiAPI 인터페이스 뒤에서 동작하기 때문에, 여기서 배운 인증 방식, 요청 구조, 작업 처리 패턴을 다른 엔드포인트에도 그대로 적용할 수 있다는 점입니다.
이 튜토리얼은 파라미터 나열이 아닌 실행 가능한 실습입니다. 읽고 나면 다음을 갖추게 됩니다:
- 텍스트-이미지 작업을 제출하는 데 바로 복사해 붙일 수 있는
curl요청, - 같은 요청을 변환한 소형 Python 클라이언트,
- 가로세로 비율과 기타 옵션이 출력에 어떻게 영향을 미치는지에 대한 명확한 이해,
- 그리고 작업 완료를 기다렸다가 이미지를 디스크에 저장하는 폴링 루프.
먼저 기대치를 정리하겠습니다: 이미지 생성은 즉시 이루어지지 않습니다. imagen4-ultra는 비동기로 동작합니다. 작업을 제출하고 작업 식별자를 받은 다음, 렌더링이 완료될 때까지 폴링합니다. HiAPI의 다른 비동기 엔드포인트를 사용해 봤다면 이 흐름이 익숙할 것입니다. 아니라면 폴링 섹션에서 전체 생명 주기를 다룹니다.
우리는 HiAPI 자체 API 범위 안에 머무릅니다: 벤더별 SDK도, 서드파티 콘솔도 사용하지 않습니다. 하나의 기본 URL, 하나의 키, 하나의 요청 형식입니다.
첫 요청을 보내기 전에
첫 호출이 성공하려면 세 가지가 필요합니다.
1. API 키
HiAPI 계정 콘솔에서 키를 생성하세요. 비밀번호처럼 취급하세요: 소스 파일에 직접 붙이지 말고 환경 변수에 저장하세요.
export HIAPI_API_KEY="your-key-here"
2. 기본 URL
모든 HiAPI 요청은 플랫폼 문서에 기록된 동일한 API 호스트로 전송됩니다. 코드에서는 한 곳에 모아 두어 여러 위치에 하드코딩하지 않도록 하세요:
export HIAPI_BASE_URL="https://api.hiapi.ai"
계정이나 리전이 다른 호스트를 사용한다면 콘솔에 표시된 값을 사용하세요. 아래 요청 경로는 동일하게 유지됩니다.
3. 인증 정보 전달 방식
HiAPI는 Authorization 헤더의 bearer 토큰을 사용합니다. 모든 요청(제출이든 폴링이든)은 동일한 두 헤더를 포함합니다:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
인증은 이게 전부입니다. 요청 서명 단계도, 호출마다 토큰을 교환하는 절차도 없습니다. 헤더를 설정할 수 있으면 이 API를 호출할 수 있습니다.
계속하기 전에 기본 확인을 하세요: curl을 실행할 동일한 셸 세션에서 키를 export했는지 확인하세요. 상당한 비율의 "401 Unauthorized" 보고는 결국 한 터미널 탭에서 키를 export하고 다른 탭에서 사용한 경우로 귀결됩니다.
아래에서는 모델 식별자를 imagen4-ultra로 가정합니다. 계정에 노출된 정확한 문자열을 확인하려면 문서의 모델 목록을 참고하세요.
실행 가능한 curl 요청
다음은 완전한 제출 요청입니다. 프롬프트를 보내고 출력 가로세로 비율을 설정하며 단일 이미지를 요청합니다.
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1
}'
요청 본문을 필드별로 설명합니다:
model—— 호출 중인 모델 식별자입니다. 요청 라우팅을 결정하며, 이것이 없으면 API는 어떤 모델을 실행할지 알 수 없습니다.prompt—— 이미지에 대한 자연어 설명입니다. 출력 품질에 가장 큰 영향을 미치는 요소입니다. 피사체, 조명, 스타일, 구도에 대해 구체적으로 작성하세요. 모호한 프롬프트는 모호한 이미지만 만들어냅니다.aspect_ratio—— 출력 캔버스의 형태로, 너비:높이로 표현됩니다. 뒤에서 자세히 설명합니다.n—— 이번 제출로 생성할 이미지 수입니다. 테스트 중에는1로 유지하여 매 실행 비용을 쉽게 예측할 수 있게 하세요.
엔드포인트 구성에 따라 응답에는 완료된 이미지가 포함되거나, 이런 모델에서 더 흔하게는 식별자와 상태 필드가 있는 작업 객체가 포함됩니다. 해당 식별자를 캡처하세요. 폴링 섹션이 이에 의존합니다.
# 제출 응답의 전형적 구조
{
"id": "job_abc123",
"status": "queued"
}
응답을 JSON 포매터로 처리하세요(있으면 | jq .). 그러면 한 줄을 눈을 찡그려 보지 않고도 계정의 응답과 대조하여 필드 이름을 이해할 수 있습니다.
같은 요청을 Python으로 작성하기
Python 버전은 줄 단위 대응 번역입니다. 같은 URL, 같은 헤더, 같은 요청 본문입니다. requests를 사용하면 매핑이 명확해집니다:
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai")
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "imagen4-ultra",
"prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
"aspect_ratio": "16:9",
"n": 1,
}
response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers=headers,
json=payload,
timeout=30,
)
response.raise_for_status()
job = response.json()
print(job["id"], job["status"])
이 코드를 실제 서비스로 옮길 때 유지할 가치가 있는 몇 가지 사항:
- 키를 환경 변수에서 읽으세요, 파일의 리터럴에서 절대 읽지 마세요.
os.environ[...]형태는 변수가 없으면 명확하게 오류를 발생시키는데, 이것이 바로 원하는 동작입니다. - 제출 호출에 명시적 타임아웃을 설정하세요. 작업 자체는 비동기로 실행되므로 HTTP 요청은 빠르게 반환되어야 합니다. 30초 상한은 프로그램이 멈추는 대신 네트워크 문제를 잡아냅니다.
- JSON을 건드리기 전에
raise_for_status()를 호출하세요. 4xx 응답의 본문은 기대하는 구조가 아니며, 세 줄 뒤에KeyError가 발생하는 것보다 미리 실패하는 편이 더 명확한 트레이스백을 제공합니다. requests.Session을 재사용하세요. 많은 작업을 제출한다면 연결 풀링이 보기보다 중요합니다.
httpx나 aiohttp를 선호한다면 변환은 기계적입니다. 같은 headers 딕셔너리, 같은 JSON 요청 본문, 같은 경로입니다. 요청 자체는 HTTP 라이브러리와 무관합니다.
가로세로 비율과 요청 옵션
가로세로 비율은 구도와 다운스트림 레이아웃에서 사용할 수 있는 출력 크기를 동시에 바꾸기 때문에 가장 자주 조정하는 옵션입니다.
가로세로 비율은 요청 본문에서 "width:height" 문자열 형식으로 전달합니다. "1:1", "16:9", "9:16", "4:3", "3:2" 등입니다. 이미지가 최종적으로 사용될 용도에 맞는 비율을 선택하세요:
1:1—— 아바타, 상품 타일, 정사각형으로 잘리는 소셜 게시물.16:9/9:16—— 히어로 배너, 동영상 썸네일, 세로형 스토리 형식의 광고 지면.4:3/3:2—— 클래식 사진 구도, 갤러리 레이아웃.
먼저 정사각형으로 생성한 뒤 자르지 말고, 비율을 의도적으로 설정하세요. 자르면 이미 비용을 지불해 생성한 픽셀을 버리게 되고, 피사체가 화면 밖으로 잘려 나갈 수도 있습니다. 최종 지면을 안다면 요청에 반영하세요.
가로세로 비율 외에 일상적으로 중요한 옵션은 다음과 같습니다:
prompt—— 여전히 가장 영향력이 큰 입력입니다. 다른 어디서든 반복하기 전에 여기서 먼저 반복하세요.n—— 제출당 생성할 이미지 수입니다. 여러 변형 중에서 고르고 싶을 때 유용하며, 프롬프트 탐색 단계에서는 낮게 유지하세요.model—— 모델 변형의 정확한 식별자입니다. 계정에 여러 이미지 모델이 노출되어 있다면 이 값이 이들 간의 전환 스위치입니다.
이 엔드포인트 문서에 기록된 파라미터를 고수하고 이름을 추측하지 마세요. 알 수 없는 필드는 400 응답의 흔한 원인이며, 오타가 난 옵션은 큰 요청 본문에서 쉽게 간과됩니다. 확신이 없으면 최소 요청 본문(model, prompt, aspect_ratio)부터 보내 동작을 확인하고, 그다음 옵션을 하나씩 추가하세요.
비동기 작업 폴링 및 결과 다운로드
이미지 생성에는 시간이 걸리므로 제출 호출은 이미지가 아닌 작업을 반환합니다. 생명 주기는 제출 → 상태 폴링 → 출력 다운로드입니다.
1단계: 제출 및 작업 ID 캡처
앞의 요청을 재사용하여 응답에서 id를 가져옵니다:
job = response.json()
job_id = job["id"]
2단계: 작업이 종료 상태에 도달할 때까지 폴링
같은 인증 헤더로 상태 엔드포인트를 폴링하고 시도 사이에 대기합니다. API에 과도한 부담을 주지 않도록 점진적으로 백오프하세요:
import time
def wait_for_job(job_id, headers, base_url, timeout=300):
deadline = time.time() + timeout
delay = 2
while time.time() < deadline:
r = requests.get(
f"{base_url}/v1/images/generations/{job_id}",
headers=headers,
timeout=30,
)
r.raise_for_status()
data = r.json()
status = data["status"]
if status == "succeeded":
return data
if status == "failed":
raise RuntimeError(f"job failed: {data}")
time.sleep(delay)
delay = min(delay * 2, 15)
raise TimeoutError(f"job {job_id} not finished within {timeout}s")
핵심 세부 사항: 하드 마감 시간, 백오프 간격에 상한 설정, 그리고 실패 상태에 대한 명시적 분기로 문제가 있는 작업이 계속 멈추지 않고 예외로 드러나게 하는 것입니다.
3단계: 이미지 다운로드
완료된 작업 응답에는 출력 위치(URL 또는 동등한 아티팩트 참조)가 포함됩니다. 이를 가져와 바이트를 디스크에 씁니다:
result = wait_for_job(job_id, headers, BASE_URL)
image_url = result["output"][0]["url"]
img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("lighthouse.png", "wb") as f:
f.write(img.content)
대부분의 프로덕션 사고를 피하는 두 가지 습관: 항상 바이트 모드("wb")로 쓰고, 텍스트 모드는 절대 사용하지 마세요. 그리고 다운로드 URL은 일시적인 것으로 취급하세요. 링크가 무기한 유효하다고 기대하지 말고 파일을 즉시 자체 스토리지에 저장하세요.
일반적인 오류 및 해결 방법
대부분의 실패는 몇 가지 범주로 나뉩니다. 각각의 증상과 해결 방법은 다음과 같습니다.
401 Unauthorized
키가 없거나, 형식이 잘못되었거나, 요청을 보내는 프로세스에서 보이지 않는 경우입니다.
- 헤더가 정확히
Authorization: Bearer <key>인지 확인하세요.Bearer라는 단어, 공백 하나, 그다음 키입니다. - 환경 변수가 같은 셸 또는 프로세스에 설정되어 있는지 확인하세요. 컨테이너와 CI에서는 로컬 셸에서 export한 변수가 코드와 함께 넘어가지 않습니다.
- 최근에 키를 교체했다면 이전 키가 어딘가에 여전히 캐시되어 있지 않은지 확인하세요.
400 Bad Request
보통 요청 본문 문제입니다.
- 알 수 없거나 오타가 난 필드 이름 —— 문서에 기록된 파라미터를 고수하세요.
- 엔드포인트가 허용하지 않는
aspect_ratio값 —— 문서의width:height형식을 사용하세요. n이 허용 범위를 벗어남.- JSON 형식 오류 —— 예를 들어 불필요한 쉼표나 프롬프트 문자열 안의 이스케이프되지 않은 따옴표. 이 문제가 의심되면 보내기 전에 요청 본문을 포맷팅하여 확인하세요.
상태 조회 또는 다운로드 단계에서 404 반환
작업 ID가 잘못되었거나, 폴링하는 경로가 제출에 사용한 엔드포인트와 일치하지 않는 경우입니다. 첫 통합 시 제출 응답을 완전히 기록하고 ID를 문자 단위로 대조하세요.
폴링 타임아웃
wait_for_job이 마감 시간에 도달한 경우:
- 올바른 상태 값을 확인하고 있는지 확인하세요. 인식하지 못하는 종료 상태는 멈춘 것처럼 보입니다.
- 크고 복잡한 렌더링의 경우 폴링 간격을 줄이지 말고 전체 타임아웃을 늘리세요.
- 통합 중에는 매 상태 응답을 기록하여 해당 프롬프트 조합에서 작업이 실제로 얼마나 걸리는지 파악하세요.
작업 상태가 failed 반환
API가 반환한 오류 응답 본문을 읽으세요. 존재하는 데는 이유가 있습니다. 실패한 작업은 보통 프롬프트나 파라미터 측 문제이며, 수정 지점은 폴링 코드가 아니라 요청에 있습니다.
불분명한 부분이 있으면 해당 모델의 HiAPI 문서가 필드 이름과 허용 값의 권위 있는 출처입니다. 한 번에 하나의 변경만 검증하고, 다음 통합을 위해 동작하는 것으로 확인된 요청을 저장해 두세요.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드