HiAPI
블로그

튜토리얼

hiapi API로 851-labs/background-remover 사용하는 방법: curl, Python 및 실행 가능한 요청

Sep 5, 2026
hiapi API로 851-labs/background-remover 사용하는 방법: curl, Python 및 실행 가능한 요청

851-labs/background-remover는 단 한 번의 API 호출로 상품, 인물, 반려동물 사진을 투명 PNG로 변환합니다 — 프롬프트도, 마스크도, 가로세로 비율 설정도 필요 없습니다. 이 글에서는 정확한 요청 구조, 실행 가능한 curl 명령, 백엔드에 바로 넣을 수 있는 Python 스크립트, 그리고 가장 많은 사람이 실수하는 스키마 오류 하나를 소개합니다.

준비 작업

  • hiapi 계정과 콘솔에서 발급받은 API key.
  • 공개 HTTPS URL로 호스팅된 이미지. 작업 API는 파일 업로드가 아니라 URL을 받습니다 — 원본 이미지가 로컬에만 있다면 먼저 임의의 CDN이나 오브젝트 스토리지에 올리세요.

모든 요청은 통합 작업 엔드포인트로 전송됩니다:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

요청 구조 (그리고 반드시 기억해야 할 단 하나의 규칙)

모델 id는 851-labs/background-remover이며, 그대로 전달하면 됩니다. 이 모델의 input 스키마에는 필드가 하나뿐입니다:

필드 타입 필수 설명
image_url string 예 ^https?://[^\s]+$와 일치해야 합니다 — 직접 접근 가능한 http(s) URL.

이것이 스키마의 전부입니다. 코드를 작성하기 전에 알아둘 점이 두 가지 있습니다:

  1. prompt, mask, background-color, aspect-ratio 필드가 없습니다. 이 엔드포인트는 오직 한 가지 일 — 전경/배경 분리 — 만 하며, 그 외에는 아무것도 하지 않습니다. 이후에 다시 채색하거나 크기를 조정해야 한다면 다른 모델을 추가로 호출해야 합니다.
  2. 잉여 필드는 무시되지 않고 거부됩니다. 다른 모델의 payload에서 가져온 format이나 size 필드를 포함하면, 작업이 시작되기도 전에 400 INVALID_REQUEST: <root>: additional properties 'format' not allowed가 반환됩니다.

최소 실행 예제: curl

작업 생성:

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "851-labs/background-remover",
    "input": {
      "image_url": "https://your-cdn.example.com/product-shot.jpg"
    }
  }'

성공적으로 제출되면 data 안에 작업 id가 반환됩니다:

{"code": 200, "data": {"taskId": "tk-hiapi-..."}}

결과 폴링:

curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... \
  -H "Authorization: Bearer sk-<your-key>"

실행 중에는 data.status가 queued → handling → archiving 순으로 진행됩니다. 완료되면 "success"가 되고, 투명 PNG가 data.output에 나타납니다:

{
  "code": 200,
  "data": {
    "status": "success",
    "output": [{"url": "https://.../result.png", "expireAt": "..."}]
  }
}

출력 URL은 단기간만 유효합니다 (expireAt에 주목하세요). 작업이 성공하면 즉시 파일 바이트를 다운로드하세요 — 원본 URL을 핫링크하거나 장기 보관하지 마세요.

프로덕션용 Python: 제출, 폴링, 다운로드

import time
import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


def remove_background(image_url: str) -> bytes:
    # 1. 작업 생성
    resp = requests.post(API_BASE, headers=HEADERS, json={
        "model": "851-labs/background-remover",
        "input": {"image_url": image_url},
    }, timeout=60)
    body = resp.json()
    if resp.status_code != 200 or not (body.get("data") or {}).get("taskId"):
        raise RuntimeError(f"create failed [{resp.status_code}]: {body}")
    task_id = body["data"]["taskId"]

    # 2. 최종 상태가 될 때까지 폴링
    deadline = time.time() + 300
    while time.time() < deadline:
        task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS,
                            timeout=30).json().get("data") or {}
        if task.get("status") == "success":
            outputs = task.get("output") or []
            if not outputs or not outputs[0].get("url"):
                raise RuntimeError(f"task {task_id} succeeded but returned no output URL")
            # 3. 즉시 다운로드 — URL은 만료됨
            png = requests.get(outputs[0]["url"], timeout=120)
            png.raise_for_status()
            return png.content
        if task.get("status") == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(3)
    raise TimeoutError(f"task {task_id} still running after 300s")


