API reference
모든 상품 호출은 https://openapi.pilldoc.co.kr 한 주소로 받아요. 이 문서는 저장소의 OpenAPI 3.1 파일에서 만들어집니다.
OpenAPI JSON 과 Postman 컬렉션은 출시할 때 함께 올려요.
Authentication
모든 요청의 X-Api-Key 헤더에 앱의 키를 보냅니다. 키는 앱마다 테스트와 라이브가 따로 있어요.
pd_test_- 과금하지 않아요. 월 50건, 분당 10건, 동시 1건. 출력은 미리보기 크기로 고정
pd_live_- 선불 크레딧을 차감해요. 이메일 인증을 마친 조직의 소유자만 발급
보안 체크리스트
- 키는 서버의 환경 변수에 두고, 앱이나 브라우저 코드에 넣지 마세요.
- 키 원문을 로그와 저장소에 남기지 마세요.
- 유출이 의심되면 재발급하세요. 기존 키는 7일 동안 함께 유효합니다.
X-Api-Key: YOUR_TEST_KEYRequest & response
POST /v1.0/removebg 에 multipart/form-data 로 보냅니다. 성공하면 배경이 지워진 이미지가 응답 본문으로 돌아와요.
curl -X POST "https://openapi.pilldoc.co.kr/v1.0/removebg" \ -H "X-Api-Key: YOUR_TEST_KEY" \ -F "image_file=@product.jpg" \ -F "size=preview" \ -o result.png
import { readFile, writeFile } from "node:fs/promises"; const form = new FormData(); form.append("image_file", new Blob([await readFile("product.jpg")]), "product.jpg"); form.append("size", "preview"); const res = await fetch("https://openapi.pilldoc.co.kr/v1.0/removebg", { method: "POST", headers: { "X-Api-Key": "YOUR_TEST_KEY" }, body: form, signal: AbortSignal.timeout(150_000), }); if (!res.ok) throw new Error(await res.text()); await writeFile("result.png", Buffer.from(await res.arrayBuffer()));
import requests res = requests.post( "https://openapi.pilldoc.co.kr/v1.0/removebg", headers={"X-Api-Key": "YOUR_TEST_KEY"}, files={"image_file": open("product.jpg", "rb")}, data={"size": "preview"}, timeout=150, ) res.raise_for_status() open("result.png", "wb").write(res.content)
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(150) }; http.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_TEST_KEY"); using var form = new MultipartFormDataContent(); form.Add(new ByteArrayContent(await File.ReadAllBytesAsync("product.jpg")), "image_file", "product.jpg"); form.Add(new StringContent("preview"), "size"); var res = await http.PostAsync("https://openapi.pilldoc.co.kr/v1.0/removebg", form); res.EnsureSuccessStatusCode(); await File.WriteAllBytesAsync("result.png", await res.Content.ReadAsByteArrayAsync());
HTTP/1.1 200 OK Content-Type: image/png X-PD-Request-Id: (요청 ID) X-PD-Test-Size: preview X-PD-Test-Remaining: 49 X-Width: 640 X-Height: 480 X-Processing-Ms: (처리 시간)
| 파라미터 | 받는 값 | 단가 등급 | 받지 않는 값 |
|---|---|---|---|
image_file | multipart 이미지. 본문 12MB 이하, 입력 12MP 이하 | 출력 픽셀로 정해요 | 12MB 초과는 413 file_too_large |
size | preview, small, regular, auto, full. 생략할 수 있어요 | preview, small, regular 는 미리보기 22원. auto, full, 생략은 전체 해상도 110원을 먼저 잡아요 | 그 밖의 값은 400 unsupported_parameter |
type | product, auto | 영향 없음 | 그 밖의 값은 400 |
format | png, auto | 영향 없음 | 그 밖의 값은 400 |
semitransparency | remove.bg 와 같은 방식 | 영향 없음 | 없음 |
crop | 생략 또는 false 만 | 영향 없음 | crop=true 는 400 unsupported_parameter, crop_margin 은 400 invalid_parameter |
image_url, image_file_b64, 쿼리 문자열 | 받지 않아요 | 해당 없음 | 400 unsupported_parameter |
응답 헤더
| 헤더 | 언제 |
|---|---|
X-PD-Request-Id | 모든 응답. 문의할 때 알려 주세요 |
X-PD-Charged-KRW | 유료 성공 응답. 이번 요청에 차감한 금액(원) |
X-PD-Balance-KRW | 유료 성공 응답. 차감 뒤 잔액(원) |
X-PD-Test-Size | 테스트 키. 항상 preview |
X-PD-Test-Remaining | 테스트 키. 이번 달 남은 무료 호출 |
X-Width X-Height X-Processing-Ms | 결과 이미지 크기와 처리 시간 |
Limits
한도에 닿으면 다음 기간까지 429 가 돌아와요. 429 요청은 과금하지 않습니다.
HTTP/1.1 429 Too Many Requests {"errors":[{"title":"Daily limit reached","code":"daily_limit_reached"}]}
| 구분 | 기본값 | 닿으면 | 다시 쓸 수 있을 때 |
|---|---|---|---|
| 조직 일 한도 | 50,000원(0원부터 1,000,000원까지 소유자가 바꿔요) | 429 daily_limit_reached | 다음 날 00:00 KST |
| 앱 일 한도, 월 한도 | 정하지 않음(선택) | 429 daily_limit_reached, monthly_limit_reached | 다음 날 00:00 KST, 매월 1일 00:00 KST |
| 라이브 동시 처리 | 조직당 2건 | 429 rate_limited | Retry-After 뒤 |
| 외부 전체 동시 처리 | 모든 고객의 합계로 정해요 | 429 rate_limited | Retry-After 뒤 |
| 테스트 키 | 월 50건, 분당 10건, 동시 1건 | 429 test_quota_exceeded | 분당 한도는 1분 뒤, 월 한도는 매월 1일 00:00 KST. 운영자가 줄인 조직은 월 초기화 없이 조직 생애 50건 |
Error codes
오류 본문은 {"errors":[{"title","code"}]} 형식이에요. 아래 오류는 모두 과금하지 않습니다.
HTTP/1.1 401 Unauthorized X-PD-Request-Id: (요청 ID) Content-Type: application/json {"errors":[{"title":"API key is invalid","code":"invalid_api_key"}]}
게이트웨이 오류
| HTTP | code | 뜻 | 과금 | 조치 |
|---|---|---|---|---|
| 400 | invalid_parameter, unsupported_parameter | multipart 를 읽지 못함, size 가 지원 값 밖 | 없음 | 요청 형식 확인 |
| 401 | invalid_api_key | 키 없음, 형식 오류, 없는 키, 삭제, 만료, 휴면 | 없음 | 인증 정보에서 키 확인 또는 재발급 |
| 403 | key_suspended | 운영자가 키를 정지함 | 없음 | 지원 문의 |
| 403 | product_not_enabled | 앱에 상품이 꺼져 있음(심사 전 포함) | 없음 | 앱 설정 또는 이용 신청 |
| 403 | refund_pending | 환불을 처리 중인 조직의 유료 호출 | 없음 | 환불 완료 뒤 재충전 |
| 403 | product_discontinued | 판매 중지된 상품 | 없음 | 상태 페이지와 공지 확인 |
| 402 | insufficient_credits | 잔액이 요청 단가 등급의 예약액보다 적음 | 없음 | 충전 |
| 413 | file_too_large | 요청 본문이 12,000,000바이트 초과. 길이를 알리지 않는 업로드는 받는 도중 넘으면 | 없음 | 이미지 축소 |
| 429 | rate_limited | 조직 라이브 동시 처리 상한, 외부 전체 동시 처리 상한(모든 고객의 합계), 같은 IP 의 무효 키 반복 | 없음 | Retry-After 뒤 재시도 |
| 429 | daily_limit_reached | 조직 일 한도 또는 앱 일 한도 도달 | 없음 | 한도 변경 또는 다음 기간 |
| 429 | monthly_limit_reached | 앱 월 한도 도달 | 없음 | 한도 변경 또는 다음 기간 |
| 429 | test_quota_exceeded | 테스트 월 50건 또는 분당 10건 초과, 운영자가 줄인 조직은 생애 50건 초과 | 없음 | 분당은 1분 뒤 재시도, 그 밖은 라이브 키 사용 |
| 502 | upstream_error | 상품 서비스 응답 형식 오류 또는 연결 실패 | 없음 | 재시도 |
| 503 | service_unavailable | 점검 또는 상품 비가용(Retry-After) | 없음 | 상태 페이지 확인 |
| 503 | gateway_busy | 게이트웨이 수신 바이트 예산 초과(Retry-After) | 없음 | Retry-After 뒤 재시도 |
| 504 | upstream_timeout | 최초 수신부터 140초 안에 상류 응답이 없음(재시도 포함 전체 시한) | 없음 | 재시도, 클라이언트 시한 150초 이상 |
상품 오류
| HTTP | code | 뜻 | 과금 | 조치 |
|---|---|---|---|---|
| 400 | unsupported_parameter | image_url, image_file_b64, 쿼리 문자열, crop=true 를 보냄 | 없음 | 지원 파라미터만 보내기 |
| 400 | invalid_parameter | crop_margin 같은 값이 잘못됨 | 없음 | 파라미터 값 확인 |
| 503 | deadline_unreachable | 처리 시한 안에 처리를 시작할 수 없음(처리 전 거절) | 없음 | Retry-After 뒤 재시도 |
| 429 | key_queue_full | 같은 키의 대기열이 가득 참(처리 전 거절) | 없음 | Retry-After 뒤 재시도 |
| 5xx | inference_failed | 처리 뒤 실패 | 없음 | 같은 오류가 반복되면 요청 ID로 문의 |
Retry
처리를 시작하기 전에 거절됐거나 닿지 못한 요청은 게이트웨이가 먼저 최대 2회 다시 보냅니다. Retry-After 를 지키고(없으면 10초), 남은 시간이 30초 이상일 때만 보내요. 재시도해도 과금은 1회입니다.
다시 보내는 경우
- 연결 오류
- 503
deadline_unreachable,queue_full,shutting_down,service_not_ready,receive_budget_exhausted,model_unavailable,circuit_open - 429
key_queue_full
고객 쪽 계약
- 503, 429 응답은
Retry-After를 지켜 다시 보내세요. - 클라이언트 시한은 150초 이상으로 설정하세요.
- 처리 뒤 실패(5xx
inference_failed등)는 게이트웨이가 다시 보내지 않아요. 과금되지 않으며, 반복되면 요청 ID로 문의해 주세요.
시한 = 150초 이상으로 설정
시도 = 0
반복:
응답 = 요청 보내기
성공이면 종료
처리 전 거절(연결 오류, 503, 429 key_queue_full)이고
시도 < 2 이면:
Retry-After 만큼 기다림(없으면 10초)
시도 = 시도 + 1
다시 반복
그 밖의 오류는 재시도하지 않고 요청 ID 를 남김Differences from remove.bg
호출 형식은 remove.bg 의 부분 집합을 지원해요. 기본 주소와 키만 바꾸면 대부분 그대로 동작하지만 아래는 달라요.
| 항목 | remove.bg | PillDoc Developers |
|---|---|---|
| 기본 주소 | api.remove.bg | openapi.pilldoc.co.kr |
| 인증 실패 | (원문 확인 중) | 401 invalid_api_key. 인증 실패를 403 으로 분기하는 클라이언트는 401 도 처리하도록 바꿔 주세요 |
| 과금 표시 | (원문 확인 중) | X-PD-Charged-KRW(원) |
| 결제 방식 | 크레딧 단위 | 원화 선불 크레딧, 건당 차감 |
| 지원하지 않는 요청 | image_url, image_file_b64 지원 | 400 unsupported_parameter |
crop | 지원 | 생략 또는 false 만 |
| 테스트 키 | 무료 계정의 미리보기 월 50건 | 테스트 키 월 50건, 출력 미리보기로 고정 |
API versioning
버전은 경로에 둡니다. 배경 제거는 /v1.0/ 이에요.
- 하위 호환을 깨는 변경
- 새 버전 경로로만 내요. 기존 경로의 동작은 바꾸지 않습니다.
- 기존 버전 종료
- 종료 90일 전에 릴리즈 노트와 이메일로 알립니다.
https://openapi.pilldoc.co.kr/v1.0/removebg