HiAPI
블로그

튜토리얼

HiAPI 요청이 실패했는데 왜 여전히 과금되나요?

Oct 8, 2026
HiAPI 요청이 실패했는데 왜 여전히 과금되나요?

문제 현상

생성 작업을 POST로 https://api.hiapi.ai/v1/tasks에 보내고, GET /v1/tasks/:id로 폴링했더니 "status": "fail"과 함께 error 객체(예: {"code": "TASK_FAILED", "message": "task failed"})가 반환되었습니다. 이 폴링 호출 자체의 HTTP 상태 코드는 정상적인 200입니다. HiAPI는 실패 정보를 상태 코드가 아니라 JSON body 안에 담아서 반환합니다. 이 작업이 실제로 queued → handling을 거쳐 실패했기 때문에, 이번 시도도 정상 호출과 마찬가지로 과금되었다고 오해하기 쉽습니다. 실제로는 작업이 종료 상태인 fail에 도달한 것이 곧 과금을 의미하지는 않습니다. 다만 환불이 아직 반영되기 전에 잔액을 먼저 확인했다면, 생성 시점의 예약(선점) 금액 때문에 장부상 과금된 것처럼 보일 수 있습니다.

흔한 원인

  1. "예약"을 "과금"으로 착각한 경우. HiAPI는 작업이 막 생성되어 아직 실제로 실행되기 전 시점에 해당 작업의 예상 비용을 예약합니다. 이 예약 금액은 즉시 잔액에 반영되지만, 아직 과금은 아닙니다.
  2. 작업이 진행 중일 때 잔액을 조회한 경우. queued/handling에서 종료 상태에 도달하기 전까지 이 예약 금액은 원래 "걸려 있는" 상태이며, 이는 설계된 동작입니다. 종료 상태(success 또는 fail)가 되어야만 결산됩니다.
  3. "다운스트림이 실제로 실행되었으나 실패한 경우"와 "생성 단계에서 거부된 경우"를 혼동한 경우. status: "fail"(예: error.code: "TASK_FAILED")에 도달한 작업은 실제로 생성되었고, 실제로 실행되었으며, 다운스트림이 실패한 것입니다. HiAPI 문서에 명시되어 있듯이, 작업이 이 종료 상태에 도달하면 예약 금액은 전액 자동으로 환불됩니다. 반면 taskId를 한 번도 받지 못한 요청, 예를 들어 동기 응답으로 반환된 402 INSUFFICIENT_QUOTA는 작업이 존재하기 전에 거부된 것이므로 예약된 것이 아무것도 없습니다. 둘 다 외부에서는 "실패"로 보이지만, 전자만 실제로 예약 메커니즘을 거쳤습니다.
  4. Idempotency-Key를 잘못 사용한 경우. 동일한 key와 동일한 요청 본문으로 재전송하면 원래의 taskId만 반환되고, 새로 생성되거나 두 번 과금되지 않습니다. 그러나 동일한 key로 요청 본문만 바꿔 재전송하면 생성 단계에서 바로 422 IDEMPOTENCY_KEY_MISMATCH가 반환됩니다. 동일한 key를 첫 호출이 아직 처리 중일 때 다시 보내면 409 IDEMPOTENCY_KEY_PROCESSING이 반환됩니다. 이 두 경로 모두 과금 가능한 작업을 생성하지 않습니다.

