Books API

책 생성, 조회, 표지/내지 추가, 최종화 API 문서입니다.

모든 Books API는 인증이 필요합니다. API Key를 Authorization: Bearer <API_KEY> 헤더로 제공하세요.

책 생성

POST/v1/books

새로운 책을 생성합니다. 초안(draft) 상태로 생성되며, 이후 표지와 콘텐츠를 추가할 수 있습니다.

Request Body

json
{
  "title": "테스트책",
  "bookSpecUid": "SQUAREBOOK_HC",
  "specProfileUid": "sp_abc123xyz",
  "creationType": "TEST",
  "externalRef": "PARTNER-ORDER-001"
}
필드타입필수설명
titlestringY책 제목 (1-255자)
bookSpecUidstringY상품 스펙 UID (예: SQUAREBOOK_HC)
specProfileUidstringNSpecProfile UID - 제공 시 해당 프로필과 연결. 유효하지 않으면 에러 반환
creationTypestringN생성 방식 (TEST, TEMPLATE 등, 기본값: TEMPLATE)
externalRefstringN파트너 외부 참조 식별자 (최대 100자). 파트너 시스템의 고유 ID를 저장하는 용도

Request 예시 (curl)

bash
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)

json
{
  "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 Limit200 req/min (일반 API 300 req/min과 별도)

파일 검증

  • Magic byte 검증: 파일 확장자뿐만 아니라 파일의 매직 바이트(파일 시그니처)를 확인하여 실제 이미지 파일인지 검증합니다.
  • 자동 포맷 변환: JPEG이 아닌 포맷은 서버에서 JPEG으로 자동 변환됩니다.
  • 이미지 URL 지원: HTTP/HTTPS URL을 통한 이미지 제공이 가능하며, 다운로드 제한은 50MB / 10초 타임아웃입니다.
  • preserveExif: 사진 업로드 시 preserveExif 파라미터를 사용하여 EXIF 데이터 보존 여부를 제어할 수 있습니다.

책 표지 추가

POST/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)

필드타입필수설명
templateUidstringY표지 템플릿 UID. 테스트용 권장: tpl_F8d15af9fd
parametersstringN템플릿 파라미터 JSON 문자열. 동적 파라미터는 반드시 이 필드로만 전달해야 합니다.
동적 이미지 필드file조건부템플릿에서 정의한 변수명으로 이미지 제공. 필드명과 템플릿 변수명이 정확히 일치해야 바인딩됩니다.
EXIF 정보는 항상 보존됩니다. 개별 form 필드로 텍스트 파라미터를 전달하는 방식은 더 이상 지원되지 않습니다. 최종화(status=2) 또는 삭제(status=9)된 책은 표지를 추가할 수 없습니다.

Request 예시 — 파일 업로드 방식

bash
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 방식

bash
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 예시 — 혼합 방식

bash
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)

json
{ "success": true, "message": "Cover created successfully", "data": { "result": "inserted" } }

성공 시 — 업데이트 (200 OK)

json
{ "success": true, "message": "Cover updated successfully", "data": { "result": "updated" } }

HTTP 상태 코드

상태 코드설명
201 Created새로운 표지 생성 성공
200 OK기존 표지 업데이트 성공
400 Bad Request잘못된 요청
401 Unauthorized인증 실패
500 Internal Server Error서버 오류

사진 업로드

POST/v1/books/{bookUid}/photos

책에 사용할 사진을 업로드합니다. 업로드된 사진의 fileName을 contents API에서 사용합니다. 지원 형식: jpg, jpeg, png, gif, bmp, webp, heic, heif (최대 50MB)

Request (multipart/form-data)

필드타입필수설명
filefileY이미지 파일

지원 이미지 포맷

포맷확장자서버 처리
JPEG.jpg, .jpeg그대로 사용
PNG.png그대로 사용
GIF.gifPNG로 자동 변환
WebP.webpPNG로 자동 변환
BMP.bmpJPG로 자동 변환
HEIC/HEIF.heic, .heifJPG로 자동 변환
SVG, TIFF, PDF, AI, PSD 등은 지원하지 않습니다. 업로드 시 에러가 발생합니다.

파일당 최대 50MB

이미지 처리

처리내용
리사이즈긴 축 기준 4000px (원본), 800px (썸네일)
형식 변환HEIC/HEIF → JPG, GIF/WebP → PNG, BMP → JPG
EXIF 처리Orientation 적용 후 EXIF 제거
중복 체크MD5 해시로 중복 검사. 중복 시 isDuplicate: true와 함께 기존 파일 정보 반환

