HiAPI
블로그

튜토리얼

hiapi API로 gpt-image-2 이미지 투 이미지 사용하는 방법

hiapi에서 gpt-image-2의 이미지 투 이미지 엔드포인트를 호출하는 방법을 알려주는 바로 실행 가능한 코드 레시피: 요청 엔벨로프, 참조 이미지와 aspect_ratio 파라미터, 폴링과 콜백의 선택, 그리고 바로 복사해 붙여넣을 수 있는 curl, Python, Node.js 예제.

Jun 26, 2026
hiapi API로 gpt-image-2 이미지 투 이미지 사용하는 방법

이 레시피는 hiapi 통합 작업 API를 통해 gpt-image-2의 이미지 투 이미지 모드를 호출하는 방법을 단계별로 보여줍니다. 바로 실행 가능한 curl 예제, 백엔드에 바로 삽입할 수 있는 Python 스크립트, 서버리스 환경에 적합한 Node.js 버전, 그리고 실제로 중요한 파라미터와 프로덕션 환경에서 흔히 겪는 함정들을 확인하게 됩니다.

이 글을 다 읽고 나면, 참조 이미지 URL과 프롬프트를 받아 생성된 이미지 URL을 반환하는 스크립트를 갖추게 됩니다. 이 URL을 직접 다운로드하거나 스토리지 계층에 넘겨 처리하면 됩니다.

준비물

  • hiapi 계정과 API 키. hiapi 콘솔에서 발급받을 수 있습니다.
  • 공개 HTTPS URL에 호스팅된 참조 이미지(또는 base64 data URL — 둘 다 가능합니다).
  • 모델이 해당 참조 이미지에 어떤 변환을 적용하길 원하는지 설명하는 텍스트 프롬프트.

이게 전부입니다. SDK 설치가 필요 없습니다 — hiapi는 HTTP + JSON이므로 POST 요청을 보낼 수 있는 언어라면 무엇이든 사용할 수 있습니다.

순수 텍스트 투 이미지부터 알고 싶으신가요? hiapi API로 이미지 생성하는 방법을 참고하세요. 아래 패턴은 동일한 비동기 작업 흐름에 image 필드만 추가된 형태입니다.

최소 실행 호출

hiapi는 동일한 비동기 작업 인터페이스로 모든 이미지 모델을 노출합니다:

  1. POST /v1/tasks — 작업을 제출하면 taskId가 반환됩니다.
  2. GET /v1/tasks/{taskId}를 status === "success"가 될 때까지 폴링하거나, 또는 callback.url을 제공하여 webhook으로 최종 결과를 받습니다.
  3. data.output[0].url에서 이미지 URL을 읽어 다운로드하거나 저장합니다.

curl

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/image-to-image",
    "input": {
      "prompt": "transform the subject into a watercolor painting, soft pastel palette",
      "image": "https://example.com/reference.jpg",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'

즉시 반환되는 응답에서 작업 id를 얻을 수 있습니다:

{ "data": { "taskId": "task_01HXXXX..." } }

그다음 결과를 폴링합니다:

curl https://api.hiapi.ai/v1/tasks/task_01HXXXX... \
  -H "Authorization: Bearer sk-YOUR_KEY"

작업이 준비되면 응답은 다음과 같습니다:

{
  "data": {
    "status": "success",
    "output": [{ "url": "https://cdn.hiapi.ai/...png", "expireAt": "..." }]
  }
}

output[0].url은 단기간만 유효하므로(expireAt 참고) 즉시 다운로드하거나 자체 스토리지에 재업로드하세요 — 최종 사용자에게 핫링크로 제공해서는 안 됩니다.

실제로 중요한 파라미터

필드 유형 설명
model string 맨 id gpt-image-2/image-to-image를 사용하세요. models/ 접두사를 붙이지 마세요.
input.prompt string 참조 이미지에 적용하고자 하는 변환.
input.image string HTTPS URL 또는 data:image/...;base64,... URL.
input.aspect_ratio string 다음 중 하나: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 또는 auto.
input.resolution string 1K, 2K 또는 4K. 기본값 1K.

중요한 동작 두 가지:

  • 일부 hiapi 모델은 aspect_ratio만 허용하고(resolution 없이), 다른 모델은 픽셀 크기를 요구합니다. gpt-image-2/image-to-image는 위에 표시된 aspect_ratio + resolution 조합을 허용합니다 — 여기에 size: "1024x1024"를 전달하지 마세요.
  • image 필드는 참조 이미지입니다. base64 data URL을 전달하는 경우 payload가 플랫폼의 요청 본문 제한보다 작은지 확인하세요(몇 MB는 괜찮지만, 여러 메가바이트 이미지는 먼저 업로드한 뒤 URL로 전달해야 합니다).

프로덕션용 Python 스크립트

이 버전은 데드라인을 두고 폴링하며 실패 시 깔끔하게 종료합니다:

import os
import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


def submit(prompt: str, image_url: str, aspect_ratio: str = "1:1") -> str:
    payload = {
        "model": "gpt-image-2/image-to-image",
        "input": {
            "prompt": prompt,
            "image": image_url,
            "aspect_ratio": aspect_ratio,
            "resolution": "1K",
        },
    }
    r = requests.post(API, headers=HEADERS, json=payload, timeout=30)
    r.raise_for_status()
    return r.json()["data"]["taskId"]


def wait(task_id: str, timeout_s: int = 300, interval_s: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=20)
        r.raise_for_status()
        task = r.json()["data"]
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(interval_s)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


if __name__ == "__main__":
    task_id = submit(
        prompt="transform the subject into a watercolor painting, soft pastel palette",
        image_url="https://example.com/reference.jpg",
    )
    print("task:", task_id)
    print("url:", wait(task_id))

HIAPI_API_KEY=sk-... python recipe.py로 실행하세요.

Node.js (fetch, 의존성 없음)

const API = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
const headers = {
  Authorization: `Bearer ${TOKEN}`,
  "Content-Type": "application/json",
};

async function submit(prompt, imageUrl, aspectRatio = "1:1") {
  const r = await fetch(API, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "gpt-image-2/image-to-image",
      input: { prompt, image: imageUrl, aspect_ratio: aspectRatio, resolution: "1K" },
    }),
  });
  const data = await r.json();
  if (!r.ok) throw new Error(JSON.stringify(data));
  return data.data.taskId;
}