if __name__ == "__main__":
    png = remove_background("https://your-cdn.example.com/product-shot.jpg")
    with open("cutout.png", "wb") as f:
        f.write(png)
    print(f"saved cutout.png ({len(png)} bytes)")

배경 제거는 가벼운 이미지 작업이므로 보통 300초 마감 시간보다 훨씬 빨리 완료됩니다 — 이 타임아웃은 예상 실행 시간이 아니라 안전장치일 뿐입니다.

폴링 대신 콜백 사용

웹 백엔드의 경우, 요청 핸들러에서 폴링하는 대신 작업 생성 시 콜백을 등록하는 것을 권장합니다. callback 객체는 model과 같은 최상위 레벨에 위치합니다:

{
  "model": "851-labs/background-remover",
  "input": { "image_url": "https://your-cdn.example.com/product-shot.jpg" },
  "callback": {
    "url": "https://your-app.example.com/hooks/hiapi",
    "when": "final"
  }
}

callback.when은 "final"만 지원합니다 — 작업이 success 또는 fail 상태가 되면 정확히 한 번 POST를 받으며, 진행 이벤트는 받지 않습니다. 핸들러는 taskId를 키로 사용해 중복 전달된 webhook이 중복 처리되지 않도록 하고, 엔드포인트가 확인하지 못한 id는 주기적으로 GET /v1/tasks/<id>로 훑어보세요.

오류 처리: 정말 중요한 오류

생성 시 400 INVALID_REQUEST — 오류 메시지가 정확한 필드를 알려줍니다:

메시지 원인
invalid input: image_url: missing required field "image_url" input이 비었거나 키 이름이 잘못됨
image_url: 'not-a-url' does not match pattern '^https?://[^\s]+$' 값이 올바른 형식의 http(s) URL이 아님
<root>: additional properties 'format' not allowed 이 모델이 허용하지 않는 필드를 전송함

이 오류들은 영구적입니다 — 동일한 payload로 재시도하면 영원히 실패합니다. 필드를 수정한 뒤 다시 전송하세요.

생성 시 401 permission_denied — 문제는 요청 본문이 아니라 key 자체에 있습니다:

{"error": {"code": "permission_denied", "message": "...", "request_id": "...", "type": "hiapi_error"}}

콘솔에서 해당 key의 모델 권한을 확인하세요.

작업이 status: "fail" 반환 — 생성은 성공했지만 실행 자체가 실패한 경우(보통 백엔드가 image_url을 가져오지 못함)입니다. data.error.code / message를 읽으세요. 이런 실패는 백오프를 두고 한 번 재시도해도 안전합니다.

알 수 없거나 만료된 작업 id를 GET하면 404와 함께 {"code": 404, "data": null, "message": "task not found"}가 반환됩니다 — 어떤 대조 스캔에서든 이를 "아직 대기 중"이 아니라 최종 상태로 취급해야 합니다.

다음 단계

자주 묻는 질문

프롬프트가 필요한가요? 아니요. image_url만 제공하면 모델이 전경과 배경을 스스로 분리합니다.

출력이 정말 투명한가요? 예 — 결과는 알파 채널이 있는 PNG이며, 어떤 배경에도 바로 합성할 수 있습니다.

같은 호출에서 가로세로 비율, 색상, 배경을 변경할 수 있나요? 아니요. 이 엔드포인트는 배경만 제거합니다. 다시 채색하거나, 크기를 조정하거나, 배경을 교체하려면 이 투명 PNG를 입력으로 사용해 이미지 편집 모델을 이어서 호출하세요.

왜 "additional properties '...' not allowed"가 발생하나요? 이 스키마는 image_url 필드 하나만 허용합니다. 다른 모델 payload에서 가져온 모든 필드 — format, size, background_color, 그 무엇이든 — 는 조용히 무시되지 않고 즉시 거부됩니다.

결과는 어떻게 저장해야 하나요? 작업이 status: "success"가 된 즉시 다운로드하세요. 출력 URL은 expireAt이 있는 서명 URL이며, 장기 핫링크용이 아닙니다.

비용은 얼마인가요? 이미지당 사용량 기준으로 청구됩니다. 현재 요금은 가격 페이지에서 확인하세요.

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

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

API 문서 보기