Books API
책 생성, 조회, 표지/내지 추가, 최종화 API 문서입니다.
Authorization: Bearer <API_KEY> 헤더로 제공하세요.책 생성
/v1/books새로운 책을 생성합니다. 초안(draft) 상태로 생성되며, 이후 표지와 콘텐츠를 추가할 수 있습니다.
Request Body
{
"title": "테스트책",
"bookSpecUid": "SQUAREBOOK_HC",
"specProfileUid": "sp_abc123xyz",
"creationType": "TEST",
"externalRef": "PARTNER-ORDER-001"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| title | string | Y | 책 제목 (1-255자) |
| bookSpecUid | string | Y | 상품 스펙 UID (예: SQUAREBOOK_HC) |
| specProfileUid | string | N | SpecProfile UID - 제공 시 해당 프로필과 연결. 유효하지 않으면 에러 반환 |
| creationType | string | N | 생성 방식 (TEST, TEMPLATE 등, 기본값: TEMPLATE) |
| externalRef | string | N | 파트너 외부 참조 식별자 (최대 100자). 파트너 시스템의 고유 ID를 저장하는 용도 |
Request 예시 (curl)
curl -X 'POST' \
'https://api.sweetbook.com/v1/books' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"title": "테스트책",
"bookSpecUid": "SQUAREBOOK_HC",
"creationType": "TEST"
}'Response (201 Created)
{
"success": true,
"message": "책 생성 완료",
"data": {
"bookUid": "bk_3dJTg8WOpR2e"
}
}/books/{bookUid}/cover 및 /books/{bookUid}/contents API로 콘텐츠를 추가해야 합니다.HTTP 상태 코드
| 상태 코드 | 설명 |
|---|---|
| 201 Created | 책 생성 성공 |
| 400 Bad Request | 잘못된 요청 (필드 누락, 잘못된 형식 등) |
| 401 Unauthorized | 인증 실패 |
| 500 Internal Server Error | 서버 오류 |
파일 업로드 제한
사진 및 이미지 업로드 시 다음 제한 사항이 적용됩니다.
| 항목 | 제한 |
|---|---|
| 파일당 최대 크기 | 50MB |
| 책당 최대 사진 수 | 200장 |
| 지원 포맷 | JPEG, PNG, GIF, BMP, TIFF, WebP |
| 업로드 Rate Limit | 200 req/min (일반 API 300 req/min과 별도) |
파일 검증
- Magic byte 검증: 파일 확장자뿐만 아니라 파일의 매직 바이트(파일 시그니처)를 확인하여 실제 이미지 파일인지 검증합니다.
- 자동 포맷 변환: JPEG이 아닌 포맷은 서버에서 JPEG으로 자동 변환됩니다.
- 이미지 URL 지원: HTTP/HTTPS URL을 통한 이미지 제공이 가능하며, 다운로드 제한은 50MB / 10초 타임아웃입니다.
- preserveExif: 사진 업로드 시
preserveExif파라미터를 사용하여 EXIF 데이터 보존 여부를 제어할 수 있습니다.
책 표지 추가
/v1/books/{bookUid}/cover책의 표지를 생성합니다. 템플릿과 이미지를 사용하여 표지를 만들며, multipart/form-data 형식으로 요청합니다. 이미지 필드명은 템플릿 레이아웃의 변수명과 정확히 일치해야 합니다.
이미지 제공 방식 (혼용 가능)
| 방식 | 설명 |
|---|---|
| 파일 업로드 | multipart/form-data로 이미지 파일 직접 업로드 |
| URL 방식 | parameters JSON 내에 이미지 URL을 문자열로 제공 (http/https/www 지원) |
| 서버 파일명 | Photo Upload API로 미리 업로드한 파일명 사용 (예: photo250105143052123.JPG) |
$upload 플레이스홀더로 업로드 파일의 위치를 지정할 수 있습니다. 예: "frontPhoto": "$upload" → 이 위치에 업로드된 frontPhoto 파일 배치Request (multipart/form-data)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| templateUid | string | Y | 표지 템플릿 UID. 테스트용 권장: tpl_F8d15af9fd |
| parameters | string | N | 템플릿 파라미터 JSON 문자열. 동적 파라미터는 반드시 이 필드로만 전달해야 합니다. |
| 동적 이미지 필드 | file | 조건부 | 템플릿에서 정의한 변수명으로 이미지 제공. 필드명과 템플릿 변수명이 정확히 일치해야 바인딩됩니다. |
Request 예시 — 파일 업로드 방식
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/cover' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=tpl_F8d15af9fd' \
-F 'frontPhoto=@front.jpg;type=image/jpeg' \
-F 'backPhoto=@back.jpg;type=image/jpeg' \
-F 'parameters={"title":"Test Book","author":"Test Author"}'Request 예시 — URL 방식
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/cover' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=tpl_F8d15af9fd' \
-F 'parameters={"title":"Test Book","author":"Test Author","frontPhoto":"https://example.com/front.jpg","backPhoto":"https://example.com/back.jpg"}'Request 예시 — 혼합 방식
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/cover' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=tpl_F8d15af9fd' \
-F 'frontPhoto=@front.jpg;type=image/jpeg' \
-F 'parameters={"title":"Test Book","author":"Test Author","frontPhoto":"$upload","backPhoto":"photo250105143052456.JPG"}'Response
성공 시 — 생성 (201 Created)
{ "success": true, "message": "Cover created successfully", "data": { "result": "inserted" } }성공 시 — 업데이트 (200 OK)
{ "success": true, "message": "Cover updated successfully", "data": { "result": "updated" } }HTTP 상태 코드
| 상태 코드 | 설명 |
|---|---|
| 201 Created | 새로운 표지 생성 성공 |
| 200 OK | 기존 표지 업데이트 성공 |
| 400 Bad Request | 잘못된 요청 |
| 401 Unauthorized | 인증 실패 |
| 500 Internal Server Error | 서버 오류 |
사진 업로드
/v1/books/{bookUid}/photos책에 사용할 사진을 업로드합니다. 업로드된 사진의 fileName을 contents API에서 사용합니다. 지원 형식: jpg, jpeg, png, gif, bmp, webp, heic, heif (최대 50MB)
Request (multipart/form-data)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| file | file | Y | 이미지 파일 |
지원 이미지 포맷
| 포맷 | 확장자 | 서버 처리 |
|---|---|---|
| JPEG | .jpg, .jpeg | 그대로 사용 |
| PNG | .png | 그대로 사용 |
| GIF | .gif | PNG로 자동 변환 |
| WebP | .webp | PNG로 자동 변환 |
| BMP | .bmp | JPG로 자동 변환 |
| HEIC/HEIF | .heic, .heif | JPG로 자동 변환 |
파일당 최대 50MB
이미지 처리
| 처리 | 내용 |
|---|---|
| 리사이즈 | 긴 축 기준 4000px (원본), 800px (썸네일) |
| 형식 변환 | HEIC/HEIF → JPG, GIF/WebP → PNG, BMP → JPG |
| EXIF 처리 | Orientation 적용 후 EXIF 제거 |
| 중복 체크 | MD5 해시로 중복 검사. 중복 시 isDuplicate: true와 함께 기존 파일 정보 반환 |
Response (201 Created)
{
"success": true,
"data": {
"fileName": "photo250105143052123.JPG",
"originalName": "IMG_1234.jpg",
"size": 1234567,
"mimeType": "image/jpeg",
"uploadedAt": "2026-01-05T14:30:52Z",
"isDuplicate": false,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
}
}사진 목록 조회
/v1/books/{bookUid}/photos책에 업로드된 사진 목록을 조회합니다.
Response (200 OK)
{
"success": true,
"data": {
"photos": [
{
"fileName": "photo250105143052123.JPG",
"originalName": "IMG_1234.jpg",
"size": 1234567,
"mimeType": "image/jpeg",
"uploadedAt": "2026-01-05T14:30:52Z",
"hash": "d41d8cd98f00b204e9800998ecf8427e"
}
],
"totalCount": 1
}
}사진 삭제
/v1/books/{bookUid}/photos/{fileName}업로드된 사진을 삭제합니다. 최종화된 책(status=2)의 사진은 삭제할 수 없습니다. 삭제된 사진의 fileName을 contents API에서 사용하면 에러가 발생합니다.
성공 시 (204 No Content) — 응답 본문 없음
책 콘텐츠 추가
/v1/books/{bookUid}/contents책의 내지(콘텐츠 페이지)를 추가합니다. 템플릿과 이미지를 사용하여 페이지를 생성하며, breakBefore 파라미터로 페이지 배치를 제어할 수 있습니다.
지원 기능
동적 텍스트 높이 계산 (isDynamic: true), 지능형 요소 배치, Gallery 레이아웃, 컬럼 레이아웃, 필드명 기반 이미지 매칭을 지원합니다.
Query Parameters
| 파라미터 | 기본값 | 설명 |
|---|---|---|
| breakBefore | content→none, divider/publish→page | page: 항상 새로운 페이지에서 시작 | column: 컬럼 기준 배치 (여유 컬럼에 배치, 없으면 다음 페이지) | none: 이전 콘텐츠 바로 다음에 연속 배치 |
Request (multipart/form-data)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| templateUid | string | Y | 콘텐츠 템플릿 UID |
| parameters | string | N | 템플릿 파라미터 JSON 문자열. 동적 파라미터는 반드시 이 필드로만 전달해야 합니다. |
| 동적 이미지 필드 | file(s) | 조건부 | 템플릿 변수명과 일치하는 필드명으로 이미지 제공. Gallery는 같은 필드명으로 여러 파일 전송. |
혼합 방식 — $upload 플레이스홀더
{
"rowPhotos": [
"$upload", // 첫 번째 업로드 파일 위치
"photo260109120000001.JPG", // 서버 파일명
"$upload", // 두 번째 업로드 파일 위치
"https://example.com/img.jpg", // URL
"photo260109120000002.JPG" // 서버 파일명
]
}Request 예시 — 파일 업로드 방식
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/contents?breakBefore=page' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=5iwCNE0Xa8Gb' \
-F 'imageMain=@image1.jpg;type=image/jpeg' \
-F 'parameters={"dateStr":"2025-11-10","contents":"Hello World!"}'Request 예시 — Gallery URL 방식
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/contents?breakBefore=page' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=4HxVDGZxwLbB' \
-F 'parameters={"date":"2025-10-17","galleryPhotos":["https://example.com/1.jpg","https://example.com/2.jpg","https://example.com/3.jpg"]}'Request 예시 — 서버 파일명 방식 (권장)
# Step 1: Photo Upload API로 사진 업로드
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/photos' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'file=@photo1.jpg'
# Response: {"data":{"fileName":"photo260107065637669.JPG"}}
# Step 2: 서버 파일명으로 contents 추가
curl -X 'POST' \
'https://api.sweetbook.com/v1/books/bk_3dJTg8WOpR2e/contents?breakBefore=page' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: multipart/form-data' \
-F 'templateUid=4HxVDGZxwLbB' \
-F 'parameters={"date":"2025-01-07","galleryPhotos":["photo260107065637669.JPG","photo260107065638193.JPG"]}'필수/선택 파라미터 검증
| required 값 | 동작 |
|---|---|
| true | 필수 파라미터 — 누락 시 400 에러 반환 |
| false 또는 미정의 | 선택 파라미터 — 누락 시 해당 요소가 페이지에서 제거됨 |
Response
{
"success": true,
"message": "Content created successfully",
"data": {
"result": "inserted",
"breakBefore": "page"
}
}HTTP 상태 코드
| 상태 코드 | 설명 |
|---|---|
| 201 Created | 새로운 콘텐츠 생성 성공 |
| 200 OK | 기존 콘텐츠 업데이트 성공 |
| 400 Bad Request | 잘못된 요청 (이미지 누락, breakBefore 값 오류 등) |
| 401 Unauthorized | 인증 실패 |
| 500 Internal Server Error | 서버 오류 |
주의사항
최종화(status=2) 또는 삭제(status=9)된 책은 콘텐츠를 추가할 수 없습니다. 템플릿의 변수명과 업로드 필드명이 정확히 일치해야 합니다. URL 방식 사용 시 이미지 다운로드 제한: 최대 50MB, 10초 타임아웃. 상품별 페이지 배치: SQUAREBOOK_HC는 첫 내지 페이지(first)가 오른쪽부터 시작합니다.
책 내지 초기화
/v1/books/{bookUid}/contents책의 모든 내지 페이지를 삭제하고 표지만 남깁니다. 개발 및 테스트 용도로 사용됩니다.
Response (200 OK)
{
"success": true,
"message": "책 내지 초기화 완료",
"data": {
"deletedPages": 15,
"message": "15개의 내지 페이지가 삭제되었습니다"
}
}HTTP 상태 코드
| 상태 코드 | 설명 |
|---|---|
| 200 OK | 내지 초기화 성공 |
| 400 Bad Request | 잘못된 요청 |
| 401 Unauthorized | 인증 실패 |
| 404 Not Found | 책을 찾을 수 없음 |
| 500 Internal Server Error | 서버 오류 |
책 최종화
/v1/books/{bookUid}/finalization책 편집을 완료하고 최종본(finalized) 상태로 전환합니다. 이후에는 페이지 추가/수정이 불가능합니다. 멱등 처리를 지원하므로 재호출 시 에러 없이 기존 정보를 반환합니다.
제약사항
| 항목 | 내용 |
|---|---|
| 상태 조건 | DRAFT 상태의 책만 최종화 가능 |
| 권한 | 책 소유자만 최종화 가능 |
| 페이지 수 | 상품 스펙의 규칙 만족 필요 (최소/최대/증분) |
Response
성공 시 — 최종화 완료 (201 Created)
{
"success": true,
"message": "책 최종화 완료",
"data": {
"result": "페이지를 추가하지 않고 완료",
"pageCount": 24,
"finalizedAt": "2025-10-01T02:28:45.505Z"
}
}성공 시 — 이미 최종화됨 (200 OK, 멱등 처리)
{
"success": true,
"message": "이미 최종화된 책입니다",
"data": {
"result": "updated",
"pageCount": 24,
"finalizedAt": "2025-10-01T02:28:45.505Z"
}
}실패 시 — 페이지 수 규칙 위반 (400 Bad Request)
{
"success": false,
"message": "Validation Error",
"data": null,
"errors": ["페이지 수는 최소 20페이지 이상이어야 합니다"]
}표지 책등 자동 조정
최종 페이지 수에 따라 cover.json의 책등 크기가 자동으로 조정됩니다. 하드커버의 경우 페이지 수 임계값에 따라 책등 너비가 증가하며, 소프트커버는 페이지 수에 따라 동적으로 계산됩니다. 왼쪽면 요소는 변화 없음, 오른쪽면 요소는 증가분만큼 이동, 책등 내 세로 텍스트는 증가분의 절반만큼 이동합니다.
HTTP 상태 코드
| 상태 코드 | 설명 |
|---|---|
| 201 Created | 최종화 완료 |
| 200 OK | 이미 최종화된 책 (멱등 처리) |
| 400 Bad Request | 페이지 수 규칙 위반 등 |
| 401 Unauthorized | 인증 실패 |
| 403 Forbidden | 권한 없음 (소유자가 아님) |
| 404 Not Found | 책을 찾을 수 없음 |
| 500 Internal Server Error | 서버 오류 |