async function wait(taskId, timeoutMs = 300000, intervalMs = 5000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const r = await fetch(`${API}/${taskId}`, { headers });
    const task = (await r.json()).data;
    if (task.status === "success") return task.output[0].url;
    if (task.status === "fail") throw new Error(JSON.stringify(task.error));
    await new Promise((res) => setTimeout(res, intervalMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await submit(
    "transform the subject into a watercolor painting, soft pastel palette",
    "https://example.com/reference.jpg",
  );
  console.log("task:", id, "\nurl:", await wait(id));
})();

폴링 vs. 콜백

5초마다 폴링하는 방식은 일회성 스크립트에는 문제없지만, 작업이 진행되는 동안 워커 하나를 계속 점유합니다. 실제 백엔드에서는 보통 webhook을 원합니다:

{
  "model": "gpt-image-2/image-to-image",
  "input": { "prompt": "...", "image": "https://example.com/reference.jpg" },
  "callback": { "url": "https://your-app.example.com/api/hiapi-callback", "when": "final" }
}

작업이 결산(성공 또는 실패)되면 hiapi가 해당 URL로 GET /v1/tasks/{id}에서 받은 것과 동일한 payload를 POST합니다. 이 핸들러는 멱등하게 취급하세요 — 재시도가 발생할 수 있습니다 — 그리고 요청을 신뢰하기 전에 검증하세요(URL에 자체 서명 토큰 포함, Authorization 헤더 확인 등).

깔끔한 패턴은 다음과 같습니다: 작업을 제출하고, 자체 job id를 키로 taskId를 영속화하고, 호출자에게 202 Accepted를 반환한 뒤, webhook이 저장 + 알림 작업을 완료하게 합니다.

오류 처리

실무에서는 세 가지 실패 모드를 만나게 됩니다:

  1. 401 permission_denied와 함께 "This API key cannot use the selected model." — 해당 키가 gpt-image-2/image-to-image 사용 권한이 없습니다. hiapi 콘솔에서 확인하고 가격 페이지에서 해당 모델이 요금제에 포함되는지 확인하세요.
  2. 400과 함께 additional properties not allowed — 특정 모델이 허용하지 않는 필드를 보냈습니다(예: aspect_ratio 대신 size 사용). 오류 메시지가 위반한 키 이름을 알려주므로 해당 필드를 제거하고 다시 시도하세요.
  3. 폴링 시 status: "fail"과 함께 data.error 객체 — 모델 자체가 입력을 거부했습니다(안전하지 않은 콘텐츠, 참조 URL 접근 불가 등). error.code와 error.message를 로그에 기록하고 무작정 자동 재시도하지 마세요.

항상 POST /v1/tasks 호출에 요청 타임아웃을 설정하고(30초면 충분합니다 — taskId를 빠르게 반환합니다), 폴링 루프나 webhook 수신 경로에는 별도의 더 긴 타임아웃을 설정하세요.

관련 링크

자주 묻는 질문

Q: gpt-image-2/image-to-image는 여러 장의 참조 이미지를 지원하나요? A: 최소 계약은 단일 image 필드를 사용합니다. 사용 사례에 여러 참조 이미지가 필요하다면(예: 피사체 이미지 + 스타일 이미지) 먼저 하나로 합성하거나 모델 페이지에서 최신 지원 필드를 확인하세요.

Q: URL 대신 로컬 파일을 전달할 수 있나요? A: 네 — data:image/png;base64,... URL로 인코딩하여 input.image로 전달하면 됩니다. 약 3 MB를 초과하는 파일은 자체 스토리지에 먼저 업로드하고 공개 URL을 전달하세요. 더 빠르고 요청 본문 제한도 피할 수 있습니다.

Q: 작업 하나에 얼마나 걸리나요? A: 대부분의 gpt-image-2 이미지 투 이미지 작업은 1K 해상도에서 10–30초에 완료됩니다. 더 높은 해상도와 복잡한 프롬프트는 더 오래 걸릴 수 있으므로 안전하게 폴링 타임아웃을 5분으로 설정하세요.

Q: 출력이 참조 이미지와 얼마나 달라지는지 어떻게 제어하나요? A: 프롬프트에서 명시적으로 표현하세요. "Keep the subject's pose and composition, only restyle to watercolor"가 "make this a watercolor"보다 더 엄격한 일관성을 만들어냅니다. gpt-image-2의 이미지 투 이미지 모드는 프롬프트 기반입니다 — 요청 엔벨로프에 별도의 "strength" 슬라이더는 없습니다.

Q: output[0].url은 영구적인가요? A: 아닙니다. expireAt 타임스탬프가 있습니다(보통 몇 시간). 작업이 성공하면 최대한 빨리 바이트를 다운로드하여 자체 스토리지(R2, S3 등)에 업로드하세요.

Q: 이미지 한 장당 비용은 얼마인가요? A: 요금제와 해상도에 따라 다릅니다. 현재 호출당 비용은 가격 페이지를 참고하세요.

영구 AI 아티팩트로 빌드 시작하기

API 키를 받아 태스크 기반의 하나의 API로 이미지, 비디오, 오디오 모델을 호출하세요.

API 문서 보기