Books API — PDF 기반
파트너가 제작한 PDF 파일(표지·내지)을 직접 업로드하여 책을 생성하는 방식의 API 레퍼런스입니다. 템플릿 바인딩이 아닌 PDF 직접 업로드 흐름과 각 엔드포인트의 정확한 스펙을 다룹니다.
creationType="TEMPLATE")은 Books — 템플릿 기반 페이지를 참고하세요. 실제 호출 흐름을 단계별 따라 하기로 보려면 PDF 업로드 시나리오를 참고하세요.Authorization: Bearer {YOUR_API_KEY} 헤더로 제공하세요. 자세한 인증 안내는 인증 가이드를 참고하세요.이 방식이 적합한 경우
- 이미 자체 제작한 PDF 파일이 있는 경우
- 인쇄용 PDF를 직접 디자인 도구(InDesign, Illustrator 등)로 제작하는 경우
- 레이아웃·폰트·이미지를 파트너가 완전히 제어하고 싶은 경우
지원 creationType
creationType | 표지 | 내지 | 비고 |
|---|---|---|---|
PDF_UPLOAD | PDF 직접 업로드 | PDF 직접 업로드 | 이 페이지의 기본 흐름 |
MIX_COVER_TEMPLATE | 템플릿 바인딩 | PDF 직접 업로드 | 표지 추가는 Books — 템플릿 기반의 POST /books/{bookUid}/cover 사용 |
TEMPLATE 방식은 표지·내지 모두 템플릿 바인딩으로 진행하며, 이 페이지의 PDF 업로드 엔드포인트(/pdf-cover, /pdf-contents)는 사용할 수 없습니다.Books — 템플릿 기반을 참고하세요.
책 생성
/books새로운 책을 생성합니다. 생성 직후 status="draft" 상태이며, 이후 PDF 업로드와 최종화 단계를 거쳐 주문 가능 상태로 진입합니다.
Request Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
title | string | O | 책 제목 (1~255자) |
bookSpecUid | string | O | 판형 UID (예: SQUAREBOOK_HC). BookSpecs API로 조회 |
creationType | string | O | "PDF_UPLOAD" 또는 "MIX_COVER_TEMPLATE". 그 외 값은 400 에러 |
pageCount | integer | O | 내지 페이지 수. PDF 방식은 필수. 업로드할 내지 PDF의 실제 페이지 수와 정확히 일치해야 함 (불일치 시 내지 업로드 단계에서 400) |
specProfileUid | string | — | SpecProfile UID (선택, 일반적으로 미사용). 사용자별 판형 프로파일이 사전 등록된 경우에만 사용. 제공 시 해당 프로필과 연결, 유효하지 않으면 400 |
externalRef | string | — | 파트너 외부 참조 식별자 (최대 100자). 파트너 시스템의 고유 ID 매핑용 |
bookUid를 사용해 표지·내지 PDF 업로드와 최종화를 순차적으로 진행해야 주문 가능한 상태(finalized)가 됩니다.POST /books는 Idempotency-Key 헤더를 지원합니다. 동일한 키로 재요청해도 책이 중복 생성되지 않으므로, 네트워크 오류 등 재시도 상황에 활용하세요. 재시도가 캐시된 응답으로 처리된 경우 응답 헤더에 X-Idempotent-Replayed: true가 포함됩니다. 자세한 동작은 멱등성 가이드를 참고하세요.Request 예시
{
"title": "PDF 업로드 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"creationType": "PDF_UPLOAD",
"pageCount": 24,
"externalRef": "PARTNER-ORDER-001"
}{
"title": "혼합 방식 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"creationType": "MIX_COVER_TEMPLATE",
"pageCount": 24,
"externalRef": "PARTNER-ORDER-002"
}curl -X POST 'https://api-sandbox.sweetbook.com/v1/books' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-H 'Idempotency-Key: unique-request-id-001' \
-H 'Content-Type: application/json' \
-d '{
"title": "PDF 업로드 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"creationType": "PDF_UPLOAD",
"pageCount": 24,
"externalRef": "PARTNER-ORDER-001"
}'응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
bookUid | string | 생성된 책의 UID |
pageMeta | object | 페이지 제약 메타. currentPageCount·pageMin·pageMax·pageIncrement·isValid 5개 필드 |
Response 예시
{
"success": true,
"message": "책 생성 완료",
"data": {
"bookUid": "bk_2h4L********",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
}
}
}pageMeta: PDF_UPLOAD·MIX_COVER_TEMPLATE 방식은 책 생성 시 pageCount를 입력받으므로 currentPageCount가 입력값과 동일하게 설정됩니다(예: pageCount: 24 → currentPageCount: 24). TEMPLATE 방식은 0으로 초기화됩니다. isValid는 pageMin ≤ currentPageCount ≤ pageMax 및 증분 규칙 만족 여부를 나타내며, 페이지 제약만 판정하고 표지·내지 PDF 업로드 여부는 별도입니다.
HTTP 상태 코드
| 코드 | errorCode | 설명 |
|---|---|---|
| 201 Created | — | 책 생성 성공 |
| 400 Bad Request | ERR_VALIDATION_FAILED | title/bookSpecUid/creationType 누락 또는 허용되지 않은 값, PDF 방식인데 pageCount 누락, 잘못된 specProfileUid 등 |
| 401 Unauthorized | ERR_UNAUTHORIZED | 인증 실패 |
| 422 Unprocessable Entity | ERR_IDEMPOTENCY_KEY_MISMATCH | 같은 Idempotency-Key로 다른 본문 전송 |
| 429 Too Many Requests | ERR_TOO_MANY_REQUESTS | 요청 빈도 제한 초과 — Rate Limiting 가이드 참고 |
| 500 Internal Server Error | ERR_INTERNAL_ERROR | 서버 오류 |
본 엔드포인트의 주요 검증 실패 메시지(400 ERR_VALIDATION_FAILED):
creationType누락 또는 허용되지 않은 값 —errors[0]:"유효하지 않은 creationType: <값> (허용: TEMPLATE, PDF_UPLOAD, MIX_COVER_TEMPLATE)"- PDF 방식(
PDF_UPLOAD·MIX_COVER_TEMPLATE)인데pageCount누락 —errors[0]:"creation_type=<값>는 pageCount(내지 페이지수)가 필수입니다."
응답 6필드 shape, 다른 errorCode, 처리 가이드는 에러 코드 & 트러블슈팅을 참조하세요.
PDF 파일 요건
표지·내지 PDF 업로드 시 PDF 형식·크기·페이지 수가 동기 검증됩니다. 업로드 단계에서 차단되는 항목(hard fail)과 업로드는 성공하지만 주문 단계에서 차단되는 항목(soft warning)이 구분됩니다. 업로드 전에 아래 요건을 충족하는지 확인하세요.
판형별 PDF 규격
정확한 PDF 규격(너비·높이 mm)은 판형(BookSpec)마다 다릅니다. 구조는 커버 타입(소프트/하드)에 따라 다음과 같이 분기되며, 실제 값은 GET /book-specs 또는 파트너 포털에서 확인하세요.
| 커버 타입 | 표지 규격 구조 | 내지 규격 구조 |
|---|---|---|
| 소프트커버 | 고정 크기 단일 객체 (책등 두께 무관) | 고정 크기 |
| 하드커버 | 페이지 수 범위별 배열 — 책등 두께에 따라 너비 가변 | 고정 크기 |
허용 오차
허용 오차는 판형의 pdfSize 정의값을 기준으로 적용됩니다. 대부분의 판형은 정의값과 정확히 일치(오차 0mm)하도록 설정되어 있습니다. 안전한 인쇄 품질을 위해 PDF 제작 시 다음 권고 마진 내로 제작하는 것을 권장합니다.
| 항목 | 권고 마진 (제작 시) |
|---|---|
| 소프트커버 표지 (너비·높이) | ±1mm 이내 |
| 하드커버 표지 너비 | ±2mm 이내 (책등 두께 보정 여유) |
| 하드커버 표지 높이 | ±1mm 이내 |
| 내지 (너비·높이) | ±1mm 이내 |
실제 허용치는 판형마다 다를 수 있습니다. 정의값 정확 일치를 목표로 제작하되, 위 권고 마진 내라면 일반적으로 안전합니다. 검증 실패 시 응답의 errors 배열에 실제 측정값과 허용 규격이 함께 표기됩니다.
공통 제약 (검증 실패 시 업로드 차단 — Hard Fail)
- 파일 형식: PDF (시그니처
%PDF-확인) - 파일 크기: 500MB 이하 (요청 크기 제한과 동일)
- PDF 구조 무결성: 손상되거나 파싱 불가능한 PDF는 차단
- 표지 페이지 수: 1페이지 고정
- 내지 페이지 수: 책 생성 시 지정한
pageCount와 정확히 일치 - PDF 크기(mm): 위 표의 권고 마진 내
페이지 수 권장 사항 (업로드는 성공, 주문 시 차단 — Soft Warning)
책 생성 시 지정한 pageCount가 판형의 페이지 규칙을 벗어나도 PDF 업로드 자체는 성공합니다. 응답의 warnings 배열에 경고가 포함되며, 주문 생성 시 400 에러로 차단됩니다.
| 규칙 | 설명 | 참고 (SQUAREBOOK_HC) |
|---|---|---|
| 페이지 수 범위 | pageCount가 판형의 pageMin ~ pageMax 사이 | 24 ~ 130 |
| 페이지 수 배수 | pageCount가 pageIncrement의 배수 | 2의 배수 (24, 26, 28, …) |
예를 들어 SQUAREBOOK_HC에서 pageCount=23으로 책을 생성하면 23p PDF 업로드는 성공하지만,pageIncrement=2의 배수가 아니므로 주문 단계에서 거부됩니다. 책 생성 시점부터 판형 범위 내·배수 조건을 충족하도록 지정하세요.
{
"cover": [
{ "minPage": 24, "maxPage": 64, "width": 544, "height": 288 },
{ "minPage": 65, "maxPage": 130, "width": 550, "height": 288 }
],
"inner": { "width": 249, "height": 254 }
}{
"cover": { "width": 332, "height": 216 },
"inner": { "width": 148, "height": 210 }
}400 ERR_VALIDATION_FAILED: PDF 규격 검증 실패 시 errors 배열에 위반 항목이 모두 포함됩니다 (예: "내지 PDF 페이지수 불일치: 올바른 페이지수 24p, 업로드된 페이지수 30p", "PDF 너비 불일치: 실제 148.0mm, 허용 규격 249mm (+/-1mm)", "PDF 높이 불일치: 실제 210.0mm, 허용 규격 254.0mm (+/-1mm)"). LAYFLAT 제본은 페이지수 메시지에 책 페이지 환산값이 괄호로 부가됩니다(예: "... (책 페이지 환산: 올바른 페이지수 16p, 업로드된 페이지수 20p)"). 응답 shape 상세는 에러 코드 & 트러블슈팅 — ERR_VALIDATION_FAILED를 참조하세요.
표지 PDF
표지 PDF는 1페이지 고정입니다. 신규 등록(POST), 교체(PUT), 다운로드(GET) 세 가지 엔드포인트를 제공합니다. 업로드/교체 동작은 동일한 검증을 거치며 응답 본문 구조도 같습니다 (HTTP 상태 코드와 메시지만 다름).
creationType="MIX_COVER_TEMPLATE" 책의 표지는 PDF가 아닌 템플릿으로 생성됩니다. 해당 책에 PDF 표지 업로드 시도 시 400 에러가 반환됩니다. 표지는 Books — 템플릿 기반의 POST /books/{bookUid}/cover를 사용하세요.공통 응답 필드 (POST · PUT)
| 필드 | 타입 | 설명 |
|---|---|---|
bookUid | string | 대상 책 UID |
kind | string | "cover" 고정 |
valid | boolean | 검증 성공 여부 (성공 시 true) |
pageMeta | object | 책의 페이지 제약 메타. currentPageCount·pageMin·pageMax·pageIncrement·isValid 5필드 (v1.2 C04에서 pageCount 정수 필드 대체). 표지 PDF는 1페이지 고정이므로 본 응답에서는 책의 페이지 제약을 반환합니다. |
pdfSizeMm | object | { width, height } mm 단위 측정값 |
messages | array | 검증 실패 시 에러 메시지 (성공 시 빈 배열) |
warnings | array | 경고 메시지 (표지는 일반적으로 비어있음, 내지에 주로 사용) |
bookStatus | integer | null | 현재 책 상태 (정수). 1(DRAFT, 작성 중) / 2(FINALIZED, 최종화 완료). 검증 실패 시 null이 반환될 수 있습니다. 책 목록 조회(GET /books) 응답의 status 필드는 같은 값을 문자열(draft/finalized)로 반환합니다. 표지·내지 PDF 업로드 후 POST /books/{bookUid}/finalization을 호출하면 1 → 2로 전환됩니다 |
url | string | null | 업로드된 PDF 다운로드 URL (검증 성공 시만 채움, 실패 시 null). 호출 도메인(api-sandbox / api)을 기준으로 자동 결정됨 |
HTTP 상태 코드 (POST · PUT 공통)
| 코드 | POST 신규 | PUT 교체 |
|---|---|---|
| 200 OK | — | 교체 성공 |
| 201 Created | 등록 성공 | — |
| 400 Bad Request | PDF 검증 실패, 잘못된 creationType, 제작 확정된 주문 존재(PUT) | |
| 401 Unauthorized | 인증 실패 (ERR_UNAUTHORIZED) | |
| 403 Forbidden | 본인 소유가 아닌 책 (ERR_FORBIDDEN) / Sandbox 도메인에서 Live 책 또는 그 반대 (ERR_ENV_MISMATCH) — 아래 케이스 박스 참고 | |
| 404 Not Found | — | 교체 대상 표지 PDF가 등록되어 있지 않음 |
| 409 Conflict | 이미 표지 PDF가 등록되어 있음 | — |
| 429 Too Many Requests | 업로드 Rate Limit 초과 — Rate Limiting 가이드 참고 | |
| 500 Internal Server Error | 서버 오류 | |
isTest 값(true=Sandbox / false=Live)과 호출 도메인이 일치해야 합니다.{ "success": false, "message": "Invalid Operation", "errors": ["환경 불일치: 이 책은 sandbox 환경에서 생성되었습니다. sandbox 도메인에서 호출하세요."] }표지 PDF 신규 등록
/books/{bookUid}/pdf-cover표지 PDF를 최초로 등록합니다. 이미 등록된 상태에서 호출하면 409 Conflict가 반환되며, 이 경우 PUT으로 교체해야 합니다. 검증은 동기로 수행되어 응답 본문에 결과가 포함됩니다.
Request — multipart/form-data
| 필드 | 위치 | 타입 | 필수 | 설명 |
|---|---|---|---|---|
bookUid | path | string | O | 대상 책 UID |
file | form-data | file (application/pdf) | O | 표지 PDF 파일 (1페이지 고정) |
업로드 Rate Limit은 upload 정책(API Key 단위 200 req/분)이 적용됩니다. Rate Limiting 가이드 참고.
Request 예시
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-cover' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'file=@hardcover24.pdf;type=application/pdf'Response 예시
{
"success": true,
"message": "cover PDF가 저장되었습니다",
"data": {
"bookUid": "bk_2h4L********",
"kind": "cover",
"valid": true,
"pdfSizeMm": { "width": 544, "height": 288 },
"messages": [],
"warnings": [],
"bookStatus": 1,
"url": "https://api-sandbox.sweetbook.com/v1/books/bk_2h4L********/pdf-cover",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
}
}
}409 ERR_CONFLICT: 이미 등록된 표지에 POST 재호출 시 — errors[0]: "표지 PDF가 이미 등록되어 있습니다. 교체하려면 PUT 메서드를 사용하세요." 응답 shape 상세는 에러 코드 & 트러블슈팅 — ERR_CONFLICT를 참조하세요.
표지 PDF 교체
/books/{bookUid}/pdf-cover이미 등록된 표지 PDF를 교체합니다. 등록되지 않은 상태에서 호출하면 404가 반환되며, 이 경우 POST로 신규 등록해야 합니다.
Request — multipart/form-data
신규 등록(POST)과 동일한 파라미터를 사용합니다.
Request 예시
curl -X PUT 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-cover' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'file=@hardcover24-v2.pdf;type=application/pdf'Response 예시
{
"success": true,
"message": "cover PDF가 교체되었습니다",
"data": {
"bookUid": "bk_krW7********",
"kind": "cover",
"valid": true,
"pdfSizeMm": { "width": 544, "height": 288 },
"messages": [],
"warnings": [],
"bookStatus": 1,
"url": "https://api-sandbox.sweetbook.com/v1/books/bk_krW7********/pdf-cover",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
}
}
}주요 에러: 404 ERR_NOT_FOUND 등록되지 않은 상태에서 PUT 호출 (errors[0]: "표지 PDF가 등록되어 있지 않습니다. 신규 등록은 POST 메서드를 사용하세요.") · 400 ERR_VALIDATION_FAILED 제작 확정 이후 교체 시도 (errors[0]: "제작 확정된 주문이 있어 PDF 교체가 불가합니다."). 응답 shape 상세는 에러 코드 & 트러블슈팅을 참조하세요.
표지 PDF 다운로드
/books/{bookUid}/pdf-cover저장된 표지 PDF를 다운로드합니다. 정상 응답은 JSON이 아닌 application/pdf 바이너리 스트림입니다.
creationType에 따라 분기됩니다.- PDF_UPLOAD (그룹 A — 사용자 업로드): 업로드된 파일 존재 여부만 검사. 파일이 있으면 200, 없으면 404.
- MIX_COVER_TEMPLATE (그룹 B — 백그라운드 생성): 책 최종화 후 백엔드가 표지를 PDF로 렌더링.
pdfStatus에 따라 200 / 409 / 422 / 500 분기.
응답 매트릭스
그룹 A — PDF_UPLOAD 책의 표지
| 파일 상태 | HTTP | 응답 형식 | errorCode |
|---|---|---|---|
| 디스크에 존재 | 200 | application/pdf 바이너리 스트림 | — |
| 디스크에 부재 (업로드 미완) | 404 | JSON | ERR_PDF_NOT_UPLOADED |
그룹 B — MIX_COVER_TEMPLATE 책의 표지
| 책 상태 | HTTP | 응답 형식 | errorCode |
|---|---|---|---|
| 책 최종화 전 (PDF 생성 미시작) | 409 | JSON | ERR_PDF_NOT_GENERATED |
| PDF 생성 진행 중 | 409 | JSON | ERR_PDF_PENDING |
| PDF 생성 실패 | 422 | JSON | ERR_PDF_GENERATION_FAILED |
| 생성 완료 + 파일 부재 (서버 결함) | 500 | JSON | ERR_PDF_FILE_MISSING |
| 생성 완료 + 파일 존재 | 200 | application/pdf 바이너리 스트림 | — |
공통 사전 검증
| 케이스 | HTTP | errorCode |
|---|---|---|
| 책 미존재 | 404 | ERR_NOT_FOUND |
| 본인 소유가 아닌 책 | 403 | ERR_FORBIDDEN |
| 환경 불일치 (Sandbox/Live 도메인 ↔ 책의 환경 불일치) | 403 | ERR_ENV_MISMATCH |
kind 경로 오류 (/pdf-cover·/pdf-contents 외 호출) | 400 | ERR_MALFORMED_REQUEST |
책의 creationType이 PDF 조회를 지원하지 않음 | 400 | ERR_CREATION_TYPE_UNSUPPORTED |
클라이언트 권장 행동
ERR_PDF_NOT_UPLOADED(그룹 A): 해당 kind의 PDF를 업로드.ERR_PDF_NOT_GENERATED(그룹 B):POST /books/{bookUid}/finalization호출 후 재시도.ERR_PDF_PENDING(그룹 B): 일정 간격(예: 10초~수십 초) 후 재시도. 무한 폴링 금지. 본 응답에는Retry-After헤더가 포함되지 않으므로 클라이언트가 자체 대기 간격을 결정해야 합니다.ERR_PDF_GENERATION_FAILED(그룹 B): 클라이언트 자체 해결 불가 — 사용자에게 실패 안내 + 고객지원팀 문의.ERR_PDF_FILE_MISSING(그룹 B): 서버 측 결함 — 고객지원팀 문의.
URL은 응답 본문이 아닌 표지 업로드 응답의 data.url 필드를 통해 확인할 수 있으며, 호출 도메인(api-sandbox.sweetbook.com / api.sweetbook.com)이 자동 적용됩니다.
Request 예시
curl -o cover.pdf \
'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-cover' \
-H 'Authorization: Bearer {YOUR_API_KEY}'출처별 errorCode 분기: creationType에 따라 그룹 A(PDF_UPLOAD·MIX 내지 — 404 ERR_PDF_NOT_UPLOADED) / 그룹 B(TEMPLATE·MIX 표지 — 409 ERR_PDF_NOT_GENERATED·ERR_PDF_PENDING·422 ERR_PDF_GENERATION_FAILED·500 ERR_PDF_FILE_MISSING). 응답 예시·처리 가이드는 에러 코드 & 트러블슈팅 — PDF 다운로드 분기를 참조하세요.
내지 PDF
내지 PDF는 책 생성 시 지정한 pageCount와 페이지 수가 정확히 일치해야 합니다. 표지와 마찬가지로 신규 등록(POST), 교체(PUT), 다운로드(GET) 세 엔드포인트를 제공하며, 응답 본문 구조는 표지와 동일합니다.
creationType="MIX_COVER_TEMPLATE" 책의 내지는 PDF 업로드를 사용합니다 (표지는 템플릿). 따라서 이 섹션의 내지 엔드포인트는 PDF_UPLOAD·MIX_COVER_TEMPLATE 두 방식 모두에서 사용됩니다.공통 응답 필드 (POST · PUT)
구조는 표지 PDF의 공통 응답 필드와 동일합니다 (bookUid / kind / valid / pageMeta / pdfSizeMm / messages / warnings / bookStatus / url). 내지의 경우 kind 값이 "contents"이고, 업로드 PDF의 페이지 수는 책 생성 시 지정한 pageCount와 정확히 일치해야 합니다 (불일치 시 400).
HTTP 상태 코드 (POST · PUT 공통)
표지와 동일합니다. POST 신규는 201 Created (이미 등록 시 409), PUT 교체는 200 OK (미등록 시 404, 제작 확정 후 400).환경(Sandbox/Live) 불일치 시 400도 표지와 동일하게 적용됩니다 — 표지 섹션의 환경 불일치 안내 박스를 참고하세요.
내지 PDF 신규 등록
/books/{bookUid}/pdf-contents내지 PDF를 최초로 등록합니다. 책 생성 시 지정한 pageCount와 PDF의 실제 페이지 수가 정확히 일치하지 않으면 400으로 차단됩니다.
Request — multipart/form-data
| 필드 | 위치 | 타입 | 필수 | 설명 |
|---|---|---|---|---|
bookUid | path | string | O | 대상 책 UID |
file | form-data | file (application/pdf) | O | 내지 PDF 파일 (페이지 수 = 책의 pageCount) |
경고(warnings) 발생 조건 — 업로드는 성공, 주문 시 차단
업로드 자체는 성공하지만 응답의 warnings 배열에 메시지가 포함되며, 이후 주문 생성 시 400으로 차단됩니다.
- 페이지 수가 판형의
pageMin미만 - 페이지 수가 판형의
pageMax초과 - 페이지 수가 판형의
pageIncrement의 배수가 아님
Request 예시
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-contents' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'file=@hardcontents24.pdf;type=application/pdf'Response 예시
{
"success": true,
"message": "contents PDF가 저장되었습니다",
"data": {
"bookUid": "bk_2h4L********",
"kind": "contents",
"valid": true,
"pdfSizeMm": { "width": 249, "height": 254 },
"messages": [],
"warnings": [],
"bookStatus": 1,
"url": "https://api-sandbox.sweetbook.com/v1/books/bk_2h4L********/pdf-contents",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
}
}
}pageMeta.currentPageCount는 내지 PDF 실제 페이지 수를 반영합니다. 기존 pageCount 필드는 v1.2에서 제거됐으며 pageMeta.currentPageCount로 대체됐습니다.
주요 에러: 400 ERR_VALIDATION_FAILED 페이지 수 불일치 (errors[0]: "내지 PDF 페이지수 불일치: 올바른 페이지수 24p, 업로드된 페이지수 30p". LAYFLAT 제본은 책 페이지 환산값이 괄호로 부가) · 409 ERR_CONFLICT 이미 등록됨 (errors[0]: "내지 PDF가 이미 등록되어 있습니다. 교체하려면 PUT 메서드를 사용하세요."). 응답 shape 상세는 에러 코드 & 트러블슈팅을 참조하세요.
내지 PDF 교체
/books/{bookUid}/pdf-contents등록된 내지 PDF를 교체합니다. 표지 교체와 동일하게 제작 확정(CONFIRMED) 이후에는 차단됩니다. 교체 시에도 책 생성 시 지정한 pageCount와 일치해야 합니다 (책의 pageCount는 변경되지 않음).
pageCount를 변경해야 합니다. 그러나 pageCount는 책 생성 시 확정되며 이후 수정 API가 제공되지 않습니다 — 페이지 수가 다른 책은 새로 생성하세요.Request — multipart/form-data
신규 등록(POST)과 동일한 파라미터를 사용합니다.
Request 예시
curl -X PUT 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-contents' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'file=@hardcontents24-v2.pdf;type=application/pdf'Response 예시
{
"success": true,
"message": "contents PDF가 교체되었습니다",
"data": {
"bookUid": "bk_2h4L********",
"kind": "contents",
"valid": true,
"pdfSizeMm": { "width": 249, "height": 254 },
"messages": [],
"warnings": [],
"bookStatus": 1,
"url": "https://api-sandbox.sweetbook.com/v1/books/bk_2h4L********/pdf-contents",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
}
}
}404 ERR_NOT_FOUND: 등록되지 않은 상태에서 PUT 호출 — errors[0]: "내지 PDF가 등록되어 있지 않습니다. 신규 등록은 POST 메서드를 사용하세요." 응답 shape 상세는 에러 코드 & 트러블슈팅 — ERR_NOT_FOUND를 참조하세요.
내지 PDF 다운로드
/books/{bookUid}/pdf-contents저장된 내지 PDF를 다운로드합니다. 정상 응답은 JSON이 아닌 application/pdf 바이너리 스트림입니다.
응답 매트릭스 (그룹 A)
| 파일 상태 | HTTP | 응답 형식 | errorCode |
|---|---|---|---|
| 디스크에 존재 | 200 | application/pdf 바이너리 스트림 | — |
| 디스크에 부재 (업로드 미완) | 404 | JSON | ERR_PDF_NOT_UPLOADED |
공통 사전 검증
| 케이스 | HTTP | errorCode |
|---|---|---|
| 책 미존재 | 404 | ERR_NOT_FOUND |
| 본인 소유가 아닌 책 | 403 | ERR_FORBIDDEN |
| 환경 불일치 | 403 | ERR_ENV_MISMATCH |
| kind 경로 오류 | 400 | ERR_MALFORMED_REQUEST |
책의 creationType이 PDF 조회를 지원하지 않음 | 400 | ERR_CREATION_TYPE_UNSUPPORTED |
Request 예시
curl -o contents.pdf \
'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/pdf-contents' \
-H 'Authorization: Bearer {YOUR_API_KEY}'404 ERR_PDF_NOT_UPLOADED: 내지 PDF 미업로드 (그룹 A) — errors[0]: "PDF 파일이 업로드되지 않았습니다." 응답 shape·다른 errorCode·처리 가이드는 에러 코드 & 트러블슈팅 — ERR_PDF_NOT_UPLOADED를 참조하세요.
책 최종화
/books/{bookUid}/finalization표지·내지 PDF 업로드를 마친 뒤 이 엔드포인트를 호출해 책을 최종화합니다. 호출 시 책의 status가 draft에서 finalized로 전환되어 주문 가능 상태가 됩니다.
전환 결과: 호출 성공 시
status가 draft → finalized로, pdfStatus가 null → 2(COMPLETED)로 전환됩니다.PAID(20) 단계를 거치지 않고 즉시 PDF_READY(25)로 진입합니다. 자세한 주문 상태 흐름은 주문 상태 흐름을 참고하세요.Request
요청 본문은 비어 있습니다. 다만 IIS 환경 특성상 Content-Length: 0 헤더가 필요합니다 (없으면 411 Length Required).
Request 예시
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/finalization' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-H 'Content-Length: 0'응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
result | string | 처리 결과. "created"(첫 finalize 성공) / "updated"(이미 finalized 상태에서 멱등 응답) |
pageMeta | object | 페이지 제약 메타. currentPageCount(책의 내지 페이지 수, PDF 방식은 책 생성 시 지정한 값과 동일) + pageMin·pageMax·pageIncrement·isValid 필드 포함 |
finalizedAt | datetime | 최종화 완료 시각 (ISO 8601) |
이미 FINALIZED 상태에서 다시 호출하면 200 OK + message: "이미 최종화된 책입니다" + result: "updated"로 멱등 응답합니다 (실제 상태 재변경은 일어나지 않음).
Response 예시
{
"success": true,
"message": "책 최종화 완료",
"data": {
"result": "created",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
},
"finalizedAt": "2026-04-22T07:46:24.099Z"
}
}{
"success": true,
"message": "이미 최종화된 책입니다",
"data": {
"result": "updated",
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
},
"finalizedAt": "2026-04-22T07:46:24.099Z"
}
}전제조건별 에러코드 매핑
finalize 호출 시 전제조건을 충족하지 못하면 아래 표대로 errorCode + fieldErrors가 반환됩니다. 클라이언트는 fieldErrors[].field·fieldErrors[].constraint로 누락 항목을 식별해 사용자에게 안내하세요.
| 전제조건 | errorCode | fieldErrors[].field | constraint |
|---|---|---|---|
| 책이 DRAFT 상태가 아님 (공통) | ERR_FINALIZE_PREREQ_UNMET | status | enum |
표지 PDF 미업로드 (PDF_UPLOAD 전용) | ERR_FINALIZE_PREREQ_UNMET | coverPdf | required |
내지 PDF 미업로드 (PDF_UPLOAD · MIX_COVER_TEMPLATE 공통) | ERR_FINALIZE_PREREQ_UNMET | contentsPdf | required |
페이지 수 < pageMin | ERR_INSUFFICIENT_PAGES | pageCount | min |
페이지 수 > pageMax | ERR_PAGECOUNT_INVALID | pageCount | max |
| 페이지 증분 규칙 위반 | ERR_PAGECOUNT_INVALID | pageCount | increment |
여러 전제조건이 동시에 깨지면 fieldErrors에 항목들이 함께 반환됩니다(예: 표지·내지 PDF 둘 다 없으면 두 항목 모두 포함). 응답 예시는 위 페이지 제약 위반 에러 섹션과 케이스 C(ERR_FINALIZE_PREREQ_UNMET 다중 필드)를 참조하세요.
pageMeta.isValid 사용 시 주의:isValid는 페이지 수 제약(pageMin·pageMax·pageIncrement)만 판정합니다.- 표지·내지 PDF 업로드 여부, 책 상태(DRAFT 여부) 등 다른 전제조건은 finalize 호출 시 별도로 검증되므로
isValid: true여도ERR_FINALIZE_PREREQ_UNMET이 반환될 수 있습니다. - finalize 가능 여부 최종 확정은
POST /finalization호출 결과로만 가능합니다.isValid는 사전 UI 안내(예: "아직 N페이지 부족") 용도로만 사용하세요.
HTTP 상태 코드
| 코드 | errorCode | 설명 |
|---|---|---|
| 200 OK | — | 이미 finalized 상태의 책에 재호출한 경우 (멱등 응답, message: "이미 최종화된 책입니다", result: "updated") |
| 201 Created | — | 최종화 신규 성공 |
| 400 Bad Request | ERR_FINALIZE_PREREQ_UNMET / ERR_INSUFFICIENT_PAGES / ERR_PAGECOUNT_INVALID | 전제조건 미충족 (위 매핑 표 참고) |
| 401 Unauthorized | ERR_UNAUTHORIZED | 인증 실패 |
| 404 Not Found | ERR_NOT_FOUND | 책 없음 |
| 411 Length Required | — | Content-Length: 0 헤더 누락 |
| 500 Internal Server Error | ERR_INTERNAL_ERROR | 서버 오류 |
book.pdfStatus 값
책 조회(GET /books) 응답에 포함되는 pdfStatus 필드는 PDF 처리 상태를 나타내는 정수값입니다. 파트너는 일반적으로 책의 status 필드만 참조하면 충분하며, pdfStatus는 PDF 준비 완료 여부를 직접 확인하고 싶을 때 부가 정보로 활용할 수 있습니다.
| 값 | 의미 | 발생 시점 |
|---|---|---|
null | 미생성/미업로드 (초기 상태) | 책 생성 직후 또는 표지·내지 PDF만 업로드한 상태 (finalize 미호출) |
2 | COMPLETED (PDF 준비 완료) | finalize 호출 후. PDF 방식은 즉시 2로 전환됨 |
9 | FAILED (처리 실패) | 처리 실패 시. PDF 방식에서는 일반적으로 발생하지 않음 (사용자가 PDF를 직접 제공하므로 렌더링 실패 경로가 없음) |
400 ERR_FINALIZE_PREREQ_UNMET: 표지/내지 PDF 미업로드 등 전제조건 미충족. 위의 전제조건별 에러코드 매핑 표가 정확한 매핑을 제공하며, 표지만 업로드되고 내지가 없으면 fieldErrors에 contentsPdf만, 반대면 coverPdf만 포함됩니다. 응답 예시(다중 fieldErrors)와 처리 가이드는 에러 코드 & 트러블슈팅 — ERR_FINALIZE_PREREQ_UNMET를 참조하세요.
책 목록 조회
/books파트너가 생성한 책 목록을 조회합니다. 다양한 쿼리 파라미터로 필터링할 수 있으며, 페이지네이션을 지원합니다. 응답에는 PDF 방식·템플릿 방식 책이 모두 포함되며, creationType 필드로 구분할 수 있습니다.
Query 파라미터
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
bookUid | string | — | 특정 책 UID로 단건 조회 |
status | string | — | 책 상태 필터. draft / finalized / deleted(일반 파트너 조회 결과에서는 삭제된 책이 자동 제외되므로 빈 결과) |
pdfStatus | string | — | PDF 상태 필터. 숫자 값(2 COMPLETED / 9 FAILED) 또는 null 문자열(PDF 미생성 책) 허용. PDF 방식 책 중 finalize 완료된 것만 조회 시 pdfStatus=2(COMPLETED) 활용 |
specProfileUid | string | — | SpecProfile UID로 필터 |
createdFrom | string | — | 생성일 시작 (ISO 8601, 예: 2026-01-01) |
createdTo | string | — | 생성일 종료 (ISO 8601) |
limit | integer | 20 | 조회할 항목 수 (1~100) |
offset | integer | 0 | 건너뛸 항목 수 (≥0) |
페이지네이션 동작과 응답 구조(data.books 배열 + data.pagination 객체)는 페이지네이션 가이드를 참고하세요.
Request 예시
curl -X GET 'https://api-sandbox.sweetbook.com/v1/books?limit=5' \
-H 'Authorization: Bearer {YOUR_API_KEY}'curl -X GET 'https://api-sandbox.sweetbook.com/v1/books?status=finalized&pdfStatus=2&limit=20' \
-H 'Authorization: Bearer {YOUR_API_KEY}'응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
bookUid | string | 책 고유 UID |
accountUid | string | 책 소유 계정 UID |
title | string | 책 제목 |
author | string | null | 저자명 (선택) |
status | string | 책 상태 — enum 문자열로 반환. "draft"(작성 중, 내부값 1) / "finalized"(최종화 완료, 내부값 2) / "deleted"(삭제됨, 내부값 9). PDF 업로드 응답의 bookStatus는 같은 값을 정수로 반환합니다 |
pageCount | integer | 내지 페이지 수 (PDF 방식은 책 생성 시 지정한 값, TEMPLATE은 자동 계산) |
bookSpecUid | string | 판형 UID |
specProfileUid | string | null | SpecProfile UID |
creationType | string | TEMPLATE / PDF_UPLOAD / MIX_COVER_TEMPLATE |
createdAt | datetime | 책 생성 시각 (ISO 8601) |
updatedAt | datetime | 마지막 수정 시각 |
externalRef | string | null | 파트너 외부 참조 식별자 |
isTest | boolean | Sandbox 환경 책 여부 |
pdfStatus | integer | null | PDF 처리 상태 (정수). null(미생성) / 2(COMPLETED, 준비 완료) / 9(FAILED, 실패). 자세한 의미는 위 책 최종화 → book.pdfStatus 값 표 참고 |
pdfCreatedAt | datetime | null | PDF 파일이 마지막으로 갱신된 시각 (업로드/교체/finalize 시 갱신) |
pdfRequestedAt | datetime | null | PDF 요청 시각 (PDF 방식은 일반적으로 null) |
thumbnailStatus | integer | null | 책 페이지 썸네일 처리 상태. null(NONE, 미생성) / 1(PENDING, 생성 진행 중) / 2(COMPLETED, 생성 완료) / 9(FAILED, 생성 실패) |
Response 예시
{
"success": true,
"message": "성공",
"data": [
{
"bookUid": "bk_2h4L********",
"accountUid": "u_b4b9********************",
"title": "PDF 업로드 샘플",
"author": null,
"status": "finalized",
"pageCount": 24,
"bookSpecUid": "SQUAREBOOK_HC",
"specProfileUid": null,
"creationType": "PDF_UPLOAD",
"createdAt": "2026-04-22T07:45:05.759Z",
"updatedAt": "2026-04-22T07:46:24.099Z",
"externalRef": "PARTNER-ORDER-001",
"isTest": true,
"pdfStatus": 2,
"pdfCreatedAt": "2026-04-22T07:46:24.000Z",
"pdfRequestedAt": null,
"thumbnailStatus": null
},
{
"bookUid": "bk_5EdC********",
"title": "DRAFT 상태 PDF 책",
"status": "draft",
"creationType": "PDF_UPLOAD",
"pageCount": 24,
"pdfStatus": null,
"pdfCreatedAt": null
/* ... 나머지 필드 생략 ... */
}
],
"pagination": {
"total": 15,
"limit": 5,
"offset": 0,
"hasNext": true
}
}HTTP 상태 코드
| 코드 | 설명 |
|---|---|
| 200 OK | 조회 성공 |
| 400 Bad Request | limit/offset 범위 위반 등 파라미터 오류 |
| 401 Unauthorized | 인증 실패 |
| 500 Internal Server Error | 서버 오류 |
책 단건 조회
/books/{bookUid}특정 책의 상세 정보를 조회합니다. v1.2에 신설된 RESTful 단건 조회 엔드포인트로, 편집 화면 진입이나 현재 페이지 수 제약 확인에 사용합니다. 응답에 pageMeta가 포함되어 "아직 N페이지 부족" 같은 힌트를 UI에 즉시 반영할 수 있습니다.
Path 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
bookUid | string | O | 조회할 책 UID |
Request 예시
curl -X GET 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}' \
-H 'Authorization: Bearer {YOUR_API_KEY}'응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
bookUid | string | 책 UID |
accountUid | string | 책을 생성한 계정의 UID (파트너 본인 계정) |
title | string | 책 제목 |
bookSpecUid | string | 책 규격 UID |
bookSpecName | string | 규격 이름 (예: "A5 소프트커버 포토북") |
specProfileUid | string | null | SpecProfile UID (사용 시) |
creationType | string | TEMPLATE / PDF_UPLOAD / MIX_COVER_TEMPLATE |
status | integer | 1=작성 중(DRAFT) / 2=최종화 완료(FINALIZED). status가 1인 책은 주문을 생성할 수 없으며, POST /books/{bookUid}/finalization을 호출해 2로 전이해야 합니다. 목록 조회(GET /books)는 동일 값을 문자열("draft" / "finalized")로 반환합니다 |
coverTemplateUid | string | null | 템플릿 방식에서 바인딩된 표지 템플릿 UID. PDF 방식은 null |
externalRef | string | null | 파트너 외부 참조 식별자 |
isTest | boolean | Sandbox 환경의 책이면 true |
pageMeta | object | 페이지 제약 메타. currentPageCount·pageMin·pageMax·pageIncrement·isValid 5개 필드 |
createdAt | datetime | 생성 시각 (ISO 8601) |
updatedAt | datetime | 최종 수정 시각 (ISO 8601) |
Response 예시
{
"success": true,
"message": "성공",
"data": {
"bookUid": "bk_2h4L********",
"accountUid": "u_b4b9********************",
"title": "PDF 업로드 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"bookSpecName": "고화질 스퀘어북 (하드커버)",
"specProfileUid": null,
"creationType": "PDF_UPLOAD",
"status": 1,
"coverTemplateUid": null,
"externalRef": "PARTNER-ORDER-001",
"isTest": true,
"pageMeta": {
"currentPageCount": 24,
"pageMin": 24,
"pageMax": 200,
"pageIncrement": 2,
"isValid": true
},
"createdAt": "2026-04-22T03:00:00.000Z",
"updatedAt": "2026-04-22T04:00:00.000Z"
}
}HTTP 상태 코드
| 상태 코드 | errorCode | 설명 |
|---|---|---|
| 200 OK | — | 조회 성공 |
| 401 Unauthorized | ERR_UNAUTHORIZED | 인증 실패 |
| 403 Forbidden | ERR_FORBIDDEN | 다른 파트너의 책 접근 시도 |
| 403 Forbidden | ERR_ENV_MISMATCH | Sandbox 도메인에서 Live 책 조회(또는 반대) |
| 404 Not Found | ERR_NOT_FOUND | 책 UID가 존재하지 않음 |
단건 조회 vs 목록 조회 (bookUid 필터) 차이
기존 목록 조회의 bookUid 필터(GET /books?bookUid=...)와 본 단건 조회는 의미·응답 타입·권한 처리가 다릅니다. 용도에 맞게 선택하세요.
| 항목 | GET /books/{uid} (단건) | GET /books?bookUid=... (목록 필터) |
|---|---|---|
| 의미론 | RESTful 리소스 단건 조회 | 목록 조회 + bookUid 동등 필터 (결과 0~1건) |
응답 data 타입 | 객체 | 배열 + pagination 메타 |
| 응답 필드 | 상세 필드 + pageMeta, bookSpecName, coverTemplateUid 등 편집 화면용 풀셋 | 목록용 요약 필드 (pageCount 유지, pageMeta 없음) |
| 결과 없을 때 | 404 ERR_NOT_FOUND | 200 + 빈 배열 |
| 다른 파트너의 책 | 403 ERR_FORBIDDEN | 200 + 빈 배열 (필터 결과) |
| 환경 불일치 (sandbox/live) | 403 ERR_ENV_MISMATCH | 빈 배열 (필터에 환경 적용) |
status 필드 타입 | 숫자 (1/2) | 문자열 ("draft"/"finalized") |
| 주 용도 | 책 편집 페이지 진입, 상세 패널 렌더링, finalize 전 상태 확인 | 목록/검색 UI, 페이지네이션, 여러 조건 조합 필터링 |
- 책 UID를 알고 있고 상세 정보(특히
pageMeta)가 필요하면 → 단건 조회 - 존재 여부만 빠르게 확인하거나 여러 조건과 조합해야 하면 → 목록 조회
- 없는 책과 권한 없는 책을 명확히 구별해야 하면 → 단건 조회 (목록은 둘 다 빈 배열로 동일)
404 ERR_NOT_FOUND: 존재하지 않는 bookUid — errors[0]: "책을 찾을 수 없습니다: bk_xxx". 응답 shape 상세는 에러 코드 & 트러블슈팅 — ERR_NOT_FOUND를 참조하세요.
페이지 제약 위반 에러
내지 PDF 업로드·최종화·내지 템플릿 추가 시 페이지 제약을 위반하면 아래 3종 에러 중 하나가 반환됩니다. fieldErrors[0].constraint로 어떤 제약이 위반됐는지 분기할 수 있습니다. 전체 에러 체계 상세는 에러 코드 & 트러블슈팅을 참고하세요.
ERR_INSUFFICIENT_PAGES(constraint: "min") — 최소 페이지 미달ERR_PAGECOUNT_INVALID(constraint: "max") — 최대 페이지 초과ERR_PAGECOUNT_INVALID(constraint: "increment") — 증분 규칙 위반.requiredValue는{min, increment}객체 형태
응답 예시(fieldErrors 배열에 currentValue·requiredValue·constraint 포함)는 errors 페이지의 각 errorCode 카드를 참조하세요: ERR_INSUFFICIENT_PAGES, ERR_PAGECOUNT_INVALID.
책 삭제
/books/{bookUid}책을 삭제 처리합니다. 물리적 삭제가 아닌 소프트 삭제(상태값 변경)로 처리되어, 이후 목록 조회 결과에서 제외됩니다. 업로드한 PDF 파일은 별도 정리되지 않고 보관 상태로 남으며, 책 자체에 대한 추가 작업(업로드/교체/finalize/주문)은 모두 차단됩니다.
상태 제약 없음:
draft·finalized 어느 상태에서도 삭제 가능합니다 (단 본인 소유 책에 한함).Path 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
bookUid | string | O | 삭제할 책 UID |
Request 예시
curl -X DELETE 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}' \
-H 'Authorization: Bearer {YOUR_API_KEY}'응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
bookUid | string | 삭제된 책 UID |
status | string | 삭제 처리 결과 ("deleted") |
Response 예시
{
"success": true,
"message": "책이 삭제되었습니다",
"data": {
"bookUid": "bk_2h4L********",
"status": "deleted"
}
}HTTP 상태 코드
| 코드 | 설명 |
|---|---|
| 200 OK | 삭제 성공 (이미 삭제된 책에 대한 재호출 포함) |
| 400 Bad Request | bookUid 형식 오류 |
| 401 Unauthorized | 인증 실패 |
| 403 Forbidden | 본인 소유가 아닌 책 |
| 404 Not Found | 책 없음 |
| 500 Internal Server Error | 서버 오류 |
404 ERR_NOT_FOUND: 존재하지 않는 bookUid — 응답 shape 상세는 에러 코드 & 트러블슈팅 — ERR_NOT_FOUND를 참조하세요.