Response (201 Created)

json
{
  "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"
  }
}

사진 목록 조회

GET/v1/books/{bookUid}/photos

책에 업로드된 사진 목록을 조회합니다.

Response (200 OK)

json
{
  "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
  }
}

사진 삭제

DELETE/v1/books/{bookUid}/photos/{fileName}

업로드된 사진을 삭제합니다. 최종화된 책(status=2)의 사진은 삭제할 수 없습니다. 삭제된 사진의 fileName을 contents API에서 사용하면 에러가 발생합니다.

성공 시 (204 No Content) — 응답 본문 없음


책 콘텐츠 추가

POST/v1/books/{bookUid}/contents

책의 내지(콘텐츠 페이지)를 추가합니다. 템플릿과 이미지를 사용하여 페이지를 생성하며, breakBefore 파라미터로 페이지 배치를 제어할 수 있습니다.

지원 기능

동적 텍스트 높이 계산 (isDynamic: true), 지능형 요소 배치, Gallery 레이아웃, 컬럼 레이아웃, 필드명 기반 이미지 매칭을 지원합니다.

Query Parameters

파라미터기본값설명
breakBeforecontent→none, divider/publish→pagepage: 항상 새로운 페이지에서 시작 | column: 컬럼 기준 배치 (여유 컬럼에 배치, 없으면 다음 페이지) | none: 이전 콘텐츠 바로 다음에 연속 배치

Request (multipart/form-data)

필드타입필수설명
templateUidstringY콘텐츠 템플릿 UID
parametersstringN템플릿 파라미터 JSON 문자열. 동적 파라미터는 반드시 이 필드로만 전달해야 합니다.
동적 이미지 필드file(s)조건부템플릿 변수명과 일치하는 필드명으로 이미지 제공. Gallery는 같은 필드명으로 여러 파일 전송.

혼합 방식 — $upload 플레이스홀더

json
{
  "rowPhotos": [
    "$upload",                          // 첫 번째 업로드 파일 위치
    "photo260109120000001.JPG",         // 서버 파일명
    "$upload",                          // 두 번째 업로드 파일 위치
    "https://example.com/img.jpg",      // URL
    "photo260109120000002.JPG"          // 서버 파일명
  ]
}

Request 예시 — 파일 업로드 방식

bash
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 방식

bash
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 예시 — 서버 파일명 방식 (권장)

bash
# 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

json
{
  "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)가 오른쪽부터 시작합니다.


책 내지 초기화

DELETE/v1/books/{bookUid}/contents

책의 모든 내지 페이지를 삭제하고 표지만 남깁니다. 개발 및 테스트 용도로 사용됩니다.

개발 테스트용 API입니다. 삭제된 내지 페이지와 이미지는 복구할 수 없습니다. 표지(cover) 페이지는 삭제되지 않고 유지됩니다.

Response (200 OK)

json
{
  "success": true,
  "message": "책 내지 초기화 완료",
  "data": {
    "deletedPages": 15,
    "message": "15개의 내지 페이지가 삭제되었습니다"
  }
}

HTTP 상태 코드

상태 코드설명
200 OK내지 초기화 성공
400 Bad Request잘못된 요청
401 Unauthorized인증 실패
404 Not Found책을 찾을 수 없음
500 Internal Server Error서버 오류

책 최종화

POST/v1/books/{bookUid}/finalization

책 편집을 완료하고 최종본(finalized) 상태로 전환합니다. 이후에는 페이지 추가/수정이 불가능합니다. 멱등 처리를 지원하므로 재호출 시 에러 없이 기존 정보를 반환합니다.

제약사항

항목내용
상태 조건DRAFT 상태의 책만 최종화 가능
권한책 소유자만 최종화 가능
페이지 수상품 스펙의 규칙 만족 필요 (최소/최대/증분)

Response

성공 시 — 최종화 완료 (201 Created)

json
{
  "success": true,
  "message": "책 최종화 완료",
  "data": {
    "result": "페이지를 추가하지 않고 완료",
    "pageCount": 24,
    "finalizedAt": "2025-10-01T02:28:45.505Z"
  }
}

성공 시 — 이미 최종화됨 (200 OK, 멱등 처리)

json
{
  "success": true,
  "message": "이미 최종화된 책입니다",
  "data": {
    "result": "updated",
    "pageCount": 24,
    "finalizedAt": "2025-10-01T02:28:45.505Z"
  }
}

실패 시 — 페이지 수 규칙 위반 (400 Bad Request)

json
{
  "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서버 오류