템플릿 기반 시나리오
템플릿을 사용해 책을 구성하고, 서버에서 PDF를 렌더링한 뒤 주문까지 완료하는 전체 흐름입니다.
개요
호출 시퀀스
- 책 생성 — 판형(
bookSpecUid) 지정 - 표지 추가 — 표지 템플릿 + 파라미터 바인딩 (템플릿에 따라 이미지 포함)
- 내지 추가 (반복) — 내지 템플릿 + 파라미터 바인딩 (템플릿에 따라 이미지 포함)
- 책 최종화 — 페이지 수 검증 후 FINALIZED 상태로 전환
- 주문 생성 —
PAID상태 진입, 서버에서 PDF 렌더링 후PDF_READY로 승격 - 주문 상태 추적 — 웹훅으로 배송 진행 수신
사용 케이스
템플릿을 활용해 포토북을 만들고 싶을 때 사용합니다. 공용 템플릿 또는 파트너 전용 템플릿을 선택하고, 사진과 텍스트만 준비하면 됩니다. 각 템플릿의 디자인 특징과 사용 예시는 템플릿 상세 정보 ↗에서 확인할 수 있습니다.
예시 환경
이 페이지의 모든 curl 예시는 아래 값을 기준으로 작성되어 있습니다. 코드 블록 우측 상단의 Sandbox / Live 탭으로 환경이 전환됩니다.
복붙해서 실행할 때는 {YOUR_API_KEY}를 본인 API Key로, {bookUid} 플레이스홀더를 실제 값으로 교체하세요.
| 항목 | 예시 값 |
|---|---|
판형 UID (bookSpecUid) | SQUAREBOOK_HC (하드커버 243×248mm) |
| 표지 템플릿 UID | 79yjMH3qRPly (일기장A 표지) |
| 내지 템플릿 UID | 46VqZhVNOfAp (일기장A 내지a) |
1. 책 생성
/books새로운 책을 생성합니다. 생성된 책은 DRAFT(편집중) 상태로 시작되며, 이후 표지와 내지를 추가할 수 있습니다.
Request Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
title | string | O | 책 제목 (1~255자) |
bookSpecUid | string | O | 판형 UID |
externalRef | string | - | 파트너 외부 참조 식별자 (최대 100자). 파트너 시스템의 고유 ID를 저장하는 용도 |
POST /books 요청 시 Idempotency-Key 헤더를 제공하면 동일한 키로 재요청해도 책이 중복 생성되지 않습니다. 네트워크 오류 등으로 인한 재시도 시 활용하세요.curl -X POST 'https://api-sandbox.sweetbook.com/v1/books' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: unique-request-id-001' \
-d '{
"title": "일기장 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"externalRef": "PARTNER-ORDER-001"
}'{
"success": true,
"message": "책 생성 완료",
"data": {
"bookUid": "bk_5WSy********"
}
}2. 표지 추가
/books/{bookUid}/cover템플릿과 파라미터를 사용하여 표지를 생성합니다. 템플릿에 이미지 변수(binding: "file")가 있으면 이미지도 함께 전달합니다. 이미 표지가 있는 상태에서 다시 호출하면 덮어쓰기됩니다.
Request (multipart/form-data)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
templateUid | string | O | 표지 템플릿 UID |
parameters | string | - | 템플릿 파라미터 JSON 문자열. 이미지 URL, 텍스트 값 등을 전달 |
| 동적 이미지 필드 | file | - | 템플릿 변수명과 일치하는 필드명으로 이미지 파일 제공 |
이미지 전달 방식 (이미지 변수가 있는 템플릿인 경우)
템플릿의 parameters.definitions에 binding: "file" 타입 변수가 있으면 이미지를 전달해야 합니다. 텍스트만으로 구성된 템플릿이면 이미지 없이 호출 가능합니다.
| 방식 | 설명 |
|---|---|
| 파일 직접 업로드 | multipart form 필드로 이미지 파일 첨부. parameters에서 해당 변수를 "$upload"로 지정 |
| URL 전달 | parameters JSON에 이미지 URL을 직접 지정 (50MB / 10초 타임아웃) |
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/cover' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'templateUid=79yjMH3qRPly' \
-F 'coverPhoto=@front.jpg;type=image/jpeg' \
-F 'parameters={"title":"나의 하루 기록","dateRange":"26.01 - 26.04","coverPhoto":"$upload"}'{
"success": true,
"message": "Cover created successfully",
"data": {
"result": "inserted"
}
}3. 내지 추가 (반복)
/books/{bookUid}/contents내지 페이지를 추가합니다. 판형의 최소 페이지 수(pageMin)를 충족할 때까지 반복 호출합니다. 템플릿에 이미지 변수가 있으면 이미지도 함께 전달합니다. 이미지 전달 방식은 표지와 동일합니다 (2. 표지 추가 섹션 참조).
Query Parameters
| 파라미터 | 기본값 | 설명 |
|---|---|---|
breakBefore | content→none, divider/publish→page | page: 새 페이지에서 시작 / column: 여유 컬럼에 배치 / none: 이전 콘텐츠 바로 다음에 연속 |
Request (multipart/form-data)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
templateUid | string | O | 내지 템플릿 UID (content, divider, publish 중 하나) |
parameters | string | - | 템플릿 파라미터 JSON 문자열 |
| 동적 이미지 필드 | file | - | 템플릿 변수명과 일치하는 필드명으로 이미지 파일 제공 |
응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
result | string | inserted (신규) 또는 updated (기존 교체) |
breakBefore | string | 적용된 breakBefore 값 |
pageNum | int | 배치된 페이지 번호 |
pageSide | string | left 또는 right |
pageCount | int | 현재까지 총 페이지 수 |
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/contents?breakBefore=page' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-F 'templateUid=46VqZhVNOfAp' \
-F 'photo=@photo1.jpg;type=image/jpeg' \
-F 'parameters={"monthNum":"04","dayNum":"14","diaryText":"오늘의 일기입니다.","photo":"$upload"}'{
"success": true,
"message": "Content created successfully",
"data": {
"result": "inserted",
"breakBefore": "page",
"pageNum": 1,
"pageSide": "right",
"pageCount": 0
}
}4. 책 최종화
/books/{bookUid}/finalization책을 FINALIZED(최종화) 상태로 전환합니다. 페이지 수가 판형의 pageMin 이상이어야 하며, pageIncrement 배수 조건도 충족해야 합니다.
페이지 수 규칙 (SQUAREBOOK_HC 기준)
| 규칙 | 값 |
|---|---|
최소 페이지 수 (pageMin) | 24 |
최대 페이지 수 (pageMax) | 130 |
페이지 증분 (pageIncrement) | 2 |
응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
result | string | 최종화 결과 메시지 |
pageCount | int | 최종 페이지 수 |
finalizedAt | string | 최종화 완료 시각 (ISO 8601) |
에러 응답
| 상황 | 상태 코드 | 응답 메시지 |
|---|---|---|
| 최소 페이지 미달 | 400 | 최소 페이지 미달: 현재 0p, 최소 24p |
curl -X POST 'https://api-sandbox.sweetbook.com/v1/books/{bookUid}/finalization' \
-H 'Authorization: Bearer {YOUR_API_KEY}'{
"success": true,
"message": "책 최종화 완료",
"data": {
"result": "페이지를 추가하고 완료",
"pageCount": 26,
"finalizedAt": "2026-04-14T07:15:44.613Z"
}
}5. 주문 생성
/orders책이 FINALIZED(최종화) 상태인 경우에만 주문 생성이 가능합니다. 주문 생성 시 PAID 상태로 진입하며, 서버에서 PDF 렌더링이 완료되면 PDF_READY로 승격됩니다.
주문 전 금액 확인이 필요하면 POST /orders/estimate를 먼저 호출하세요. 충전금 잔액 부족 시 402 Insufficient Credit이 반환됩니다.
필드 상세는 Orders API 레퍼런스 참조.
POST /orders 요청 시 Idempotency-Key 헤더를 제공하면 동일한 키로 재요청해도 주문이 중복 생성되지 않습니다. 네트워크 오류 등으로 인한 재시도 시 활용하세요.에러 응답
| 상황 | 상태 코드 | 응답 메시지 |
|---|---|---|
| DRAFT(편집중) 상태 책을 주문 시도 | 400 | Book이 FINALIZED 상태가 아닙니다: bk_588b******** |
| 충전금 부족 | 402 | 잔액이 부족합니다. 필요: 3420, 잔액: 760.00 |
curl -X POST 'https://api-sandbox.sweetbook.com/v1/orders' \
-H 'Authorization: Bearer {YOUR_API_KEY}' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: unique-request-id-002' \
-d '{
"items": [{ "bookUid": "{bookUid}", "quantity": 1 }],
"shipping": {
"recipientName": "김영수",
"recipientPhone": "010-0000-0000",
"postalCode": "06134",
"address1": "서울시 강남구 테헤란로 100",
"address2": "101호",
"memo": ""
},
"externalRef": "PARTNER-ORDER-001"
}'{
"success": false,
"message": "Insufficient Credit",
"data": {
"required": 3420,
"balance": 760.00,
"currency": "KRW"
},
"errors": [
"잔액이 부족합니다. 필요: 3420, 잔액: 760.00"
]
}{
"success": true,
"message": "주문이 생성되었습니다",
"data": {
"orderUid": "or_41qi********",
"accountName": "김영수",
"accountOrganizationName": null,
"externalRef": "PARTNER-ORDER-001",
"orderStatus": "PAID",
"orderStatusDisplay": "결제완료",
"isTest": true,
"totalProductAmount": 110.00,
"totalShippingFee": 3000,
"totalPackagingFee": 0,
"totalAmount": 3110.00,
"paidCreditAmount": 3420,
"creditBalanceAfter": 93160.00,
"recipientName": "김영수",
"recipientPhone": "010-0000-0000",
"postalCode": "06134",
"address1": "서울시 강남구 테헤란로 100",
"address2": "101호",
"shippingMemo": "",
"trackingNumber": null,
"trackingCarrier": null,
"cancelReason": null,
"refundAmount": null,
"orderedAt": "2026-04-14T07:15:47.527Z",
"paidAt": "2026-04-14T07:15:47.527Z",
"cancelledAt": null,
"shippedAt": null,
"deliveredAt": null,
"createdAt": "2026-04-14T07:15:47.527Z",
"items": [
{
"itemUid": "oi_4nfx********",
"bookUid": "bk_5WSy********",
"bookTitle": "일기장 샘플",
"bookSpecUid": "SQUAREBOOK_HC",
"bookSpecName": "고화질 스퀘어북 (하드커버)",
"quantity": 1,
"pageCount": 26,
"unitPrice": 110.00,
"itemAmount": 110.00,
"itemStatus": "PAID",
"itemStatusDisplay": "결제완료",
"trackingNumber": null,
"trackingCarrier": null,
"shippedAt": null,
"createdAt": "2026-04-14T07:15:47.527Z"
}
]
}
}6. 주문 상태 추적
주문이 생성된 이후 제작·배송 진행은 웹훅 이벤트로 수신합니다. 템플릿 기반 방식 주문은 PAID에서 시작하며, 서버에서 PDF 렌더링이 완료되면 PDF_READY로 승격됩니다. 이후 상태 전이 체계는 주문 상태 흐름 페이지 참조.
- 수신 이벤트 목록: Webhook Events 레퍼런스
- 서명 검증: Webhooks API
- 상태 전이 전체도: 주문 상태 흐름