에러 코드 & 트러블슈팅
Book Print API가 반환하는 HTTP 상태 코드, errorCode 카탈로그, 응답 shape, 트러블슈팅을 안내합니다.
HTTP 상태 코드
Book Print API가 사용하는 HTTP 상태 코드 카탈로그입니다. 같은 HTTP 상태라도 도메인 의미에 따라 구체적인 errorCode가 달라지므로, 클라이언트 분기는 HTTP 상태가 아니라 errorCode로 하세요.
| 코드 | 설명 | 비고 |
|---|---|---|
200 | 성공 | 요청이 정상적으로 처리됨 |
201 | 리소스 생성 성공 | 새 리소스가 생성됨 (예: 주문, 도서) |
400 | 잘못된 요청 | 필드 검증 실패, 잘못된 파라미터 등 |
401 | 인증 실패 | API Key가 없거나 유효하지 않음 |
402 | 충전금 부족 | 잔액이 부족하여 주문 결제 불가 |
403 | 권한 없음 | 해당 리소스에 대한 접근 권한 없음 / 환경 불일치 |
404 | 리소스 없음 | 요청한 리소스를 찾을 수 없음 |
409 | 충돌 | 리소스 상태 충돌, Idempotency 락 타임아웃 |
422 | 처리 불가 | 동일 Idempotency-Key + 다른 요청 본문, PDF 생성 실패 |
429 | Rate Limit 초과 | 요청 빈도 제한 초과(Retry-After 헤더 동봉) |
500 | 서버 에러 | 서버 내부 오류 |
501 | Sandbox 미지원 | Sandbox 환경에서 의도적으로 차단된 엔드포인트 호출 (Live 전용) |
에러 응답 형식
모든 실패 응답은 6필드 고정 shape으로 반환됩니다. errorCode·errors·fieldErrors가 항상 존재하므로 클라이언트에서 null 체크 없이 바로 접근할 수 있습니다.
| 필드 | 타입 | 역할 |
|---|---|---|
success | boolean | 실패 응답은 항상 false |
errorCode | string | 기계 분기용 식별자. ERR_* 형식. HTTP 상태 기반 기본값이 자동 주입되어 항상 존재 |
message | string | HTTP 상태 영어 라벨 ("Bad Request", "Not Found", "Forbidden" 등). 사용자 표시용 아님 |
data | object | null | 기본 null. 일부 에러는 진단 객체 포함(예: 402 {required, balance, currency}) |
errors | string[] | 사용자 표시용 한글 상세 메시지 배열. 항상 배열(비어 있으면 []) |
fieldErrors | object[] | 필드 단위 구조화 에러 배열. 항상 배열(해당 없으면 []) |
errors[0]을 사용하세요. message는 영어 라벨이므로 사용자 노출에 부적합합니다. 클라이언트 분기는 errorCode + 필요 시 fieldErrors[].constraint로 하세요.{
"success": false,
"errorCode": "ERR_NOT_FOUND",
"message": "Not Found",
"data": null,
"errors": ["해당 주문을 찾을 수 없습니다"],
"fieldErrors": []
}fieldErrors 항목 구조
필드 단위 검증 실패는 fieldErrors 배열의 각 항목이 아래 5필드를 가집니다. field·message는 항상 존재하며, 나머지 3개는 값이 있을 때만 포함됩니다.
| 필드 | 타입 | 설명 |
|---|---|---|
field | string | 에러 발생 필드명 (중첩은 점 표기) |
message | string | 한글 설명 |
currentValue | any | 요청에 담겨 온 실제 값(있을 때만) |
requiredValue | any | 요구 값 또는 허용 범위(단일 값 또는 {min, increment} 객체) |
constraint | string | 제약 종류 enum: required / min / max / increment / enum / pattern |
errorCode 카탈로그
파트너에게 반환되는 errorCode 21종(Generic 8 + Specific 13)의 한눈 매핑입니다. 각 코드의 응답 예시·처리 가이드는 아래 errorCode 케이스 상세에서 확인하세요.
| HTTP | errorCode | 카테고리 | 발생 조건 | 주요 발생 엔드포인트 | 재시도 |
|---|---|---|---|---|---|
| 400 | ERR_VALIDATION_FAILED | Generic | 일반 검증 실패 (Specific 코드 없을 때 기본값) | 모든 POST·PATCH·PUT (요청 본문/파라미터 검증) | X |
| 400 | ERR_MALFORMED_REQUEST | Generic | 요청 형식 오류 (필드 누락, null 등) | 모든 엔드포인트 | X |
| 400 | ERR_INSUFFICIENT_PAGES | Specific | 최소 페이지 미달 (pageCount < pageMin) | POST /books/{bookUid}/finalization | X |
| 400 | ERR_PAGECOUNT_INVALID | Specific | 최대 초과 또는 증분 규칙 위반 | POST /books/{bookUid}/finalization, /contents | X |
| 400 | ERR_FINALIZE_PREREQ_UNMET | Specific | finalize 전제조건 미충족 (PDF 미업로드, DRAFT 아님 등) | POST /books/{bookUid}/finalization | X |
| 400 | ERR_CREATION_TYPE_UNSUPPORTED | Specific | 책의 creationType과 호출 API가 호환되지 않음 | 표지/내지/사진/PDF 추가 (cover·contents·photos·pdf-cover·pdf-contents) | X |
| 401 | ERR_UNAUTHORIZED | Generic | 인증 실패 (API Key 누락·무효 등) | 모든 엔드포인트 | X |
| 402 | ERR_INSUFFICIENT_CREDIT | Specific | 충전금 잔액 부족 (data에 required·balance·currency 동봉) | POST /orders, POST /orders/estimate | X |
| 403 | ERR_FORBIDDEN | Generic | 권한 부족 (다른 파트너 자원 접근) | 모든 자원 접근 엔드포인트 | X |
| 403 | ERR_ENV_MISMATCH | Specific | 호출 도메인(sandbox/live)과 대상 리소스의 환경 불일치 | 책·사진·PDF 자원 접근 | X |
| 404 | ERR_NOT_FOUND | Generic | 리소스 미존재 | 모든 단건 조회/수정/삭제 엔드포인트 | X |
| 404 | ERR_PDF_NOT_UPLOADED | Specific | PDF 다운로드 시 업로드형 PDF가 디스크에 없음 (그룹 A — PDF_UPLOAD/MIX 내지) | GET /books/{bookUid}/pdf-cover, /pdf-contents | X |
| 409 | ERR_CONFLICT | Generic | 리소스 상태 충돌 (PDF 재등록), Idempotency 락 타임아웃 | POST /books/{bookUid}/pdf-cover, /pdf-contents, 모든 [Idempotent] 엔드포인트 | 일부 O |
| 409 | ERR_PDF_NOT_GENERATED | Specific | PDF 다운로드 시 책 최종화 호출 전 (그룹 B — TEMPLATE/MIX 표지) | GET /books/{bookUid}/pdf-cover, /pdf-contents | O (finalize 후) |
| 409 | ERR_PDF_PENDING | Specific | PDF 다운로드 시 백그라운드 생성 진행 중 (그룹 B) | 동일 (그룹 B) | O (간격 두고) |
| 422 | ERR_IDEMPOTENCY_KEY_MISMATCH | Specific | 동일 Idempotency-Key로 다른 요청 본문 전송 | [Idempotent] 적용 엔드포인트 (POST /books, /cover, /contents, /finalization, /orders, /orders/{uid}/cancel 등) | X |
| 422 | ERR_PDF_GENERATION_FAILED | Specific | PDF 다운로드 시 백그라운드 생성 실패 (그룹 B). 클라이언트 자체 해결 불가 | GET /books/{bookUid}/pdf-cover, /pdf-contents (그룹 B) | X (고객지원) |
| 429 | ERR_TOO_MANY_REQUESTS | Generic | Rate Limit 초과 (Retry-After 헤더 동봉) | 모든 엔드포인트 | O (Retry-After 후) |
| 500 | ERR_INTERNAL_ERROR | Generic | 서버 내부 오류 (미처리 예외 폴백) | 모든 엔드포인트 | O (Backoff) |
| 500 | ERR_PDF_FILE_MISSING | Specific | PDF 다운로드 시 생성 완료(pdfStatus=2 COMPLETED)인데 디스크에 파일 부재 (그룹 B — 서버 결함) | GET /books/{bookUid}/pdf-cover, /pdf-contents (그룹 B) | X (고객지원) |
| 501 | ERR_SANDBOX_UNSUPPORTED | Specific | Sandbox 환경에서 의도적으로 차단된 엔드포인트 (Live 전용) | 현재 파트너 노출 엔드포인트 중 0건 (관리자 전용 결제 확인 한정) | X (Live로) |
엔드포인트별 환경(Sandbox/Live) 호출 가능 여부는 환경 매트릭스를 참조하세요. Retry 전략·Backoff·Idempotency 결합 등 운영 패턴은 에러 핸들링 & Retry 전략을 참조하세요.
errorCode 케이스 상세
errorCode별로 발생 조건·응답 예시·처리 가이드를 정리합니다. 응답 받았을 때 errorCode로 검색하여 해당 카드를 참조하세요.
ERR_VALIDATION_FAILED · HTTP 400 · Generic
일반 검증 실패. 필수 필드 누락·잘못된 값·형식 불일치 등 Specific 코드가 더 구체적이지 않은 모든 검증 실패에서 반환됩니다. fieldErrors 배열에서 field·constraint를 확인하여 사용자에게 구체 수정 안내를 제공하세요. 재시도 불가 — 요청 본문 수정 필요.
{
"success": false,
"errorCode": "ERR_VALIDATION_FAILED",
"message": "Bad Request",
"data": null,
"errors": ["입력값을 확인해 주세요"],
"fieldErrors": [
{
"field": "title",
"message": "필수 항목입니다",
"constraint": "required"
}
]
}ERR_MALFORMED_REQUEST · HTTP 400 · Generic
요청 본문 형식 자체 오류. JSON 파싱 실패, 잘못된 Content-Type, 필수 헤더 누락 등 ModelBinding 단계에서 거부된 요청. 재시도 불가 — 요청 형식 수정 필요.
{
"success": false,
"errorCode": "ERR_MALFORMED_REQUEST",
"message": "Bad Request",
"data": null,
"errors": ["요청 형식이 올바르지 않습니다"],
"fieldErrors": []
}ERR_INSUFFICIENT_PAGES · HTTP 400 · Specific
finalize 직전 최소 페이지 미달 감지. fieldErrors의 pageCount에 currentValue·requiredValue·constraint: "min"이 구조화되어 있어 UI에 바로 매핑 가능합니다. 처리: 사용자에게 "최소 N페이지 필요" 안내 후 콘텐츠 추가하여 재시도.
{
"success": false,
"errorCode": "ERR_INSUFFICIENT_PAGES",
"message": "Bad Request",
"data": null,
"errors": ["최소 페이지 미달: 현재 10p, 최소 24p"],
"fieldErrors": [
{
"field": "pageCount",
"message": "최소 24 페이지가 필요합니다",
"currentValue": 10,
"requiredValue": 24,
"constraint": "min"
}
]
}ERR_PAGECOUNT_INVALID · HTTP 400 · Specific
최대 페이지 초과 또는 증분 규칙 위반(예: 짝수 단위만 허용). fieldErrors의 constraint로 max / increment 구분. 처리: pageMin~pageMax 범위와 pageIncrement 단위 확인 후 재시도.
{
"success": false,
"errorCode": "ERR_PAGECOUNT_INVALID",
"message": "Bad Request",
"data": null,
"errors": ["페이지 수는 2의 배수여야 합니다"],
"fieldErrors": [
{
"field": "pageCount",
"message": "2의 배수만 허용됩니다",
"currentValue": 25,
"requiredValue": { "min": 24, "increment": 2 },
"constraint": "increment"
}
]
}ERR_FINALIZE_PREREQ_UNMET · HTTP 400 · Specific
finalize 전제조건 미충족 — PDF 미업로드(PDF_UPLOAD 책), DRAFT 상태 아님 등. 다중 필드가 미충족인 경우 fieldErrors에 모두 누적되며, 하나라도 충족되면 해당 항목은 제외됩니다. 처리: fieldErrors에서 누락 항목별로 준비 단계 완료 후 재시도.
{
"success": false,
"errorCode": "ERR_FINALIZE_PREREQ_UNMET",
"message": "Bad Request",
"data": null,
"errors": [
"coverPdf: 표지 PDF가 업로드되지 않았습니다",
"contentsPdf: 내지 PDF가 업로드되지 않았습니다"
],
"fieldErrors": [
{
"field": "coverPdf",
"message": "표지 PDF가 업로드되지 않았습니다",
"requiredValue": "uploaded",
"constraint": "required"
},
{
"field": "contentsPdf",
"message": "내지 PDF가 업로드되지 않았습니다",
"requiredValue": "uploaded",
"constraint": "required"
}
]
}ERR_CREATION_TYPE_UNSUPPORTED · HTTP 400 · Specific
책의 creationType(TEMPLATE/PDF_UPLOAD/MIX_COVER_TEMPLATE)과 호출 API가 호환되지 않을 때 (예: PDF_UPLOAD 책에 POST /cover 템플릿 호출). 재시도 불가 — 책 생성 시 creationType 또는 호출 API 변경 필요. 자세한 호환성은 창작 방식을 참조하세요.
{
"success": false,
"errorCode": "ERR_CREATION_TYPE_UNSUPPORTED",
"message": "Bad Request",
"data": null,
"errors": ["이 책의 creationType(PDF_UPLOAD)에서는 사진 업로드를 지원하지 않습니다"],
"fieldErrors": []
}ERR_UNAUTHORIZED · HTTP 401 · Generic
Authorization 헤더 누락, Bearer 접두사 누락, 폐기·만료된 API Key. 환경 불일치(Sandbox Key로 Live URL 호출 등)는 401이 아니라 403 ERR_ENV_MISMATCH로 분기됩니다. 재시도 불가 — Authorization: Bearer <API Key> 형식 확인, 포털에서 Key 상태 확인 후 새 요청.
{
"success": false,
"errorCode": "ERR_UNAUTHORIZED",
"message": "Unauthorized",
"data": null,
"errors": ["인증이 필요합니다"],
"fieldErrors": []
}ERR_INSUFFICIENT_CREDIT · HTTP 402 · Specific
주문 생성 시 충전금 잔액 부족. 이 에러는 예외적으로 data에 진단 객체(required·balance·currency)가 들어있어 충전 UI로 바로 안내할 수 있습니다. 재시도 불가 — 파트너 포털에서 충전 후 새 요청.
{
"success": false,
"errorCode": "ERR_INSUFFICIENT_CREDIT",
"message": "Insufficient Credit",
"data": {
"required": 5500,
"balance": 1820.00,
"currency": "KRW"
},
"errors": ["잔액이 부족합니다. 필요: 5500, 잔액: 1820.00"],
"fieldErrors": []
}ERR_FORBIDDEN · HTTP 403 · Generic
본인 소유가 아닌 자원에 접근하려 한 경우. 재시도 불가 — 자원 소유권 확인 후 본인 자원으로 재요청.
{
"success": false,
"errorCode": "ERR_FORBIDDEN",
"message": "Forbidden",
"data": null,
"errors": ["해당 리소스에 대한 권한이 없습니다"],
"fieldErrors": []
}ERR_ENV_MISMATCH · HTTP 403 · Specific
Sandbox 도메인에서 Live 리소스를 접근하거나 그 반대인 경우. 401(잘못된 키)과 명확히 구분되므로 클라이언트는 "도메인 재선택"만 안내하면 됩니다. 재시도 불가 — api-sandbox.sweetbook.com과 api.sweetbook.com 중 키에 맞는 쪽으로 새 요청.
{
"success": false,
"errorCode": "ERR_ENV_MISMATCH",
"message": "Forbidden",
"data": null,
"errors": [
"환경 불일치: 호출 도메인과 API Key의 환경(sandbox/live)이 일치하지 않습니다. 키에 맞는 도메인으로 재시도하세요."
],
"fieldErrors": []
}ERR_NOT_FOUND · HTTP 404 · Generic
요청한 리소스(도서, 주문, 사진 등)를 찾을 수 없음. errors[0] 문구로 어떤 리소스가 누락됐는지 식별 가능합니다. 재시도 불가 — 생성 응답에서 받은 UID가 맞는지, 같은 환경에서 조회하는지 확인.
{
"success": false,
"errorCode": "ERR_NOT_FOUND",
"message": "Not Found",
"data": null,
"errors": ["책을 찾을 수 없습니다: bk_xxx"],
"fieldErrors": []
}참고: PDF 다운로드 시 그룹 A(PDF_UPLOAD/MIX 내지)에서 파일이 없는 경우는 더 구체적인 ERR_PDF_NOT_UPLOADED가 반환됩니다.
ERR_PDF_NOT_UPLOADED · HTTP 404 · Specific
PDF 다운로드 시 업로드형 PDF가 디스크에 없음. 그룹 A(PDF_UPLOAD cover/contents + MIX_COVER_TEMPLATE 내지)에서만 발생. 재시도 불가 — POST /books/{bookUid}/pdf-cover 또는 /pdf-contents로 PDF 업로드 후 새 요청.
{
"success": false,
"errorCode": "ERR_PDF_NOT_UPLOADED",
"message": "Not Found",
"data": null,
"errors": ["PDF 파일이 업로드되지 않았습니다."],
"fieldErrors": []
}ERR_CONFLICT · HTTP 409 · Generic
두 가지 상황에서 반환됩니다.
① 리소스 이미 존재 (재시도 불가)
PDF 업로드 POST(신규 등록 전용)를 이미 등록된 책에 다시 호출. 교체하려면 PUT 메서드를 사용하세요. 같은 요청을 재시도해도 같은 결과.
{
"success": false,
"errorCode": "ERR_CONFLICT",
"message": "Conflict",
"data": null,
"errors": ["표지 PDF가 이미 등록되어 있습니다. 교체하려면 PUT 메서드를 사용하세요."],
"fieldErrors": []
}② Idempotency 락 타임아웃 (재시도 가능)
동일한 Idempotency-Key로 동시 요청이 들어와 선행 요청의 분산 락이 잡혀 있는 경우. 첫 요청이 완료되기를 기다렸다가 같은 키로 재시도하면 캐시된 응답이 반환됩니다. 상세는 멱등성 (Idempotency) 참조.
{
"success": false,
"errorCode": "ERR_CONFLICT",
"message": "Conflict",
"data": null,
"errors": ["동일한 요청이 처리 중입니다. 잠시 후 다시 시도하세요."],
"fieldErrors": []
}참고: 같은 키로 다른 본문을 보낸 경우는 409가 아니라 422 ERR_IDEMPOTENCY_KEY_MISMATCH로 반환됩니다.
ERR_PDF_NOT_GENERATED · HTTP 409 · Specific
PDF 다운로드 시 책 최종화(POST /finalization) 호출 전. 그룹 B(TEMPLATE cover/contents + MIX_COVER_TEMPLATE 표지)에서만 발생. 처리: POST /books/{bookUid}/finalization 호출 후 재시도.
{
"success": false,
"errorCode": "ERR_PDF_NOT_GENERATED",
"message": "Conflict",
"data": null,
"errors": ["책 최종화 전이라 PDF가 존재하지 않습니다."],
"fieldErrors": []
}ERR_PDF_PENDING · HTTP 409 · Specific
PDF 다운로드 시 백그라운드 생성 진행 중. 그룹 B에서만 발생. 처리: 일정 간격(예: 10초~수십 초) 후 재시도. 응답에는 Retry-After 헤더가 포함되지 않으므로 클라이언트가 자체 대기 간격을 결정해야 합니다. 무한 폴링 금지 — 횟수·총 대기 시간 제한 필수.
{
"success": false,
"errorCode": "ERR_PDF_PENDING",
"message": "Conflict",
"data": null,
"errors": ["PDF 생성이 진행 중입니다. 잠시 후 다시 시도해 주세요."],
"fieldErrors": []
}ERR_IDEMPOTENCY_KEY_MISMATCH · HTTP 422 · Specific
같은 Idempotency-Key로 이전과 다른 요청 본문을 보낸 경우. 재시도는 반드시 동일 키 + 동일 본문으로만 가능합니다. 재시도 불가 — 본문이 달라져야 한다면 새 키 발급 후 새 요청.
{
"success": false,
"errorCode": "ERR_IDEMPOTENCY_KEY_MISMATCH",
"message": "Unprocessable Entity",
"data": null,
"errors": [
"동일한 Idempotency-Key에 서로 다른 요청 본문이 사용되었습니다. 같은 키는 같은 본문에만 재사용 가능합니다."
],
"fieldErrors": []
}ERR_PDF_GENERATION_FAILED · HTTP 422 · Specific
PDF 다운로드 시 백그라운드 생성 실패. 그룹 B에서만 발생. 클라이언트 자체 해결 불가 — 사용자에게 실패를 안내하고 고객지원팀 문의 권장. 재시도해도 같은 결과.
{
"success": false,
"errorCode": "ERR_PDF_GENERATION_FAILED",
"message": "Error",
"data": null,
"errors": ["PDF 생성에 실패했습니다. 고객지원팀에 문의해 주세요."],
"fieldErrors": []
}ERR_TOO_MANY_REQUESTS · HTTP 429 · Generic
정책별(auth/general/upload) 요청 한도 초과. 응답 본문과 함께 Retry-After 헤더(초 단위)가 동봉됩니다. 처리: Retry-After 헤더 값만큼 대기 후 재시도. 정책 상세는 Rate Limiting 가이드 참고.
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json; charset=utf-8
{
"success": false,
"errorCode": "ERR_TOO_MANY_REQUESTS",
"message": "Too Many Requests",
"data": null,
"errors": ["요청 한도를 초과했습니다. Retry-After 헤더 값만큼 대기 후 재시도하세요."],
"fieldErrors": []
}ERR_INTERNAL_ERROR · HTTP 500 · Generic
서버에서 미처리 예외가 발생한 경우의 폴백 응답. 내부 정보 유출 방지를 위해 일반 메시지만 반환되며, 일시적 오류일 수 있습니다. 처리: 짧은 간격(예: 1~2초) 후 Backoff로 재시도. 지속 발생 시 고객지원팀 문의.
{
"success": false,
"errorCode": "ERR_INTERNAL_ERROR",
"message": "Internal Server Error",
"data": null,
"errors": ["서버 오류가 발생했습니다"],
"fieldErrors": []
}ERR_PDF_FILE_MISSING · HTTP 500 · Specific
PDF 다운로드 시 생성 완료 상태(pdfStatus=2 COMPLETED)인데 디스크에 파일이 부재. 서버 결함으로 클라이언트 자체 해결 불가. 처리: 사용자에게 실패 안내 + 고객지원팀 문의. 재시도해도 같은 결과.
{
"success": false,
"errorCode": "ERR_PDF_FILE_MISSING",
"message": "Internal Server Error",
"data": null,
"errors": ["PDF 파일이 존재하지 않습니다. 고객지원팀에 문의해 주세요."],
"fieldErrors": []
}ERR_SANDBOX_UNSUPPORTED · HTTP 501 · Specific
Sandbox 환경에서 의도적으로 차단된 엔드포인트(예: 외부 결제망 호출) 호출. Live 환경 전용 액션이며, Sandbox에서는 실 결제 등 외부 부수효과 방지를 위해 차단. 엔드포인트별 환경 호출 가능 여부는 환경 매트릭스 참조.
재시도 주의: HTTP 501은 일반적으로 "서버 미구현"으로 해석되지만, 본 케이스는 의도적 미지원이라 재시도해도 동일 결과입니다. 자동 재시도 로직에서 제외하세요.
{
"success": false,
"errorCode": "ERR_SANDBOX_UNSUPPORTED",
"message": "Not Implemented",
"data": null,
"errors": ["이 엔드포인트는 sandbox 환경에서 지원되지 않습니다"],
"fieldErrors": []
}PDF 다운로드 — 출처별 응답 분기 (그룹 A·B)
GET /books/{bookUid}/pdf-cover·GET /books/{bookUid}/pdf-contents는 책의 creationType에 따라 응답이 두 그룹으로 분기됩니다. 클라이언트는 errorCode로 분기해야 하며, HTTP 상태만으로 판단하면 의도와 다른 동작이 됩니다.
- 그룹 A (사용자 업로드):
PDF_UPLOADcover/contents +MIX_COVER_TEMPLATE내지. 업로드된 파일 존재 여부만 검사.- 200 (성공) 또는 404
ERR_PDF_NOT_UPLOADED
- 200 (성공) 또는 404
- 그룹 B (백그라운드 생성):
TEMPLATEcover/contents +MIX_COVER_TEMPLATE표지. 책 최종화 후 백엔드가 PDF 렌더링 →pdfStatus에 따라 분기.- 200 (성공)
- 409
ERR_PDF_NOT_GENERATED(최종화 전) - 409
ERR_PDF_PENDING(생성 진행 중) - 422
ERR_PDF_GENERATION_FAILED(생성 실패 — 고객지원) - 500
ERR_PDF_FILE_MISSING(서버 결함 — 고객지원)
자세한 분기 표는 Books — PDF 기반 / Books — 템플릿 기반 페이지의 PDF 다운로드 섹션을 참조하세요.
자주 묻는 질문 (FAQ)
QHTTP 상태 코드로 분기해도 되나요?
ERR_INSUFFICIENT_PAGES·ERR_PAGECOUNT_INVALID·ERR_FINALIZE_PREREQ_UNMET·ERR_VALIDATION_FAILED 등으로 세분화되어 있어, errorCode로 분기해야 정확한 사용자 안내가 가능합니다.Q응답 메시지 문자열을 includes()로 파싱해 분기해도 되나요?
errors[0]·message 문구는 다국어화·표현 정비로 언제든 변경될 수 있습니다. 분기는 errorCode + fieldErrors[].constraint 조합으로만 하세요.QSandbox Key로 Live URL을 호출하면?
403 ERR_ENV_MISMATCH가 반환됩니다. 401(키 무효)과 구분되므로 클라이언트는 "도메인만 맞춰서 재시도"하면 됩니다. Sandbox Key는 api-sandbox.sweetbook.com, Live Key는 api.sweetbook.com에서만 사용 가능합니다.Q같은 Idempotency-Key로 다른 본문을 보내면?
422 ERR_IDEMPOTENCY_KEY_MISMATCH가 반환됩니다. 재시도는 반드시 원본과 동일한 본문 + 동일 키로만 가능합니다. 본문이 달라져야 한다면 새로운 키를 발급하세요.