해결 단계

  1. GET /v1/tasks/:id로 폴링하여 data.status를 직접 확인하세요. 어느 한 시점의 잔액 스크린샷만으로 과금 결과를 추측하지 마세요. queued, handling, archiving은 모두 비종료 상태이며, success와 fail만 종료 상태입니다.
  2. data.status가 "fail"이라면 이는 환불되는 결과입니다. data.error.code(예: TASK_FAILED)를 확인해 원인을 파악한 뒤 잔액을 다시 조회하세요. 환불은 작업이 이 종료 상태에 도달한 후 자동으로 반영됩니다.
  3. POST /v1/tasks 호출 자체가 2xx가 아닌 상태 코드(400/402/409/415/422)를 반환하고 body에 taskId가 없다면, 환불할 작업이 없습니다. 애초에 생성되거나 과금된 작업이 없기 때문입니다. 잔액 부족의 구체적인 상황은 402 응답의 error_code: "INSUFFICIENT_QUOTA"로 나타납니다.
  4. HiAPI 빌링 대시보드에서 특정 시점의 잔액 숫자만 보지 말고 "예약—환불" 거래 기록 쌍을 대조 확인하세요.
  5. 실패한 작업을 재시도할 때는 이번의 진짜 새로운 시도에 대해 새로운 Idempotency-Key를 사용하세요. 기존 key로 요청 본문만 바꿔 재전송하지 마세요(422가 발생합니다). 또한 첫 번째 요청이 아직 처리 중일 때 동일한 key로 다시 보내지 마세요(409가 발생합니다).
  6. 작업이 fail 종료 상태에 도달한 것이 확인되었는데도 일정 시간이 지나도록 예약 금액이 환불되지 않는다면, 이는 이 자동 환불 메커니즘의 범위를 벗어난 것입니다. 스스로 복구될 것이라고 가정하지 말고 지원팀에 직접 문의하세요.

최소 검증 예시

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "model": "gpt-image-2/text-to-image",
    "input": { "prompt": "a minimalist desk setup, studio lighting" }
  }'

여기서 model 필드에는 라우팅 접미사 /text-to-image가 붙어 있습니다. 이 글을 작성하는 시점 기준으로 HiAPI 모델 인덱스의 gpt-image-2 그룹에는 라우팅 접미사가 붙은 항목(/text-to-image, /image-to-image)만 등재되어 있고, 접미사 없는 순수 id 항목은 없습니다. 접미사를 붙여야 하는지, 어떤 접미사를 붙여야 하는지는 반드시 이 실시간 모델 인덱스에서 availability: "online"인 항목을 기준으로 확인하고, 다른 모델이나 오래된 문서의 표기법을 그대로 따라 하지 마세요.

반환된 taskId를 받은 후 폴링합니다:

curl -s https://api.hiapi.ai/v1/tasks/$TASK_ID \
  -H "Authorization: Bearer $HIAPI_API_KEY"

환불된 실패 작업은 다음과 같은 형태입니다:

{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "tk-hiapi-...",
    "model": "gpt-image-2/text-to-image",
    "status": "fail",
    "created": 1777282033,
    "completed": 1777282099,
    "error": { "code": "TASK_FAILED", "message": "task failed" }
  }
}

관련 내부 링크

FAQ

이미지나 동영상 작업이 실패하면 HiAPI가 요금을 청구하나요? 아니요. 작업이 종료 상태인 fail에 도달하면 생성 시점에 예약된 금액은 전액 자동으로 환불됩니다.

작업을 제출한 직후 잔액이 바로 줄었는데, 이 작업이 나중에 실패했습니다. 왜 잔액이 돌아오지 않나요? 그 감소분은 생성 시점의 예약 금액이지 과금이 아닙니다. 작업이 종료 상태에 도달하면 자동으로 결산됩니다. fail이면 환불되고, success일 때만 실제로 소모됩니다.

402 오류와 작업 실패의 차이는 무엇인가요? 402 INSUFFICIENT_QUOTA는 작업이 애초에 생성되지 않았다는 뜻이므로 예약할 것도, 환불할 것도 없습니다. 반면 taskId를 받고 나중에 status가 "fail"로 바뀐 작업은 실제로 생성되었고, 실제로 실행되었으며, 다운스트림이 실패한 것입니다. HiAPI는 이 예약 금액을 자동으로 환불합니다.

동일한 Idempotency-Key로 재시도하면 두 번 과금되나요? 아니요. 동일한 key와 동일한 요청 본문으로 재전송하면 원래의 taskId만 반환되고 새 작업은 생성되지 않습니다. 동일한 key에서 요청 본문을 바꾸면 422 IDEMPOTENCY_KEY_MISMATCH가 바로 발생하며, 중복 작업도 생성되지 않습니다.

예약과 환불 기록은 어디에서 볼 수 있나요? HiAPI 빌링 대시보드의 청구 및 거래 기록에서 확인할 수 있습니다.

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

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

API 문서 보기