변경 이력
관리 API·스토어프론트 API·SDK의 공개 변경 사항
연동에 영향을 주는 변경을 날짜순(최신이 위)으로 정리합니다. 호환되지 않는 변경에는 호환성 변경을 표시합니다.
2026-10-13
서비스 주소 이전 (sayren.io, sayren 0.9.0 · @sayren/mcp 0.24.0 · @sayren/app 0.9.0)
호환성 변경이 있습니다. 서비스 도메인을 sayren.app에서 sayren.io로 옮깁니다.
- 변경(호환성 변경): API 주소가
https://api.sayren.io입니다. 관리 API는https://api.sayren.io/v1, 스토어프론트 API는https://api.sayren.io/storefront/v1입니다. - 변경(호환성 변경): 계정 토큰의 발급자(
iss)가https://accounts.sayren.io, 대상(aud)이https://api.sayren.io·https://mcp.sayren.io/mcp입니다. 옛 주소로 발급된 토큰은 받지 않으므로 다시 로그인하거나 액세스 토큰을 새로 발급하십시오. - 변경: 원격 MCP는
https://mcp.sayren.io/mcp, 문서는https://docs.sayren.io, OpenAPI 문서는https://api.sayren.io/openapi/store.json·https://api.sayren.io/openapi/storefront.json입니다. - 변경:
sayrenCLI·@sayren/mcp·@sayren/app의 기본 api 주소가https://api.sayren.io입니다..mcp.json등 연결 설정에 옛 주소를 적었다면 새 주소로 바꾸십시오.
2026-10-08
앱 매니페스트 파일 이름 (sayren 0.8.1)
- 변경: 앱 매니페스트 파일 이름이
manifest.json입니다.npx sayren app init이 이 이름으로 만듭니다. - 옛 이름
sayren.app.json은manifest.json이 없을 때 계속 읽고, CLI가 이름을 바꾸라는 경고를 냅니다.
개발자 서버에서 실행·에이전트 도구 (@sayren/store-sdk 0.30.13 · @sayren/app 0.8.0 · sayren 0.8.0)
- 추가: 매니페스트
runtime: "external"·external.url— 앱 코드를 개발자 서버에서 실행합니다. 호출에는 서명(x-sayren-signature)이 붙고 공개 키는/.well-known/sayren-apps-jwks.json입니다.@sayren/appcreateExternalHandler가 확인합니다. - 추가: 매니페스트
mcp.tools와defineApp({ tools })— 상점의 AI 에이전트가 쓰는 앱 도구. 관리 APIGET /v1/apps/tools·POST /v1/apps/installations/{id}/tools/{name}(SDKappTools). - 추가: 설치·앱 상세 응답
tools·externalHost. 도구 추가·실행 호스트 변경은 재동의가 필요합니다.
주문 흐름에서 앱 쓰기 (@sayren/store-sdk 0.30.13 · @sayren/app 0.8.0 · sayren 0.8.0)
- 추가: 매니페스트
flow.notifications·flow.events와defineApp({ flows })— 주문 흐름의 알림 블록이 앱으로 알림과 매개변수 값(셀러가 식으로 연결)을 보냅니다. - 추가: 흐름 알림 블록
channel: "app.<handle>.<알림>"과params(매개변수 → 식). 웹훅 알림은 그대로event가 필요합니다. - 추가: 앱 사건
POST /v1/order-items/{id}/events/app.<handle>.<사건>— 그 앱의 설치 토큰으로만, 매니페스트flow.events에 있는 이름만 받습니다(아니면 403FLOW_EVENT_APP_FORBIDDEN). SDKorderItems.emitEvent가app.키를 받습니다. - 추가: 설치 응답
flowNotifications·flowEvents. 로컬에서는npx sayren app trigger --flow <이름>.
앱 공개 범위 — 비공개 앱·퍼블릭 앱
- 추가: 비공개 앱 — 만들 때 상점 하나를 정하면(
sayren app init --private-store <storeId>, 개발자 APIprivateStoreId) 그 상점에만 보이고 설치됩니다. - 추가: 공개 신청과 운영자 심사 — 승인된 앱은 모든 상점의 앱 목록에 보입니다. 개발자 앱 응답
privateStoreId·listingReview. - 추가: 앱 목록·상세 응답
visibility(DEVELOPMENT·PRIVATE·PUBLIC).
앱 공개 HTTP·예약 작업·저장소 (@sayren/store-sdk 0.30.12 · @sayren/app 0.7.0 · sayren 0.7.0)
- 추가: 매니페스트
http.public— 적은 HTTP 핸들러를https://{handle}.sayrenapps.com/hooks/{설치 id}/…로 외부에서 부를 수 있습니다(메일 링크·외부 서비스 콜백).ctx.publicUrl(path)가 주소를 만듭니다. - 추가: 매니페스트
schedules와defineApp({ schedules })— 설치마다 15분~하루 간격으로 실행되는 작업입니다. 로컬에서는npx sayren app trigger --schedule <이름>. - 추가:
ctx.storage— 설치별 키-값 저장소(1,000키·1MB). 관리 APIGET·PUT·DELETE /v1/app/storage/{key}·GET /v1/app/storage(앱 설치 토큰 전용, SDKapp.storage). - 추가: 설치 상세·앱 상세 응답
publicHttp·schedules. 공개 HTTP·예약 작업이 늘어난 버전은 재동의가 필요합니다.
앱 화면·HTTP 핸들러
- 추가: 매니페스트
ui.adminPage를 적은 앱은 상점 플랫폼 **앱 › 설치한 앱 › {앱}**의 앱 화면 탭에 열립니다. 화면 주소는https://{handle}.sayrenapps.com입니다. - 추가: 앱 화면이
@sayren/app/ui의app.fetch로 앱 코드의http핸들러를 부릅니다. 핸들러의ctx.user에 화면을 연 사람의 id와 역할이 들어 있습니다.
앱 권한 업데이트·실행 기록 (@sayren/store-sdk 0.30.11 · @sayren/app 0.6.1 · sayren 0.6.1)
- 추가: 설치 상세
pendingVersion(재동의를 기다리는 새 버전의 권한·외부 호스트·이벤트). 없으면null입니다. - 추가:
POST /v1/apps/installations/{installationId}/consent(SDKapps.installations.consent) — 권한 업데이트에 동의하고 새 버전으로 옮깁니다. 앱에APP.SCOPES_UPDATED가 갑니다. 상점 플랫폼 전용입니다. - 추가:
GET /v1/apps/installations/{installationId}/activity(SDKapps.installations.activity) — 최근 이벤트 전송 결과 50건과 최근 7일 관리 API 호출 수. - 추가: 구매자가 탈퇴하면 고객 정보 권한(
customer:*)으로 설치된 앱에APP.CUSTOMER_REDACT가 갑니다. - 추가: 실행 한도 — 앱 전체 동시 실행 20, 설치당 분당 이벤트 300. 넘은 이벤트는 시도로 세지 않고 뒤로 미룹니다.
- 추가: 24시간 동안 모든 호출이 앱 오류로 실패한 앱은 자동으로 정지되고 개발자 조직 구성원에게 메일이 갑니다.
- 수정: 앱 로그·오류 메시지에 섞인 설치 토큰·비밀 값·비밀 설정을 가려서 저장합니다. 호출 기록을 7일 뒤 지웁니다.
- 수정:
sayren app init의 예제 코드가event.data를 캐스팅하고 없는 필드(order.totalAmount)를 읽던 문제.order.payment.totalAmount를 씁니다.
2026-10-05
테스트 결제 주문 리뷰 설정·주문상품 리뷰 작성 가능 (@sayren/store-sdk 0.30.8 · @sayren/storefront-sdk 0.20.17)
- 추가: 상점
testOrderReviewsAllowed(기본false).PATCH /v1/store로 켜면 테스트 결제 주문에서도 구매자가 리뷰를 쓸 수 있습니다. 끄면 이전처럼 409REVIEW_NOT_ALLOWED_FOR_TEST_ORDER입니다. - 추가: 스토어프론트 내 주문의 주문상품
reviewWritable. 로그인 회원이 지금 리뷰를 쓸 수 있으면true입니다(구매확정, 작성 기한 안, 아직 쓰지 않음, 테스트 결제 주문이면 상점 허용). 리뷰 버튼은 이 값으로 그립니다.
배송·주문 연락처 형식 (@sayren/storefront-sdk 0.20.16)
- 변경: 배송지
phone과 비회원 주문자phone이 휴대폰 외에 050 안심번호(0503~0508)·070·지역번호 전화도 받습니다(숫자만). 회원 가입 휴대폰은 그대로 휴대폰만 받습니다. SDKCONTACT_PHONE_PATTERN.
흐름 기록 행동 이름·묶음에서 먼저 취소된 상품
- 추가: 흐름 실행 기록
trigger.label— 셀러·구매자 행동의 버튼 이름(예: 「접수」). 이름이 없는 상점 행동은 키만 옵니다. - 변경: 묶음 진행에서 취소·반품 클레임으로 먼저 빠진 주문상품은 묶음이 거절 등 다른 단계로 끝나도 흐름 보기가 「취소」(반품이면 반품)입니다. 끝난 주문상품의
moveTargets는 빈 배열입니다. - 변경: 주문제작형 프리셋 4 — 시안 확인 기한 초과·수정 요청 한도 초과 단계 이름을 「구매자 연락 필요」(구매자 「판매자 확인 중」)로 바꾸고 구매자 안내문과 취소 요청 권한을 더했습니다. 이미 만든 흐름은 그대로입니다.
즉시 취소·묶음 클레임·판매자 취소 미리보기 (@sayren/store-sdk 0.30.7 · @sayren/storefront-sdk 0.20.15)
- 변경: 흐름 권한이 「주문 취소」(즉시)인 단계에서 구매자가 취소를 신청하면 판매자 승인 없이 바로 취소·환불합니다. 클레임 접수 응답
approved: true, 흐름 행동 응답claim.approved: true입니다. 이전에는 승인 대기 클레임으로 남았습니다. - 추가: 흐름 설정
requires.groupClaim(주문 묶음 진행에서 한 상품의 취소·반품 중).CONTINUE면 묶음의 다른 상품은 그대로 진행하고 승인된 상품만 빠집니다.PAUSE(기본)면 처리할 때까지 묶음 전체의 기한·행동이 멈춥니다. 음식 배달형 5는CONTINUE입니다. - 변경: 묶음 진행에서 취소·반품 클레임의 행동(요청 철회)은 그 클레임의 주문상품에만 옵니다. 묶음에서 전량 취소돼 빠진 주문상품의 흐름 보기는 「취소」 상태이고 행동이 없습니다.
- 추가:
GET /v1/order-items/{orderItemId}/cancel-preview(SDKorderItems.cancelPreview) — 판매자 취소를 하면 돌려줄 현금·적립금·배송비. - 추가: 흐름 행동
attachments(REQUIRED·OPTIONAL, 첨부를 받는 행동만). 흐름 상태 입력 값display(선택지 이름 등 보이는 값). 입력 칸options가{ value, label }을 받습니다. - 추가: 구매자 주문
payment.pointRefundedAmount(취소·반품으로 돌려준 적립금). - 변경: 판매자가 흐름 행동으로 주문을 거절·취소하면 흐름이 그 행동의 도착 단계(예: 「주문 거절」)와 입력 사유로 끝납니다. 이전에는 「주문 취소」로 끝났습니다.
- 수정: 적립금으로 낸 배송비가 전량 판매자 취소에서 돌아오지 않던 문제.
기본 흐름 시드·흐름 만들기 순서 (@sayren/store-sdk 0.30.6)
- 변경: 새 상점은 기본 흐름 두 개(일반 배송형·배송 없는 상품 기본형)만 상점 흐름으로 시드합니다. 이전에는 주문제작형·티켓형·숙박 예약형·음식 배달형을 게시된 흐름으로 미리 만들었습니다. 이미 만들어진 흐름은 그대로입니다.
- 추가: 흐름 요약
defaultFor(기본 흐름이면SHIPPING·MANUAL). 기본 흐름의 초안 저장·게시·버전 옮기기는409 FLOW_DEFAULT_LOCKED입니다. 흐름을 지정하지 않은 상품은 상점의 기본 흐름을 따릅니다. - 추가:
GET /v1/flow-presets/{key}(프리셋 그래프·흐름 설정, SDKcommerceFlows.preset). 흐름 생성POST /v1/commerce-flows가graph·definition을 받습니다 — 편집한 그래프로 처음부터 만듭니다.
구매자 주문의 환불 금액·클레임 중 흐름 행동 (@sayren/storefront-sdk 0.20.14)
- 추가: 구매자 주문
payment.refundedAmount(환불된 결제 금액)·payment.refundPendingAmount(판매자가 승인했지만 아직 환불하지 않은 금액). - 변경: 취소·반품·교환이 진행 중인 주문상품은 흐름 행동(구매확정·셀러 버튼 등)이
enabled: false로 옵니다(disabled.reason은CONDITION). 실행하면 거절되던 행동을 미리 꺼서 보입니다. 클레임 쪽 행동(요청 철회)은 그대로 켜져 있습니다. - 변경: 배송 뒤 반품으로 끝난 주문상품의 흐름 상태 이름이 「반품 완료」(셀러 「반품」)입니다. 이전에는 「주문 취소」였습니다.
권한 표 수수료·신청 안내·환불 대기 (@sayren/store-sdk 0.30.5 · @sayren/storefront-sdk 0.20.13)
- 추가: 스토어프론트 단계 요약
step.claimable(지금 신청할 수 있는 취소·반품·교환과 기한). - 추가: 판매자 취소
holdRefund, 응답refundHeld. 환불 이력status에HELD(환불 대기)·PROCESSING.POST /v1/payments/refunds/{refundId}/process(SDKpayments.processRefund). - 추가: 흐름 셀러 권한
SELLER_CANCEL_HOLD(주문 취소, 환불은 따로). - 추가: 클레임 승인
holdRefund, 응답refundHeld. 결제 목록refundHeld=true조건과 결제heldRefundAmount. - 추가:
GET /v1/flow-node-types의platformActions(권한 표에 켤 수 있는 플랫폼 행동 — 키·이름·기본 방식·하위 흐름·기간·수수료 가능 여부). - 변경: 행동 입력 칸은 그래프 안에 둡니다 — 셀러 확인 노드 버튼의
input, 셀러·구매자 행동 연결선 조건(on)의input(입력 칸 목록). 흐름 정의의actionInputs는 쓰지 않고, 옛 흐름은 읽을 때 버튼·연결선으로 옮겨집니다. 연결선 조건의 문자열input힌트는 없앴습니다. 음식 배달형 4. - 변경: 그래프 형식이
{"$var": …}를 받지 않습니다(기간은 ISO 8601 문자열).
흐름은 빈 흐름을 편집한 그래프 하나
- 변경: 흐름 만들기는 이름·키만 받습니다. 프리셋 설치 값(
variables)은 무시하고, 기한·횟수 같은 값은 그래프의 노드 설정 안에 실제 값으로 들어 있습니다. 프리셋 요약의variables는 늘 빈 목록입니다. - 변경: 흐름 정의의 커스텀 필드(
fields)·이름 붙인 식(expressions)·주문 입력·속성 선언(requires.orderInputs등)을 쓰지 않습니다. 데이터 블록은 선언 없이 칸을 저장하고, 식은 오프셋 있는 ISO 일시 문자열을 시각으로 읽습니다. 흐름 데이터(flowState.fields)는 셀러에게만 보입니다. - 이미 만든 흐름은 읽을 때 설치 값·이름 붙인 식이 노드 설정으로 펼쳐지고, 다시 게시하면 그 형태로 저장됩니다. 진행 중 주문은 결제 때 버전으로 그대로 진행합니다.
- 프리셋 버전: 주문제작형 3, 음식 배달형 3, 티켓형 3, 숙박 예약형 2.
승인 요청 작업 이름·미리보기 (@sayren/store-sdk 0.30.4)
필드 추가와 오류를 앞당겨 주는 변경입니다. 에이전트 쓰기 승인
- 추가: 승인 요청
operationName(작업 이름), 미리보기targetName(대상 이름). - 추가: 흐름 게시·구매자 적립금 지급·차감·적립 정책 수정의 미리보기
facts·changes. - 변경: 실행하면 실패할 요청(흐름 게시 차단 오류, 적립금 소멸 시각 없음, 잔액 부족)은 드라이런·승인 요청 단계에서 실행과 같은 오류를 줍니다. 승인해도 실패할 승인 요청을 만들지 않습니다.
- 변경: 수동 지급의
400 POINT_EXPIRY_REQUIRED문구가 원인(소멸 시각을 정할 수 없음)과 해결(expiresAt또는 정책expiryDays)을 알려 줍니다.
신청 전 미리보기·흐름 판정 (@sayren/storefront-sdk 0.20.12)
- 추가:
POST /storefront/v1/me/order-items/{orderItemId}/claims/preview(SDKmyClaims.preview). 예상 환불·반품 배송비·취소 수수료(deductAmount)를 접수 없이 줍니다. - 변경: 클레임 API(
POST /storefront/v1/me/order-items/{orderItemId}/claims)도 주문 흐름의 판정을 따릅니다. 흐름이 그 단계에서 신청을 받지 않으면409 INVALID_STATUS, 흐름 기한이 지났으면409 PERIOD_EXPIRED입니다. 지금까지는 상태만 보고 받았습니다. - 수정: 클레임 API로 접수해도 흐름이 정한 취소 수수료(숙박 차감표·티켓 수수료 등)를 예상 환불과 승인 기본 차감에 반영합니다. 지금까지는 흐름 행동으로 접수할 때만 반영했습니다.
프리셋 판매자 취소
- 변경: 티켓형(2)·주문제작형(2)·숙박 예약형(1) 프리셋의 발송·제공 전 상태에 판매자 취소(
SELLER_CANCEL)가 켜집니다. 이미 설치한 흐름은 복사본이라 바뀌지 않습니다. 편집기 권한 표에서 켭니다. - 변경: 음식 배달형(2)은 접수 뒤 조리 중·배달 대기에서 셀러 행동 「가게 사정 취소」(
STORE_CANCEL)로 묶음 전체를 취소합니다(PG 취소 1회). 묶음 진행이라 상품별 판매자 취소는 두지 않습니다.
구매자 요청 철회 행동
- 수정: 정해진 시각 타이머(
at, 체크인·관람일)는 취소·반품이 진행되는 동안 멈추지 않습니다. 지금까지는 철회·거절 뒤 그 시간만큼 기한이 밀렸습니다. 기간 타이머(after)는 그대로 멈춥니다. - 수정: 이름 없는 플랫폼 행동이 키 대신 기본 이름(예: 요청 철회)으로 옵니다.
- 추가: 취소·반품·교환 요청이 「요청」 상태면 구매자 주문상품
actions에WITHDRAW_REQUEST(요청 철회)가 옵니다.POST /storefront/v1/me/order-items/{orderItemId}/actions/WITHDRAW_REQUEST(비회원은 비회원 행동 경로)로 철회합니다.
2026-10-04
흐름 진행 단위 게시 반영
- 수정: 초안
definition.requires.progression·fulfillmentMethods를 바꿔 게시해도 흐름의progression·fulfillmentMethods가 만들 때 값 그대로였습니다. 이제 게시한 버전의 값을 따르고, 진행 단위는 버전마다 고정됩니다. - 추가: 게시 검사 코드
REQUIRES_INVALID, 버전 옮기기409 FLOW_PROGRESSION_MISMATCH(details.from·details.to).
플랫폼 행동 입력 칸·이전 자료 (@sayren/store-sdk 0.30.3 · @sayren/storefront-sdk 0.20.11)
필드·값 추가만 있습니다. 주문 흐름
- 추가: 흐름 조회
actions[].input이 송장 등록(DISPATCH: 배송 방법·택배사·운송장 번호)과 판매자 취소(SELLER_CANCEL: 사유·상세)의 칸을 싣습니다. - 추가: 입력 칸
options의 값·이름 쌍({ value, label }), 조건부 칸when({ key, in }). - 추가: 흐름 상태·단계
earlierAttachments(앞 상태에서 붙인 자료).attachments는 그 자료를 붙여 도착한 상태에서만 옵니다. - 변경:
409 ACTION_NOT_AVAILABLE·409 FLOW_MOVE_NOT_ALLOWED의 문구에 코드를 싣지 않습니다. 코드는details.key·details.reason에 있습니다.
버튼 입력 칸·구매자 단계 요약 (@sayren/store-sdk 0.30.2 · @sayren/storefront-sdk 0.20.10)
필드·값 추가만 있습니다. 주문 흐름
- 추가: 스토어프론트 주문상품
step(type·label·message·deadlineAt·attachments·inputs·actions·data.delivery). - 추가: 흐름 상태
inputs(앞 행동의 입력값, 관리·스토어프론트). - 추가: 행동 입력 형식
textarea·radio·checkbox·boolean, 칸placeholder. 셀러 확인 버튼buttons[].input, 구매자 확인inputs.APPROVE·inputs.REQUEST_CHANGE. - 추가: 행동 입력 검사
400 FLOW_ACTION_INPUT_INVALID(details.issues). 지금까지는 입력 칸과 맞지 않는 값도 받았습니다. - 추가: 스토어프론트 SDK
cart.createInputImageUpload(POST /storefront/v1/uploads/order-inputs).
주문 흐름 확장 (@sayren/store-sdk 0.30.1 · @sayren/storefront-sdk 0.20.9)
필드·엔드포인트·값 추가만 있습니다. 주문 흐름
- 추가: 상태 직접 이동
POST /v1/order-items/{orderItemId}/flow/move, 흐름 조회의moveTargets·branches, 실행 기록GET /v1/order-items/{orderItemId}/flow/runs·GET /v1/flow-runs/{runId}. - 추가: 주문 전체 행동
POST /v1/orders/{orderId}/actions/{key},POST /storefront/v1/me/orders/{orderId}/actions/{key},POST /storefront/v1/guest/orders/{orderId}/actions/{key}. - 추가: 주문
progressStatus(관리 목록·상세, 내 주문), 내 주문 주문상품flowBranches. - 추가: 버전
GET /v1/commerce-flows/{flowId}/versions/{version}·POST …/versions/{version}/migrate, 흐름 조회versions[].inProgress. - 추가: 시뮬레이션
POST /v1/commerce-flows/{flowId}/draft/simulate, 과거 주문 재생POST …/draft/replay, 노드 종류GET /v1/flow-node-types. - 추가: 노드 하위 흐름 호출·병렬 분기·합류·반복 횟수 조건·알림·주문 동기화, 그래프
notes(메모). 게시 검사 코드CALL_TARGET_MISSING·CALL_TARGET_UNPUBLISHED·CALL_CYCLE·FORK_JOIN_INVALID. - 추가: 웹훅
ORDER.FLOW_STATE_CHANGED. 구독하려면 이 버전 이상의 SDK로 웹훅을 파싱하십시오. - 변경: 권한 표에 이름이 없는 플랫폼 행동(취소 요청·판매자 취소 등)에 기본 이름이 붙습니다.
- 삭제: 견적형 프리셋(
quote). 설치한 적이 없는 준비 중 프리셋이었습니다.
흐름 지정을 상품·카테고리로 (@sayren/store-sdk 0.30.0)
호환성 변경이 있습니다. 할당 규칙(조건식)을 없애고 흐름을 상품·카테고리에 지정합니다. 주문 흐름
- 삭제(호환성 변경):
GET·PUT /v1/commerce-flows/assignment-rules,POST /v1/commerce-flows/assignment-rules/test. 이제410 FLOW_ASSIGNMENT_RULES_RETIRED로 답합니다. SDKcommerceFlows.rules·saveRules·testRules와 할당 규칙 스키마를 지웠습니다. - 변경(호환성 변경):
GET /v1/products/{productId}/flow의source가PRODUCT·CATEGORY·PLATFORM입니다(RULE·ruleId없음). - 추가: 상품
flowId(등록·수정·일부 수정·응답), 카테고리flowId(일부 수정·응답, 맨 아래 카테고리만). - 변경: 일반 배송형 기본 흐름의 상태 이름이 결제완료 → 배송준비중 → 배송중 → 배송완료 → 구매확정입니다.
주문 흐름 (#115) (@sayren/store-sdk 0.29.8 · @sayren/storefront-sdk 0.20.8)
필드·엔드포인트·값 추가만 있습니다. 주문 흐름은 순차적으로 열리고, 열리기 전에는 모든 주문이 기본 흐름으로 처리됩니다. 주문 흐름
- 추가: 관리 API
GET /v1/flow-presets,/v1/commerce-flows(설치·조회·초안 저장·검사·게시),/v1/commerce-flows/assignment-rules(할당 규칙·시험),/v1/commerce-flows/secrets. 스코프flow:r·flow:rw. - 추가: 주문상품 흐름
GET /v1/order-items/{orderItemId}/flow, 행동POST /v1/order-items/{orderItemId}/actions/{key}, 사건POST /v1/order-items/{orderItemId}/events/{custom.…}. - 추가: 스토어프론트 주문 상세 주문상품의
flowState·actions, 구매자 행동POST /me/order-items/{orderItemId}/actions/{key}, 비회원POST /guest/orders/{orderId}/items/{orderItemId}/actions/{key}. - 추가: 상품 직접 입력의
key·type(datetime·select·image등)·options, 상품fulfillment.methods(택배·직접 배달·방문 수령), 주문서fulfillmentMethod·pickupLocationId, 픽업 장소/v1/pickup-locations, 조합attributes. - 추가: 업로드
purpose: "flow-attachment", 웹훅ORDER.FLOW_NOTIFICATION.
날짜별 재고·숙박 예약형 (#118) (@sayren/store-sdk 0.29.8 · @sayren/storefront-sdk 0.20.8)
필드·엔드포인트·값 추가만 있습니다. 상품 › 날짜별 재고
- 추가: 상품
inventoryMode(STANDARD·DATED), 달력GET·PUT /v1/products/{productId}/calendar, 스토어프론트GET /products/{productId}/calendar. - 추가: 장바구니 담기·바로 구매의
stay(checkIn·checkOut), 장바구니·주문서·주문상품 응답의stay(박마다 날짜·가격). - 추가: 오류
400 STAY_REQUIRED·STAY_NOT_APPLICABLE·STAY_INVALID,409 DATES_UNAVAILABLE·INVENTORY_MODE_LOCKED·INVENTORY_MODE_NOT_DATED. - 추가: 주문 흐름 프리셋
stay(숙박 예약형). - 추가: SDK
products.getCalendar·products.setCalendar(store-sdk),catalog.getProductCalendar(storefront-sdk), 스키마stayRangeSchema·staySnapshotSchema·calendarDaySchema·stayRequestSchema·stayViewSchema.
2026-10-02
쿠폰 받기·회원가입 쿠폰 (@sayren/store-sdk 0.29.7 · @sayren/storefront-sdk 0.20.7)
필드·엔드포인트·값 추가만 있습니다. 쿠폰
- 추가: 쿠폰 발급 방식
issueMethod에DOWNLOAD(구매자가 스토어프론트에서 받기)·SIGNUP(회원가입 자동 지급). 관리 APIPOST /v1/coupons·GET /v1/coupons?issueMethod=가 받습니다. 두 방식은 회원 전용이고code·perMemberUseLimit을 받지 않습니다.SIGNUP의perMemberIssueLimit은 1만 받습니다. 응답issueMethod는 원래 문자열이라 기존 SDK도 읽습니다. - 추가: 스토어프론트
GET /coupons— 받을 수 있는 다운로드 쿠폰 목록(페이지,productId로 상품 대상 쿠폰만). 회원 토큰이 있으면downloaded·downloadable을 싣습니다. - 추가: 스토어프론트
POST /coupons/{couponId}/download— 쿠폰 받기(회원). 응답은 내 쿠폰 항목 한 장입니다. 오류409 COUPON_ALREADY_DOWNLOADED·COUPON_SOLD_OUT·COUPON_NOT_STARTED. - 추가: 내 쿠폰
GET /me/coupons항목과 관리 API 발급 내역GET /v1/coupons/{couponId}/issues항목의source(MANUAL·DOWNLOAD·SIGNUP). - 추가: SDK
catalog.listCoupons(params)·me.downloadCoupon(couponId), 스키마storefrontCouponSchema. - 변경: 회원가입(이메일 가입·소셜 로그인 첫 가입)에 사용 중인 회원가입 쿠폰을 1장씩 지급합니다. 가입 응답 형태는 그대로입니다.
주문서 상품 대표 이미지 (@sayren/storefront-sdk 0.20.6)
필드 추가만 있습니다.
- 추가: 스토어프론트 주문서 응답(
POST /checkout)의items[].thumbnailUrl— 주문서 시점의 상품 대표 이미지입니다. 없으면null이고, 장바구니 줄의thumbnailUrl과 같은 값입니다.
주문·상품 번호 (@sayren/store-sdk 0.29.6 · @sayren/storefront-sdk 0.20.5 · @sayren/mcp 0.23.7, 템플릿 0.2.15)
필드 추가와 조회 추가만 있습니다. 기존 id(orderId·productId 등)와 경로는 그대로입니다. 주문·상품 번호
- 추가: 주문번호
orderNo(14자리 숫자), 상품주문번호orderItemNo, 클레임번호claimNo, 상품번호productNo(상점별 1부터), 조합 번호variants[].variantNo(상점 안에서 유일), 장바구니items[].productNo. 관리 API·스토어프론트 API의 주문·클레임·상품 응답과 웹훅ORDER.*(data.orderNo)·CLAIM.*(data.claimNo)에 실립니다. 기존 주문·상품에도 번호가 채워져 있습니다. - 추가: 관리 API
GET /v1/orders?orderNo=— 기간 없이 주문번호로 찾습니다(하이픈 허용).orderNo가 있으면orderedFrom을 생략할 수 있습니다.keyword도 주문번호를 받습니다. - 추가: 관리 API
GET /v1/products?productNo=. - 추가: 스토어프론트
GET /products/{productId}(리뷰·문의 목록 포함)와 비회원 주문 조회POST /guest/orders/{orderId}가 경로에 숫자 번호(productNo·orderNo)를 받습니다. 상품번호는 그 상점 안에서 찾습니다. - 변경: 새 결제의 PG 주문번호(토스페이먼츠
orderId·포트원paymentId)가{주문번호}-{시도 순번}입니다. 결제 내역 API의pgOrderId가 이 값입니다. 이전 결제는 그대로 결제 시도 id입니다. - 추가: SDK
formatOrderNo(4자리 하이픈 표기)·parseOrderNo. - 추가: 템플릿 0.2.15 주문 내역·주문 상세·비회원 주문 조회에 주문번호(4자리 하이픈 표기)와 상품주문번호.
- 변경: 템플릿 0.2.15 상품 주소가
/products/{productNo}입니다. 예전 주소(/products/prod_…)는 상품번호 주소로 301 이동합니다. MCP 규칙product-link(권고)가 상품 id 링크를 알립니다.
MCP 대화에서 승인 요청 처리 (@sayren/mcp 0.23.6)
필드 추가와 권한 완화만 있습니다. MCP 대화에서 승인하기
- 추가: MCP 도구
list_approvals(승인 요청 목록·한 건)와decide_approval(승인·거절). 원격 MCP에서는 MCP 클라이언트가 확인 창(elicitation)을 띄우고 사람이 수락했을 때만 결정합니다. 확인 창을 지원하지 않는 클라이언트와 로컬 MCP는 승인 화면 링크만 알려 줍니다. - 변경: 승인 요청 목록
GET /v1/approval-requests와 남의 요청 단건 조회를 원격 MCP·AI 에이전트용 토큰의 OWNER·ADMIN도 씁니다(이전에는 상점 플랫폼 로그인만). 승인 APIapprove·reject는 여전히 에이전트에게403 AGENT_OPERATION_DENIED입니다. - 추가: 원격 MCP 쓰기 도구의 승인 대기 안내에
decide_approval. 감사 로그 상세 기록APPROVAL_DECIDED(metadata.via=MCP_ELICITATION).
버전의 기준 템플릿 버전 (@sayren/mcp 0.23.5, 템플릿 0.2.14)
필드 추가와 값 판정 수정입니다. 템플릿으로 쇼핑몰 열기
- 수정: 편집으로 만든 버전의
templateVersion이 그 시점 카탈로그 버전으로 적혀 파일을 바꾸지 않아도 카탈로그가 오를 때마다 함께 올랐습니다. 이제 버전 파일의package.jsonsayren.templateVersion이고, 없으면 발행 버전의 값을 이어받습니다. 이미 만든 버전의 값은 그대로입니다. - 추가: 템플릿 0.2.14
package.json의sayren필드(template·templateVersion).sayren-mcp create·원격get_template_file도 같은 값을 싣습니다.
컬렉션 홈 섹션 (@sayren/mcp 0.23.4, 템플릿 0.2.13)
API 변경은 없습니다. 컬렉션
- 추가: 템플릿 0.2.13 레이아웃 상품 섹션의
source에{ "collection": "주소" }. 섹션이GET /collections/{slug}/products로 컬렉션 상품을 그리고, 컬렉션이 없거나 숨김·기간 밖이면 섹션을 그리지 않습니다.moreLink의 「더 보기」는/collections/{slug}로 갑니다. 옛 레이아웃은 그대로 읽힙니다. - 추가: MCP 편집 안내(
get_editing_guide·get_scaffold_plan의extensionPoints)에 컬렉션 섹션 쓰는 법.
적립금 화면 안내 (@sayren/storefront-sdk 0.20.4 · @sayren/mcp 0.23.4, 템플릿 0.2.13)
- 추가: 스토어프론트 상품 상세
GET /products/{productId}의purchasePoint. 지금 가격 1개 기준 구매 적립 예정액을 서버가 상점·상품 적립률로 계산합니다. 구매 적립이 꺼져 있거나 적립하지 않는 상품이면null입니다. 옛 서버 응답은 SDK가null로 읽습니다. - 추가: 템플릿 0.2.13 상품 상세 「구매 시 n원 적립」, 후기 블록의 리뷰 혜택 안내(
GET /point-policy), 내 적립금 화면(/points, 잔액·30일 안 소멸 예정·내역). - 문서: 결제 연동 가이드 맨 앞에 「5분 요약」(SDK 주문 예시, 스토어프론트는 정보만 넘기는 원칙).
적립금 전액 결제 (@sayren/store-sdk 0.29.5 · @sayren/storefront-sdk 0.20.3 · @sayren/mcp 0.23.3, 템플릿 0.2.12)
필드 추가와 요청 완화만 있습니다. 적립금 · 결제 흐름
- 변경: 적립금이 결제 금액 전체를 덮으면 0원 결제입니다. 남는 결제 금액이 1~99원일 때만 적립금을 줄여 100원을 남깁니다(
points.adjustReasonMIN_PAYMENT). 전액 사용은 사용 단위를 보지 않습니다. store-sdkpointUseOf·quotePricing이 같은 규칙입니다. - 추가: 금액 미리보기 응답의
paymentRequired.false면 결제수단으로 낼 금액이 없습니다. 판단은 서버가 하고, 스토어프론트는 금액을 계산하지 않고 이 값으로 결제수단 영역을 숨깁니다.payable은 0원(적립금 전액)도true입니다. - 변경: 결제 시작 요청의
option이 선택입니다. 결제가 필요 없는 주문은 생략하고, 결제가 필요한데 생략하면400 VALIDATION_FAILED입니다. 0원 결제는 결제창 없이 그 요청에서 주문을 만들고 응답이status: "completed"·orderId,payUrl·attemptId·option이null입니다. 주문의payment.method·approvedMethod는POINT,totalAmount는0입니다. 0원 결제는 재시도할 수 없고(409 ALREADY_PROCESSED) 현금영수증을 신청하면400 CASH_RECEIPT_NOT_AVAILABLE입니다. 취소·반품은 현금 환불 없이 적립금만 돌려줍니다. - 추가: 결제 시작의 헤더
Idempotency-Key(선택). 같은 키의 재요청은 처음 결과를, 같은 키의 동시 요청은409 IDEMPOTENCY_KEY_IN_USE를 돌려줍니다. - 수정: SDK
payments.start가pointAmount를 결제 시작 본문에 싣습니다(이전에는 빠져 브라우저 도우미로는 적립금을 쓸 수 없었습니다).option은 선택입니다. - 추가: 템플릿 0.2.12 주문서가
paymentRequired가false면 결제수단을 숨기고 「적립금으로 결제」로 바로 주문합니다. - 수정: 템플릿 0.2.12 컬렉션 화면이 컬렉션 기본 정렬(
productSort,latest같은 값)을 정렬 선택에 맞게 보입니다. 이전에는 늘 「진열순」으로 보였습니다(상품 순서는 맞았습니다).
판매량 상위 컬렉션 (@sayren/store-sdk 0.29.4 · @sayren/storefront-sdk 0.20.2)
필드 추가뿐입니다. 판매량을 사용하지 않는 컬렉션의 동작은 그대로입니다. 컬렉션
- 추가: 조건
{ field: "bestSelling", days: 7 | 30 | 90, top: 1~100 }— 다른 조건을 만족하는 판매 중 상품 중 기간 판매 수량 상위 N개입니다. 판매 수량은 실결제 주문의 결제 수량 − 취소·반품 수량이고 날짜는 주문 시각의 한국 날짜입니다. 판매가 없는 상품은 담지 않고, 동률은 최근 등록 → 상품 id 순입니다. 집계는 최대 10분 늦습니다. - 추가: 상품 정렬
BEST_SELLING(판매량순)을 만들기·수정·미리보기에서 받습니다. 판매량 상위 조건이 있으면 정렬을 생략했을 때 기본값입니다. 기간은 그 조건의 기간, 없으면 30일입니다. - 추가: 컬렉션 응답·미리보기 응답의
salesComputedAt(판매량 기준 시각), 스토어프론트GET /collections/{slug}의salesComputedAt. 판매량을 사용하지 않거나 집계 전이면null입니다. - 추가: store-sdk 순수 함수
rankBestSelling·compareBySales·bestSellingRuleOf, 상수COLLECTION_BEST_SELLING_DAYS·MAX_COLLECTION_BEST_SELLING_TOP. - 스토어프론트 정렬 값은 그대로입니다. 판매량순 컬렉션의
productSort는manual이고sort=manual이 판매량 순입니다.
적립금 결제 사용·취소 환불 (@sayren/store-sdk 0.29.3 · @sayren/storefront-sdk 0.20.1 · @sayren/mcp 0.23.2, 템플릿 0.2.11)
필드 추가만 있습니다. 적립금 사용이 준비 중인 동안에는 정책 조회의 useAvailable이 false이고 적립금 사용 요청이 409 POINTS_UNAVAILABLE입니다. 적립금
- 추가: 적립금 정책의
use(enabled·minBalance·minAmount·unit·maxRatioBp·includeDeliveryFee)와 조회의useAvailable. 필드가 없는 이전 응답은 끔으로 읽습니다. - 추가: 주문서 응답의
points(잔액·최대 사용액·사용 단위·최소 사용액·최소 보유액, 비회원·사용 끔이면null),amounts.pointAmount. - 추가: 금액 미리보기·결제 시작 요청의
pointAmount. 미리보기 응답의amounts.pointAmount·items[].pointAllocation·points(balance·maxUsable·adjustReason·rejectReason). 적용 순서는 즉시할인 → 쿠폰 → 적립금이고 결제 금액은 100원 이상 남깁니다(전액 결제는 위 「적립금 전액 결제」). 오류는400 POINT_NOT_APPLICABLE(details.reason)·409 POINT_BALANCE_CHANGED·409 POINTS_UNAVAILABLE입니다. - 추가: 주문의
payment.pointAmount·items[].pointAllocation(관리 API·구매자 주문 조회), 주문 웹훅 데이터의pointAmount. - 추가: 직권취소·클레임 승인 응답, 클레임 웹훅(
CLAIM.*)·취소 웹훅의pointRefundAmount, 구매자 클레임 접수 응답의pointRefundAmount, 클레임 조회의expectedPointRefundAmount, 결제 내역 환불의pointRefundAmount.refundAmount는 현금 환불만 뜻합니다. 적립금을 쓰지 않은 주문은 모두0입니다. - 추가: 적립금 내역 유형
USE_RESERVE(결제 사용)·USE_RELEASE(결제 실패·만료로 되돌림)·REFUND_RESTORE(환불 반환), 적립 묶음 출처REFUND_RESTORE. - 추가: store-sdk 순수 함수
pointUseOf·proratedPointRefund·splitRefund·pointRestoreExpiresAtOf,quotePricing입력points·결과pointAmount.proratedPaidRefundBase는 적립금 몫(pointAllocation)을 뺀 현금 기준입니다. - 추가: 템플릿 0.2.11 주문서에 적립금 칸(적용·전액 사용·빼기)이 생겼습니다. 회원이고 상점이 사용을 켰을 때만 보입니다.
조건 자동 컬렉션 (@sayren/store-sdk 0.29.2)
필드 추가뿐입니다. 기존 직접 선택 컬렉션의 동작은 그대로입니다. 컬렉션
- 추가:
POST /v1/collections가type: "AUTOMATIC"과 조건rules(모두 만족, 최대 10개)를 받습니다. 조건은 등록일(createdWithinDays, 1~365일)·카테고리(category, 하위 포함, 20개까지)· 가격(price, 즉시할인 반영 판매가,min·max)·할인 중(discounted)입니다. 같은 조건은 한 번만 사용합니다. 조회할 때마다 조건을 만족하는 판매 중 상품을 계산하고 결과를 저장하지 않습니다.PATCH의rules로 조건을 통째로 바꿉니다. 정렬을 생략하면 조건 자동은LATEST이고MANUAL은 받지 않습니다(400 COLLECTION_SORT_INVALID). - 추가: 컬렉션 응답의
rules(직접 선택은null). 조건 자동의productCount는 지금 조건을 만족하는 판매 중 상품 수이고,GET /v1/collections/{collectionId}/products는 그 상품을 기본 정렬 순으로 돌려줍니다(position은 순위,addedAt은 상품 등록 시각). - 추가:
POST /v1/collections/preview(스코프category:r) — 저장하지 않고 조건으로 나오는 상품 수와 앞 20개를 봅니다. 데이터를 바꾸지 않아 AI 에이전트의 쓰기 횟수에 세지 않습니다. SDKcollections.preview, 순수 함수matchesCollectionRules·collectionRulesPredicate. - 추가: 오류
400 COLLECTION_RULES_REQUIRED·COLLECTION_RULES_NOT_ALLOWED·COLLECTION_PRODUCTS_NOT_ALLOWED·COLLECTION_CATEGORY_NOT_FOUND·COLLECTION_SORT_INVALID. 조건 자동 컬렉션에 상품을 담거나 빼면409 COLLECTION_NOT_MANUAL입니다. - 변경: 조건 자동 컬렉션이 조건으로 사용하는 카테고리는 지울 수 없습니다(
DELETE /v1/categories/{categoryId}→409 CATEGORY_IN_USE,error.details.collectionIds).strategy=cascade는 하위 카테고리까지 봅니다. 조건 자동 컬렉션이 없는 상점은 영향이 없습니다. - 변경: SDK
collectionCreateRequestSchema가productSort기본값을 채우지 않습니다. 서버가 유형에 맞춰 채웁니다(직접 선택MANUAL). 보내는 요청의 결과는 같습니다. - 스토어프론트 API 응답 형태는 그대로입니다. 조건 자동 컬렉션의
GET /collections/{slug}/products는 정한 순서가 없어sort=manual을 기본 정렬로 봅니다.
적립금 기존 잔액 이전
API 형태는 그대로입니다. 잔액은 바뀌지 않습니다.
- 변경: 적립금 원장 이전에 쌓인 잔액을 기존 적립금으로 옮깁니다. 구매자·상점 적립금 내역에 유형
OPENING(기존 적립금) 한 줄이 생기고, 잔액 조회의 적립 묶음(lots)에 출처OPENING이 보입니다. 기존 적립금의 소멸 시각은 적립금 설정을 연 날 + 상점 유효 기간이고, 유효 기간을 설정하지 않은 상점은 설정할 때까지 소멸하지 않습니다. 적립금
적립금 — 리뷰 적립 기본값 끔·정책·구매 적립·소멸·조정 (@sayren/store-sdk 0.29.1)
동작 변경이 있습니다. 기존 필드의 이름과 형태는 그대로입니다. 적립금
- 변경(동작 변경): 리뷰를 작성하면 주던 적립금(리뷰 500원, 사진 리뷰 500원 추가)을 더 주지 않습니다. 적립금은 상점이 정책을 설정해 켤 때만 지급하고,
정책이 없으면 모두 끔입니다. 리뷰 작성 응답(
POST /me/order-items/{orderItemId}/review)의rewardPoint는 정책이 꺼져 있으면0입니다. 이미 지급된 적립금은 그대로이고, 구매자가 리뷰를 삭제하면 지금처럼 그 리뷰로 받은 금액을 회수합니다(잔액이 모자라면 0까지). 같은 리뷰를 동시에 두 번 삭제해도 한 번만 회수합니다. - 추가:
GET /v1/store/point-policy(스코프promotion:r)·PUT /v1/store/point-policy(promotion:rw). 리뷰 적립(reviewReward, 사진은 추가분)·구매 적립(purchaseEarn.rateBp, 만분율 03000)·유효 기간(1825일)입니다. 적립을 하나라도 켜려면 유효 기간이 있어야 합니다(expiryDays, 30400 POINT_EXPIRY_REQUIRED). 적립금 설정이 준비 중이면 저장이409 POINTS_UNAVAILABLE이고 조회의available이false입니다. 조회의notice는 상점에 보일 안내입니다(REVIEW_REWARD_PAUSED·POINTS_AVAILABLE·null). - 추가: 상품의
pointEarnRateBp(등록·전체 수정·부분 수정·조회).null이면 상점 기본 적립률,0이면 적립 안 함입니다. 전체 수정(PUT)에서 생략하면 지금 값을 유지합니다. 구매 적립은 구매확정 때 실결제 금액(배송비 제외) × 결제 시점 적립률이고, 비회원·테스트 결제 주문은 적립하지 않습니다. - 추가: 구매자 적립금
GET /v1/customers/{customerId}/points·/points/history(customer:r), 상점 전체 내역GET /v1/points/history(promotion:r), 지급·차감POST /v1/customers/{customerId}/points/adjustments(promotion:rw,Idempotency-Key필수,409 POINT_BALANCE_INSUFFICIENT). 소멸 시각이 지난 적립금은 소멸하고 내역에EXPIRE로 남습니다. - 에이전트의 정책 수정·지급·차감·상품 적립률 변경은 승인 대상입니다. SDK
store.getPointPolicy·updatePointPolicy,customers.getPoints·listPointHistory·adjustPoints,points.listHistory, 순수 함수resolvePointPolicy·reviewRewardPointOf·purchaseEarnRateOf·pointEarnOf·pointExpiresAtOf.
결제창 없는 결제 완료·응답 결제수단 확장 (@sayren/storefront-sdk 0.20.0)
호환성 변경이 있습니다. 적립금(준비 중)으로 결제 금액 전체를 내는 주문을 위해 SDK를 먼저 바꿉니다. 지금 서버 응답은 그대로입니다.
- 변경(호환성 변경): 주문 응답의
payment.method(GET /me/orders, 비회원 주문 조회)를 이 SDK가 모르는 값도 받는 문자열로 읽습니다. 적립금 전액 결제 주문은POINT가 옵니다. 0.19 이하 SDK는POINT를 받으면 주문 파싱에 실패하므로, 적립금을 켜기 전에 0.20 이상으로 올리십시오. TypeScript 타입은ResponsePaymentMethod(PaymentMethod | string)입니다. 결제 옵션(요청)의method는 그대로 enum입니다. - 변경(호환성 변경): 결제 시작·재시도 응답(
POST /checkout/{checkoutId}/payment,POST /payments/{paymentId}/attempts)의payUrl·attemptId·option이 nullable입니다. 결제창 없이 끝난 결제(status: "completed")에서 null입니다. 지금 서버는 늘 값을 싣습니다. - 추가: 결제 시작 응답의
status(pending결제창을 엶 ·completed결제창 없이 결제 완료)와orderId(completed일 때 주문 번호, 그 밖에는null). 필드가 없는 응답은pending·null로 읽습니다. - 변경:
payments.start·retry·open은 결제 시작 응답이completed면 결제창을 열지 않고(미리 연 팝업은 닫습니다) 바로COMPLETED결과를 돌려줍니다. 모르는status나payUrl이 없는 응답은 결제 상태 조회(GET /payments/{paymentId})로 결과를 정합니다. SDK 결과로 화면을 분기하는 코드는 그대로 동작합니다.payUrl을 직접 여는 코드는status를 먼저 보십시오. 결제 흐름 - 추가: 적립금 조회
GET /point-policy(인증 없음, 리뷰·구매 적립과 리뷰 작성·수정 기한review)·GET /me/points(잔액·30일 안 소멸 예정)·GET /me/points/history. SDKcatalog.getPointPolicy,member.getPoints·listPointHistory. 적립금
스토어프론트 템플릿 컬렉션 화면 (@sayren/mcp 0.23.1, 템플릿 0.2.10)
API 변경은 없습니다.
- 추가: 템플릿 라우트
/collections/$slug(대표 이미지·제목·설명, 상품 그리드, 정렬?sort=·페이지?page=, 정렬을 생략하면 컬렉션 기본 정렬)와/collections(노출 중인 컬렉션 모음).404 COLLECTION_NOT_FOUND는 없는 화면으로 그립니다. 목록 보기 이벤트의listId는collection:{slug}입니다. - 추가: 레이아웃 설정(
src/site/layout.json)의 사이트 안 경로에/collections와 그 아래 경로를 쓸 수 있습니다. 옛 설정은 그대로 유효합니다.
컬렉션 (@sayren/store-sdk 0.29.0 · @sayren/storefront-sdk 0.19.0)
새 리소스입니다. 기존 필드의 이름과 형태는 그대로입니다.
- 추가: 관리 API
/v1/collections(스코프category:r·category:rw). 목록(q·type·state·productId, 응답stateCounts)·만들기·조회· 수정(PATCH, 준 항목만)·삭제와 담긴 상품 보기·바꾸기(PUT)·붙이기(POST, 500개)·빼기(DELETE …/products/{productId}). 지금은 직접 선택(MANUAL)만 만들고 유형은 바꿀 수 없습니다. 쓰기마다revision이 오르고, 본문에 읽은revision을 주면 그 사이 바뀐 경우409 COLLECTION_CHANGED입니다. 상점당 200개, 컬렉션당 상품 1,000개입니다. 상품을 삭제하면 컬렉션에서도 빠집니다. SDKcollections.*. 컬렉션 - 추가: 스토어프론트 API
GET /collections·GET /collections/{slug}·GET /collections/{slug}/products. 노출이 켜져 있고 기간 안인 컬렉션만 보이고, 숨김·기간 밖·없음은 모두404 COLLECTION_NOT_FOUND입니다. 상품은 판매 중만ProductCard페이지로 오고sort(manual과 상품 검색 정렬)·minPrice·maxPrice·page·size를 받습니다. SDKcatalog.listCollections·getCollection·listCollectionProducts. 컬렉션 - 추가: 오류 코드
COLLECTION_NOT_FOUND·COLLECTION_SLUG_TAKEN·COLLECTION_LIMIT_EXCEEDED·COLLECTION_PRODUCT_LIMIT_EXCEEDED·COLLECTION_CHANGED·COLLECTION_TYPE_IMMUTABLE·COLLECTION_PERIOD_INVALID·COLLECTION_PRODUCT_NOT_FOUND·COLLECTION_NOT_MANUAL.
원격 MCP 템플릿 원본 읽기 (@sayren/mcp 0.23.0)
API 변경은 없습니다.
- 추가: 원격 MCP(
https://mcp.sayren.app/mcp)의list_template_files·get_template_file. 호스팅 카탈로그 템플릿의 지금 버전(새 사이트의 첫 작업 트리와 같은 파일)을 읽기만 합니다. 입력templateId(생략하면 기본 템플릿)·version(지금 버전만, 다르면 오류)을 받고, 목록 응답에templateId·version·templates(고를 수 있는 템플릿)가 옵니다. 이진 파일은path·encoding(base64)·contentJSON입니다. 원격 MCP - 변경: 로컬 MCP(
@sayren/mcp)의 두 도구는 같은 입력 이름을 갖지만 npm 패키지에 든 템플릿 하나만 줍니다.templateId·version을 주면 원격 MCP를 안내하는 오류입니다. 인자 없이 부르는 기존 호출은 그대로입니다.
스토어프론트 CLI (sayren 0.4.0)
API 변경은 없습니다.
- 추가:
npx sayren init [폴더] [--template <id>] [--store <storeId>] [--yes]. 템플릿을 골라 호스팅 사이트를 만들고(POST /v1/storefront/site)pull과 같은 폴더(.mcp.json·.env·.sayren/state.json)로 받습니다. 사이트가 이미 있으면 만들지 않고pull을 안내합니다. 비대화형은--template과--yes가 필요합니다. 사이트 만들기 - 변경:
npx sayren deploy가 올리기 전에 로컬 빌드를 합니다. 의존성이 설치된 폴더(node_modules가 있는 폴더)면package.json의build스크립트를npm run build로 돌리고, 실패하면 빌드 출력의 마지막 줄들을 보여 주고 올리지 않습니다(종료 코드1). 의존성을 설치하지 않은 폴더는 알리고 건너뜁니다.--skip-build로 끕니다. 서버 빌드는 그대로 합니다. CLI로 호스팅 사이트 고치기
결제수단 반복 실패 경고 (@sayren/store-sdk 0.28.3)
필드 추가만 있습니다. 기존 필드의 이름과 형태는 그대로입니다.
- 추가: 결제 설정 조회(
GET /v1/store/payment-settings)의warnings. 같은 PG·결제수단·간편결제사가 PG 설정 문제(구매자가 고칠 수 없는 실패)로 최근 24시간에 3번 이상 실패한 조합이고, 항목은provider·method·easyPayProvider·code(PG 실패 코드, 없으면null)·count·lastAt·message(마지막 PG 원문 사유)입니다. 마지막 실패가 최근인 순이고 없으면 빈 배열입니다. 판정 기준은 바뀔 수 있습니다. SDK 타입PaymentFailureWarning. PG 연결하기
출고지·반품지 주소록 조회 개방
- 변경: 주소록 목록(
GET /v1/seller-addresses)·상세(GET /v1/seller-addresses/{addressId})를store:r스코프만으로 부를 수 있습니다. 전에는 상점 플랫폼으로 로그인한 소유자·관리자만 불렀고, 액세스 토큰·연동 앱·AI 에이전트는403 INSUFFICIENT_ROLE이었습니다. 응답 형태는 그대로입니다. 등록·수정·삭제·기본 지정은 지금처럼 상점 플랫폼으로 로그인한 소유자·관리자만 합니다. 배송비와 출고지·반품지
템플릿 링크 미리 불러오기·자산 캐시 (@sayren/mcp 0.22.2)
API 변경은 없습니다.
- 변경:
create로 받는 스토어프론트 템플릿(0.2.9)의 라우터가defaultPreload: "intent",defaultPreloadStaleTime: 30000입니다. 링크에 마우스를 올리거나 포커스하면 다음 화면의 loader가 스토어프론트 API를 미리 부르고, 30초 안에 같은 링크로 다시 부르지 않습니다. 주문서(/checkout)·주문 완료 라우트는preload: false입니다. loader에서 주문서 세션 생성처럼 상태를 바꾸는 호출을 하면 그 라우트에preload: false를 두십시오. - 추가: 템플릿
public/_headers. 해시가 붙은 빌드 파일(/assets/*)에Cache-Control: public, max-age=31536000, immutable을 줍니다. HTML과 해시 없는 파일(파비콘 등)은 그대로max-age=0, must-revalidate입니다.public/assets/에는 파일을 두지 마십시오.
결제 실패의 결제수단 사용 불가 안내 (@sayren/storefront-sdk 0.18.4)
필드 추가만 있습니다. 기존 필드의 이름과 형태는 그대로입니다.
- 추가: 결제 상태(
GET /payments/{paymentId})의lastFailure.optionUnavailable. 상점의 PG 설정 문제처럼 구매자가 고칠 수 없는 실패면true이고, 이때lastFailure.message는 「이 결제수단은 지금 사용할 수 없습니다. 다른 결제수단을 선택하십시오」입니다. 같은 결제 옵션으로 다시 시도해도 실패하므로 다른 결제수단을 고르게 하십시오. PG 원문 사유는 상점 플랫폼 결제 내역에 남습니다. SDK 결제 결과(FAILED)에도optionUnavailable이 실립니다. 결제 흐름
리뷰 랭킹순 정렬 기준
- 변경: 스토어프론트 상품 리뷰 목록(
GET /products/{productId}/reviews)의sort=helpful(랭킹순)이 평점 높은 순과 같던 것을 바꿨습니다. 사진 있는 리뷰를 먼저, 그다음 평점 높은 순, 평점이 같으면 최신 순입니다. 도움돼요 수는 반영하지 않습니다. 정렬 값(latest·ratingDesc·ratingAsc·helpful)은 그대로입니다. 카탈로그
2026-10-01
상점 정보 수정 드라이런의 변경 미리보기
- 변경: 상점 정보 수정(
PATCH /v1/store)의 드라이런(x-sayren-dry-run: 1)과 승인 요청의preview.changes에 변경 전후를 싣습니다. 본문에 준 필드 중 값이 달라지는 것만 오고, 배송비·환불 정책은 항목마다(shippingPolicy.freeThreshold등) 나뉩니다. 판정은 그대로 승인 대기입니다. 드라이런
리뷰 옵션별 필터·내가 쓴 리뷰·리뷰 사진 (@sayren/storefront-sdk 0.18.3)
필드 추가만 있습니다. 기존 필드의 이름과 형태는 그대로입니다.
- 추가: 스토어프론트 상품 리뷰 목록(
GET /products/{productId}/reviews)의 쿼리variantId와 리뷰 항목의variantId. 상품 상세variants[].variantId와 같은 값이고, 주면 그 옵션(조합)으로 산 리뷰만 옵니다. 주문 정보를 찾지 못한 리뷰는null입니다.summary는 필터와 무관하게 상품 전체 기준입니다. SDKcatalog.listProductReviews(productId, { variantId }). 카탈로그 - 추가: 스토어프론트
GET /me/reviews(구매자 로그인) — 내가 쓴 리뷰를 최신순으로 돌려줍니다. 항목은reviewId·productId·productName·thumbnailUrl·optionName·rating·content·images·sellerReply·blinded·editable(작성 후 30일까지)·editableUntil·createdAt입니다. SDKreviews.listMine({ page, size }). 회원 · 리뷰 · 문의 - 추가: 스토어프론트
POST /me/uploads(구매자 로그인) — 리뷰 사진 업로드 자리를 발급합니다. 본문은filename·purpose(review-image, 생략 가능)·size이고 응답은url·uploadUrl입니다.uploadUrl에 파일을 PUT한 뒤url을 리뷰 작성·수정의images에 넣습니다. 형식·크기는 상품 이미지와 같고(400 UNSUPPORTED_FILE_TYPE·413 FILE_TOO_LARGE), 회원마다 발급 한도가 있습니다(429 TOO_MANY_REQUESTS). SDKreviews.createImageUpload.
상품 이미지 일부 수정, 드라이런 본문 검증
- 추가:
PATCH /v1/products/{productId}의images. 준 목록으로 이미지를 통째로 바꾸고 첫 번째가 대표입니다. 항목 형식은 등록과 같습니다. 에이전트 정책은 그대로이고 이미지만 바꾸면 승인 없이 실행됩니다. 상품 이미지 등록 - 변경:
x-sayren-dry-run: 1요청도 실행과 같은 본문 검증을 거칩니다. 형식이 맞지 않으면 판정 대신400 VALIDATION_FAILED입니다.
MCP 상품 이미지 업로드 (@sayren/mcp 0.22.0)
- 추가: MCP 도구
upload_image(로컬·원격 공통,product:rw). 입력은sourceUrl(https) 또는base64+contentType중 하나와 선택filename이고, 출력은url·contentType·size입니다.POST /v1/uploads(purpose: product-image)로 자리를 받아 올리므로 형식·크기 제한이 같습니다. MCP 도구 레퍼런스
사업자 정보·상품 정가·상품 문의 유형 (@sayren/store-sdk 0.28.2 · @sayren/storefront-sdk 0.18.2)
필드 추가만 있습니다. 기존 필드의 이름과 형태는 그대로입니다.
- 추가:
PATCH /v1/store·GET /v1/store의 사업자 정보 —businessName(상호)·representativeName(대표자명)·mailOrderSalesNumber(통신판매업 신고번호)·businessAddress(사업장 주소)·customerCenterEmail(고객센터 이메일)·privacyOfficerName·privacyOfficerEmail(개인정보 보호책임자). 정하지 않았으면null이고,PATCH에null을 주면 지웁니다. - 추가:
PATCH /v1/store의businessNumber(사업자등록번호). 숫자 10자리이고 하이픈을 넣어도 됩니다. 숫자만 저장합니다. 형식이 틀리면 400입니다.customerCenterPhone은null로 지울 수 있습니다. - 추가: 스토어프론트
GET /store의businessName·representativeName·businessNumber·mailOrderSalesNumber·businessAddress·customerCenterEmail·privacyOfficerName·privacyOfficerEmail. 푸터 표기용입니다. 상점 공개 설정 - 추가: 스토어프론트 상품 목록·상세(
GET /products·GET /products/{productId}, 찜 목록)의originalPrice(정가). 비교용 표시 값이고 결제 금액은discountedPrice ?? salePrice입니다. 정가가 없으면null입니다. 가격 표시 - 추가: 스토어프론트 상품 문의 목록(
GET /products/{productId}/inquiries)과 내 상품 문의(GET /me/inquiries)의productId·productName·thumbnailUrl(상품 대표 이미지)·category(문의 유형). 상품이 지워졌으면productName·thumbnailUrl은null입니다. - 추가: 상품 문의 작성(
POST /products/{productId}/inquiries)의category(PRODUCT·DELIVERY·RETURN·EXCHANGE·ETC). 생략하면PRODUCT입니다. - MCP 템플릿: 상품 카드·상세가 정가 취소선과 정가 기준 할인율을 표시하고, 푸터가 사업자 정보를 표시합니다(값이 없는 항목은 표시하지 않습니다).
원격 MCP에서 상점 정보 수정 요청
- 변경: 원격 MCP(
https://mcp.sayren.app/mcp) 연결이store:rw를 받을 수 있습니다. 보호 리소스 메타데이터scopes_supported에 더했습니다. 상점 정보 수정(PATCH /v1/store)은 AI 에이전트 요청이면 승인 대기(202 APPROVAL_REQUIRED)입니다. 이미 연결한 도구는 다시 연결해야 받습니다. - 변경: 구매자 로그인 설정(
/v1/store/login-settings·/v1/store/auth-providers/**)에x-console-only: true를 더했습니다. 상점 플랫폼에서만 합니다. - 변경: AI 에이전트 요청 중 승인해도 실행되지 않던 쓰기를 승인 대기 대신
403 AGENT_OPERATION_DENIED로 거부합니다 — 구매자 로그인 방식 변경 (PATCH /v1/store/login-settings·PATCH /v1/store/auth-providers/{provider}), 약관 버전·주소(termsVersion·privacyVersion·termsUrl·privacyUrl)를 바꾸는 상점 수정. 약관 필드가 없는 상점 수정은 그대로 승인 대기입니다. - MCP:
list_operations가 토큰에 없는 스코프가 필요한 오퍼레이션에토큰 스코프 없음을 붙이고,describe_operation이missingTokenScopes를 줍니다.403 INSUFFICIENT_ROLE결과에 다시 연결해 권한을 늘리라는 다음 할 일을 붙입니다.
요금제 개편 — Free·Pro·프리미엄·엔터프라이즈 (@sayren/store-sdk 0.28.0 · @sayren/mcp 0.20.0)
요금제를 4단계로 다시 나눴습니다. 공개 API의 변경은 가산입니다. 베타 기간에는 새 한도를 관측만 합니다. 요금제와 한도
- 추가:
GET /v1/public/plans— 인증 없는 요금제 비교표(가격·부가세 포함 표시가·기능 키 값). 5분 캐시할 수 있습니다. store-sdkplans.listPublic(). 요금제 값은 바뀔 수 있으니 코드에 수치를 두지 말고 이 응답을 읽으십시오. 요금제 비교표 API - 추가: 요금제 코드
PREMIUM.BASIC·BUSINESS는 더 쓰지 않습니다(베이직 → Pro, 프로 → 프리미엄, 비즈니스 → 엔터프라이즈로 옮겼습니다). - 호환성 주의:
@sayren/store-sdk0.27.0 이하는PREMIUM코드를 몰라 프리미엄 상점에서subscription.get()의 응답 검증이 실패합니다. 0.28.0으로 올리십시오. 0.28.0부터 응답의 요금제 코드(plan.code, 오류details.plan)와 지원 등급은 모르는 값도 문자열로 받습니다. - 추가:
GET /v1/store/subscription의limits.aiReadsMonthly·storefrontRequestsMonthly·apiLogRetentionDays·auditLogRetentionDays,features.adminApi·analytics,usage.aiReads·storefrontRequests,aiReads(MCP 읽기 한도 요약). - 변경: 라이브 주문·메일·소셜 로그인 공급자·구성원 석은 한도가 없습니다.
limits.liveOrdersMonthly·emailsMonthly·socialProviders·seatsIncluded는null이고features.storeClone·removeBadge는 항상false입니다. 필드는 그대로 둡니다. - 추가:
403 PLAN_FEATURE_REQUIRED— 관리 API(액세스 토큰·외부 앱)와 애널리틱스 조회는 Pro부터입니다. 상점 플랫폼·CLI·MCP는 모든 요금제에서 씁니다. - 추가:
429 PLAN_AI_READS_EXCEEDED— MCP 읽기 월 한도. MCP 요청은 관리 API 요청으로 세지 않고 MCP 읽기·쓰기로 셉니다. - 변경: 계정당 상점은 요금제와 무관하게 3개입니다(
409 STORE_LIMIT_EXCEEDED,details.reason: OWNED_STORES). 계정당 무료 상점 1개 규칙 (FREE_STORES)은 없앴습니다. - 변경: 웹훅 구독 상한은 요금제 값입니다(Free 0·Pro 5·프리미엄 20). API 로그·감사 로그 보관 기간은 요금제 값입니다.
- 없어짐: 상점 복제(상점 플랫폼). 새 상점은 템플릿이나 빠른 시작으로 만듭니다.
- MCP 0.20.0:
get_store_context의plan.aiReads(남은 MCP 읽기 수). MCP 읽기 한도 오류에 다음 할 일을 붙입니다.
파괴적 변경 — 셀러 토큰을 Sayren 계정 토큰으로 일원화 (@sayren/store-sdk 0.27.0 · @sayren/mcp 0.19.0 · sayren 0.3.0)
관리 API는 Sayren 계정이 발급한 토큰(로그인 토큰·액세스 토큰)만 받습니다. 옛 토큰과 인증 경로는 함께 쓰는 기간 없이 끊었습니다. 인증과 계정 토큰
- 호환성 변경: 없어진 토큰 — storeToken, 상점 API 토큰(
sy_pat_…), client_credentials(서버 간 연동)로 받은 토큰. 이 토큰으로 부르면401 TOKEN_TYPE_RETIRED입니다. - 호환성 변경: 없어진 경로 —
/v1/oauth2/authorize·/v1/oauth2/token(authorization_code·refresh_token·token-exchange·client_credentials)·/v1/oauth2/revoke·/v1/oauth2/logout·/v1/oauth2/register(클라이언트 등록),/v1/store/api-tokens/**,/v1/store/api-clients/**. 부르면410 TOKEN_TYPE_RETIRED입니다./.well-known/oauth-authorization-server와/.well-known/jwks.json도 없어졌습니다. - 호환성 변경: 구매자 위임 token-exchange(
member-uid·member-ref)를 없앴습니다.POST /v1/customers/delegations를 쓰십시오. - 호환성 변경: 관리 API의 상점 리소스 요청에는
X-Store-Id가 필요합니다. 없으면400 STORE_ID_REQUIRED, 토큰의 상점 범위 밖이면403 STORE_NOT_GRANTED입니다. - 상점 플랫폼: 개발자 › 자격 증명 › API 토큰·앱이 없어졌습니다. 액세스 토큰은 Sayren 계정 › 액세스 토큰, 로그인으로 연결한 앱은 Sayren 계정 › 연결된 앱에서 관리합니다.
- 추가:
GET /.well-known/oauth-protected-resource(RFC 9728). 관리 API의 인가 서버(authorization_servers)는 Sayren 계정입니다. - store-sdk 0.27.0:
createStoreClient({ baseUrl, accessToken, storeId }). 옵션storeToken·userToken·auth.apiToken,apiTokens·apiClients,auth.issueStoreTokenByClientCredentials·auth.revoke,exchangeStoreTokenViaOAuth를 없앴습니다.createStoreSession은authServer(Sayren 계정의authorizeUrl·tokenUrl·revokeUrl과resource)가 필요하고, 가입 화면은prompt: "create"입니다(screen: "signup"삭제).@sayren/store-sdk/server는delegateMember만 내보냅니다(delegateMemberByUid·delegateMemberByEmail삭제). Store SDK - 호환성 변경: MCP 0.19.0 —
SAYREN_TOKEN은 Sayren 계정 액세스 토큰만 받습니다. 옛 API 토큰(sy_pat_…)을 넣으면 API를 부르지 않고 오류로 안내합니다. 다룰 상점은 늘 정해야 하고SAYREN_STORE_ID로 고릅니다(토큰의 상점 범위가 하나면 생략).sayren-mcp create가 쓰는.mcp.json에는 원격 MCP 주소와 상점 id만 있고 토큰은 없습니다. MCP 연결하기 - 호환성 변경: CLI 0.3.0 — 토큰은
--token→SAYREN_TOKEN→ 로그인 정보(npx sayren login, 브라우저·기기 코드) 순서로 읽고.mcp.json의 토큰은 읽지 않습니다. 옛 API 토큰(sy_pat_…)은 받지 않고 로그인이나 액세스 토큰을 안내합니다. 상점은 명령마다 고릅니다(--store·SAYREN_STORE_ID, 없으면 폴더 상태·토큰의 상점 범위·선택)..mcp.json에는 토큰을 쓰지 않고, 남아 있던 옛 토큰 헤더와.env의 옛SAYREN_TOKEN줄은 지웁니다. CLI로 호스팅 사이트 고치기 - 호환성 변경: 원격 MCP는 Sayren 계정 토큰만 받습니다. 옛 API 토큰·storeToken은
401 invalid_token입니다. 상점은X-Store-Id로 정하고, 없으면 허락한 상점이 하나일 때만 연결합니다. - 추가: 원격 MCP 동적 클라이언트 등록. OAuth를 지원하는 AI 도구는 토큰 없이 주소만으로 연결하고, 처음 연결할 때 Sayren 계정 로그인과 권한 허용을 거칩니다. 이렇게 등록한 앱은 확인하지 않은 앱으로 표시되고 구성원 조회·관리, 상점 설정·웹훅 변경 권한은 받을 수 없습니다. 30일 동안 쓰지 않은 연결은 정리됩니다. 설치 없이 MCP 연결하기
- 스토어프론트 API(
X-Store-Code, 구매자 토큰)와@sayren/storefront-sdk는 바뀌지 않았습니다.
옮기는 순서입니다.
- Sayren 계정 › 액세스 토큰에서 필요한 권한과 상점 범위로 액세스 토큰을 만듭니다. 구매자 위임에 쓸 토큰은 구매자 위임을 켭니다.
- 요청의
Authorization: Bearer를 새 토큰으로 바꾸고X-Store-Id를 싣습니다. @sayren/store-sdk0.27.0,@sayren/mcp0.19.0,sayren0.3.0으로 올립니다.
2026-09-30
주문 가능 상태·공개 조건·샘플 상품 (@sayren/storefront-sdk 0.18.0 · @sayren/store-sdk 0.25.0)
- 추가: 스토어프론트
GET /store의checkoutAvailable·checkoutMode·checkoutUnavailableReason.checkoutAvailable이false면 결제 시작이409 PAYMENT_NOT_CONFIGURED이니 주문 버튼을 숨기고 안내를 보이십시오. 옛 SDK는 이 필드를 모르고, 새 SDK는 필드가 없는 응답을 주문 가능으로 읽습니다. 결제를 받을 수 없는 상태 - 추가: 결제 시작
409 PAYMENT_NOT_CONFIGURED의error.details.reason(NO_PROVIDER·NOT_LIVE). 코드는 그대로입니다. - 변경: 샌드박스 PG만 있는 상점이 호스팅 쇼핑몰을 공개하면 결제(테스트 결제 포함)를 받지 않습니다(
PAYMENT_NOT_LIVE). - 추가: 호스팅 공개 전환
409 STOREFRONT_NOT_READY— 판매 중인 상품(상점을 만들 때 넣은 샘플 제외)이 없으면 공개하지 않습니다. 공개하기 - 추가: 관리 API 상품 응답의
sample(상점 플랫폼 빠른 시작이 넣은 샘플 상품이면true). 스토어프론트 응답에는 없습니다.
유료 요금제 결제
상점 플랫폼에서 요금제를 고르고 카드로 결제합니다. 공개 API의 변경은 오류 코드 추가뿐입니다. 요금제와 한도
- 추가:
402 STORE_PAYMENT_REQUIRED— 첫 결제를 기다리는 상점(계정당 무료 상점 1개를 넘어 유료로 시작한 상점)의 관리 API 요청. - 추가:
403 SEAT_SUSPENDED— 무료 요금제로 바뀌며 석이 멈춘 구성원의 요청.
계정 토큰 (@sayren/store-sdk · sayren CLI · @sayren/mcp)
Sayren 계정에 발급되는 토큰으로 관리 API를 부릅니다. 모든 변경은 가산이고 기존 API 토큰·storeToken은 그대로 동작합니다. 계정 토큰
- 추가: 관리 API가 Sayren 계정 토큰(로그인 토큰·액세스 토큰)을 받습니다. 상점은
X-Store-Id로 고르고, 권한은 역할과 토큰 권한 중 좁은 쪽입니다. 오류 코드STORE_NOT_GRANTED(403, 토큰 상점 범위 밖)·TOKEN_REVOKED(401)를 더했습니다.GET /v1/me·GET /v1/me/stores도 계정 토큰을 받습니다. - 추가: 구매자 위임
POST /v1/customers/delegations(권한customer:rw+ 토큰 권한member:delegate). 계정 액세스 토큰과 Sayren 상점 플랫폼·CLI 로그인만 받고 다른 앱·AI 에이전트는DELEGATION_NOT_ALLOWED(403)입니다. store-sdkcustomerDelegationRequestSchema·customerDelegationSchema,@sayren/store-sdk/server의delegateMember. - CLI:
sayren login이 브라우저·기기 코드로 Sayren 계정에 로그인하고logout·whoami를 더했습니다. 로그인한 폴더의.mcp.json에는 토큰을 쓰지 않습니다. CLI로 호스팅 사이트 고치기 - 원격 MCP: Sayren 계정 로그인 창(OAuth)으로 연결합니다. stdio MCP는
SAYREN_STORE_ID를 읽어X-Store-Id를 싣습니다. 원격 MCP
요금제·사용량 조회 (@sayren/store-sdk 0.24.0 · @sayren/mcp 0.17.0)
베타 기간의 요금제·한도·사용량을 공개 API로 봅니다. 모든 변경은 가산입니다. 요금제와 한도
- 추가:
GET /v1/store/subscription(스코프store:r) — 요금제(plan.code·plan.name), 상태, 사용량 기간, 한도(limits), 이번 기간 사용량(usage), AI 작업 요약(aiActions), 판매 수수료(salesFeePercent, 항상 0). store-sdksubscription.get()·storeSubscriptionSchema·planErrorDetailsSchema. - 추가: 한도 오류 코드
PLAN_AI_ACTIONS_EXCEEDED(429)·PLAN_API_QUOTA_EXCEEDED(429,Retry-After)·PLAN_LIMIT_EXCEEDED(409)·PLAN_FEATURE_UNAVAILABLE(403)·SEAT_PAYMENT_REQUIRED(409). 베타 기간에는 구성원 석·AI 작업·관리 API 스로틀·상점 복제 기능· 소셜 로그인 공급자 수·웹훅 수 한도를 기록만 하고 막지 않습니다. - 변경: 편집 미리보기 시간·빌드 시간·초대·양도 메일 수에 요금제 월 한도가 있습니다. 넘으면 새 편집 환경·새 버전은
409 PLAN_LIMIT_EXCEEDED이고 메일은 보내지 않습니다(deliveryStatus: FAILED,deliveryErrorCode: MAIL_QUOTA_EXCEEDED, 초대·양도 요청은 만들어집니다). - 추가: 기존 한도 오류(
STORE_LIMIT_EXCEEDED·STOREFRONT_DOMAIN_LIMIT·WEBHOOK_LIMIT_EXCEEDED)의details에feature·limit·used·plan·upgradeUrl, 상점 수 한도에는reason(OWNED_STORES·FREE_STORES). 코드와 상태는 그대로입니다. - 추가: 초대 발송 실패 코드
deliveryErrorCode: MAIL_QUOTA_EXCEEDED. - MCP(
@sayren/mcp0.17.0):get_store_context에 요금제와 남은 AI 작업 수(plan.aiActions.remaining). AI 작업 한도·편집 한도 오류에 다음 할 일을 붙입니다.
스토어프론트 CLI·원격 MCP: 받은 폴더에 .mcp.json (sayren 0.2.0 · @sayren/mcp 0.16.0)
- 변경:
npx sayren pull이 받은 폴더에 sayren 원격 MCP 연결 설정.mcp.json(Claude Code 형식, 토큰·상점 id 포함)을 씁니다..sayrenrc는 없어지고 상태는.sayren/state.json에 둡니다. 토큰은.env가 아니라.mcp.json에서 읽습니다(--token→SAYREN_TOKEN→.mcp.json). 옛 폴더는 다음 명령에서 한 번 옮깁니다..mcp.json·.sayren/은.gitignore에 더하고 배포에 올리지 않습니다.sayren-mcp create도 토큰을 주면 같은.mcp.json을 씁니다. CLI로 호스팅 사이트 고치기 - 추가: 원격 MCP의 선택 헤더
X-Store-Id. 토큰의 상점과 다르면403입니다. 원격 MCP - 변경: 관리 API가 API 토큰(
sy_pat_…) 요청의X-Store-Id도 토큰의 상점과 대조합니다. 다르면403 STORE_ID_MISMATCH입니다 (storeToken과 같은 규칙). 헤더를 보내지 않으면 전과 같습니다.
store-sdk: 세션 로그아웃이 서버 토큰을 폐기합니다 (@sayren/store-sdk 0.23.0)
- 추가:
createStoreSession의logout(). refresh 토큰(갱신 체인 전체)과 access 토큰을POST /v1/oauth2/revoke로 폐기한 뒤 세션을 지웁니다. 폐기 요청이 실패해도 세션은 지웁니다. 지금까지clear()로 로그아웃했다면logout()으로 바꾸십시오 —clear()는 저장한 값만 지워 서버의 refresh 토큰이 만료까지 유효하게 남습니다. store SDK
스토어프론트 호스팅: 배포 진행 조회·템플릿 변경 폐기
- 호환성 변경: 템플릿 변경
POST /v1/storefront/site/template을 폐기했습니다. 경로는 남아 있고 본문과 관계없이 항상409 TEMPLATE_CHANGE_NOT_SUPPORTED로 답하며 사이트·버전을 바꾸지 않습니다. 템플릿은 사이트를 만들 때(POST /v1/storefront/site,templateId필수)만 고릅니다. store-sdkstorefront.changeTemplate은@deprecated로 남겨 두었습니다. 스토어프론트 호스팅 - 변경: 상점을 만들어도 호스팅 사이트가 생기지 않습니다.
GET /v1/storefront/site의site는 사이트를 만들기 전까지null이고,POST /v1/storefront/site가 사이트를 만드는 유일한 방법입니다. 이미 만들어진 사이트는 그대로입니다. - 추가: 배포 진행
GET /v1/storefront/site/deployment(단계SITE·UPLOAD·PUBLISH, 기록, 실패 코드, 다음 자동 시도)와 다시 시도POST /v1/storefront/site/deployment/retry(202). store-sdkstorefront.getDeployment·retryDeployment. - 새 오류 코드:
TEMPLATE_CHANGE_NOT_SUPPORTED.
상품 옵션: 추가 선택·직접 입력·저장 옵션 (@sayren/store-sdk 0.21.0 · @sayren/storefront-sdk 0.17.0 · @sayren/mcp 0.14.0)
옵션명마다 조합과 추가 선택 중 하나를 고르고, 구매자가 글자를 적는 직접 입력 항목을 둘 수 있습니다. 모든 변경은 가산이고 기존 필드의 형태는 그대로입니다. 상품 옵션 구성
- 추가: 관리 API 상품·옵션 모델에
addonGroups(추가 선택, 재고 없이 값별 추가금)·customInputs(직접 입력)·optionSort(값 정렬 순서).PUT /v1/products/{productId}·PUT /v1/products/{productId}/options에서 생략하면 현재 값을 유지합니다.optionGroups·variants는 조합만 담습니다. - 추가: 조합 응답
variants[].hasOrders. 주문에 담긴 조합이면true이고, 이 조합은 교체 목록에서 뺄 수 없습니다(409 OPTION_HAS_ORDERS). - 추가: 저장 옵션
/v1/saved-option-sets(목록·만들기·조회·수정·삭제, 상품에서 저장POST /v1/saved-option-sets/from-product). SDK는savedOptionSets입니다. 상품 등록·수정 본문의sourceOptionSetIds는 불러온 저장 옵션을 기록합니다. - 추가: 스토어프론트 상품 상세의
addonGroups·customInputs. 장바구니 담기·수정과 바로 구매가addons·customInputs를 받고, 장바구니·주문서·주문 상품 줄에 고른 값을 싣습니다. 추가 선택·직접 입력값이 다르면 다른 줄입니다. - 추가: 주문서 줄과 쿠폰 결과의
lineId. 같은 조합이 여러 줄에 있으면 상품 쿠폰을 걸 줄을lineId로 지목합니다. - 추가: 관리 API 주문 상품의
optionSelections·customInputs(주문 시점 이름·값), 웹훅ORDER.PAID의itemOptions. - 추가: store-sdk
CUSTOM_INPUT_FORBIDDEN_WORDS, storefront-sdkcustomInputLength·normalizeCustomInputValue. - 새 오류 코드:
ADDON_OPTION_REQUIRED·ADDON_OPTION_NOT_FOUND·CUSTOM_INPUT_REQUIRED·CUSTOM_INPUT_TOO_LONG·CUSTOM_INPUT_NOT_FOUND·CUSTOM_INPUT_LABEL_FORBIDDEN·OPTION_SET_NAME_TAKEN·OPTION_SET_LIMIT_EXCEEDED·OPTION_ADDONS_UNAVAILABLE.OPTION_ADDONS_UNAVAILABLE는 추가 선택·직접 입력이 아직 열리지 않았을 때 비어 있지 않은 값을 보내면 나옵니다. - 스토어프론트 템플릿(
@sayren/mcp0.14.0): 상품 상세에 추가 선택·직접 입력을 두고 장바구니·주문서·주문 화면이 줄마다 옵션을 보여 줍니다.verify_storefront규칙custom-input-private를 더했습니다(직접 입력값을 URL·브라우저 저장소·로그에 두지 않음). 규칙은 20개입니다.
상품 유형 축소 (@sayren/store-sdk 0.20.0 · @sayren/storefront-sdk 0.16.0 · @sayren/mcp 0.13.0)
비실물 상품의 세부 유형을 없애고 상품 유형을 배송 상품(SHIPPING)과 배송 없는 상품(MANUAL) 둘로 줄였습니다. 배송 없는 상품은 판매자가
제공 처리(POST /v1/order-items/{orderItemId}/fulfill)로 제공 완료를 기록하는 한 가지 흐름입니다. 비실물 상품 판매하기
- 호환성 변경:
fulfillment.type의DOWNLOAD·CODE·SERVICE·PICKUP을 없앴습니다. 요청에 보내면400입니다. 배송 없는 상품은{ "type": "MANUAL" }이고 유형 속성이 없습니다. 주문 상품의fulfillmentSnapshot도SHIPPING·MANUAL둘입니다. - 호환성 변경: 결제와 함께 자동으로 제공하는 방식(
AUTO)을 없앴습니다. 모든 배송 없는 상품은 판매자가 제공 처리합니다. 제공 처리 본문은note만 받습니다(codes삭제). - 호환성 변경: 코드 발급을 없앴습니다. 코드 업로드·목록·폐기(
/v1/products/{productId}/codes/**), 셀러 코드 열람(/v1/fulfillment-codes/{codeId}/reveal), 구매자 코드 열람(/storefront/v1/me/order-items/{orderItemId}/fulfillment/reveal, 비회원…/guest/orders/{orderId}/order-items/{orderItemId}/fulfillment/reveal)이 없어졌습니다. SDK의products.uploadCodes·listCodes·voidCode,fulfillmentCodes.reveal,myOrders.revealCode·revealGuestCode도 없앴습니다. - 호환성 변경: 파일 다운로드를 없앴습니다. 판매 파일(
/v1/products/{productId}/digital-assets/**), 업로드 용도digital-asset, 구매자 다운로드 (/storefront/v1/me/order-items/{orderItemId}/downloads, 비회원…/guest/orders/{orderId}/order-items/{orderItemId}/downloads)가 없어졌습니다. 업로드 응답의key·headers도 없앴습니다. SDK의products.attachDigitalAsset·listDigitalAssets·removeDigitalAsset·previewDigitalAsset,myOrders.createDownload·createGuestDownload도 없앴습니다. - 호환성 변경: 방문 수령을 없앴습니다. 주소록 유형
PICKUP과 등록된 방문 수령지가 없어졌습니다(주소록 유형은SHIPPING·RETURN). - 호환성 변경: 청약철회 제한 고지·동의를 없앴습니다. 결제 시작의
withdrawalAgreement, 주문의withdrawalAgreedAt, 상점 설정withdrawalNotice가 없어졌습니다. 주문서의withdrawal은 항상{ "required": false, "notice": null }, 장바구니·주문서 줄의fulfillment.withdrawalRestricted는 항상false이고 Deprecated입니다(아래 「옛 SDK 호환 필드」). - 호환성 변경: 제공 안내 메일을 없앴습니다. 상점 설정
fulfillmentMailEnabled, 재발송POST /v1/order-items/{orderItemId}/fulfillment/mail(orderItems.resendFulfillmentMail), 주문 상품fulfillment.mail이 없어졌습니다. 구매자 알림은ORDER.FULFILLED웹훅으로 직접 보내십시오. - 호환성 변경: 주문 상품의 제공 기록
fulfillment는status·fulfilledAt·note를 싣습니다(codes·download·mail삭제). 관리 API의fulfillment.mode와 웹훅ORDER.FULFILLED의fulfillment.mode는 항상MANUAL이고 Deprecated입니다. - 옛 SDK 호환 필드: 이미 배포된 스토어프론트(
@sayren/storefront-sdk0.15 이하)와 연동(@sayren/store-sdk0.19 이하)이 계속 동작하도록 위의 Deprecated 필드를 고정값으로 한 릴리스 더 싣습니다. 다음 릴리스에서 뺍니다. 그 전에 SDK를 이 버전 이상으로 올리십시오. - 삭제된 오류 코드:
FULFILLMENT_TYPE_NOT_AVAILABLE·INVALID_FULFILLMENT_MODE·PICKUP_ADDRESS_REQUIRED·STOCK_MANAGED_BY_CODES·CODE_REQUIRED·CODE_COUNT_MISMATCH·CODES_NOT_ALLOWED·ASSET_REQUIRED·ASSET_NOT_PRIVATE·ASSET_CHECK_FAILED·ASSET_ALREADY_ATTACHED·DOWNLOAD_LIMIT_REACHED·DOWNLOAD_EXPIRED·WITHDRAWAL_AGREEMENT_REQUIRED·WITHDRAWAL_RESTRICTED·MAIL_SENDING. - SDK는 옛 서버나 옛 이벤트가 보낸 없앤 유형을
{ type: "OTHER", rawType }로 읽습니다. - 스토어프론트 템플릿(
@sayren/mcp0.13.0)에서 다운로드·코드 보기 화면과 청약철회 동의 체크를 없앴습니다. 배송 없는 주문 상품은 판매자 이용 안내(fulfillment.note)를 보여 줍니다.
2026-09-29
원격 MCP (@sayren/mcp 0.11.0)
- 추가: 설치 없이
https://mcp.sayren.app/mcp주소와 API 토큰(Authorization: Bearer)으로 연결하는 원격 MCP. 상점 조회·관리 API·스토어프론트 호스팅 도구를 씁니다. 설치 없이 MCP 연결하기 - 추가: 스토어프론트 호스팅 도구
get_site·list_versions·publish_version·rollback·set_visibility(로컬·원격 공통). AI 도구의 발행·되돌리기·공개 전환은 승인 뒤 실행됩니다.
스토어프론트 템플릿 쿠키·테마 (@sayren/mcp 0.10.0)
- 호환성 변경: 템플릿의 서버 쿠키(구매자 세션·비회원 장바구니·소셜 로그인 왕복)는 배포 빌드에서 이름에
__Host-접두사가 붙습니다 (src/lib/cookies.server.ts). 같은 상위 도메인의 다른 사이트가 심은 쿠키로 구매자 세션이 바뀌지 않게 하는 장치입니다. 접두사 없는 옛 이름은 읽지 않으므로 0.10.0 템플릿으로 배포하면 로그인해 있던 구매자는 한 번 다시 로그인합니다. 빌드 결과는 https(또는 localhost)에서만 로그인·장바구니가 유지됩니다. - 변경: 브랜드 색·서체·본문 폭 토큰이
src/styles.css에서src/theme.css로 옮겨졌습니다. 페이지 바탕(--color-page)과 본문 최대 폭 (--container-page) 토큰이 더해졌습니다. 디자인 수정하기 - 변경:
verify_storefront의buyer-token-cookie규칙이 서버 쿠키에domain을 주는 코드를 위반으로 봅니다. 규칙 수는 그대로 19개입니다.
스토어프론트 호스팅 API (@sayren/store-sdk 0.19.0)
- 추가: 관리 API
/v1/storefront/**(템플릿 목록, 사이트 조회·만들기, 템플릿 변경, 버전 목록·발행·되돌리기, 주소 변경, 공개 전환, 호스팅 끄기, 미리보기 링크)와 스코프storefront:r·storefront:rw. 새 사이트 만들기는 순차적으로 엽니다. 열리기 전에는GET /v1/storefront/site의enabled가false이고 만들기는403 STOREFRONT_HOSTING_DISABLED입니다. 스토어프론트 호스팅
상품 모델 재구성 (@sayren/store-sdk 0.18.0 · @sayren/storefront-sdk 0.15.0 · @sayren/mcp 0.9.0)
상품의 유형과 유형별 속성을 fulfillment 하나로 모았습니다. 배송비·출고지 같은 배송 속성은 배송 상품에만, 다운로드 횟수·제공 방식 같은 비실물 속성은
그 유형에만 있습니다. 주문 상품은 주문 시점의 이행을 fulfillmentSnapshot으로 굳혀 둡니다. 상품 유형 참고.
- 호환성 변경: 관리 API 상품 응답의 평면 필드(
deliveryType·deliveryFee·conditionalFreeAmount·shippingAddressId·returnAddressId·returnFee·exchangeFee·fulfillmentType·fulfillmentMode·withdrawalRestricted·pickupAddressId·stockTracking·downloadLimit·downloadDays)를 없앴습니다. 유형과 속성은fulfillment: { type, <유형>: { … } }입니다. 상품 목록의 유형은fulfillment.type입니다. - 호환성 변경: 상품 등록·수정 요청은 정한 필드만 받습니다. 옛 평면 필드를 보내면
400입니다. 수정(PUT·PATCH)에서fulfillment를 주면 유형 안의 필드를 모두 보내야 하고, 생략하면 이행을 바꾸지 않습니다. - 호환성 변경: 상품의 반품·교환 배송비는
refundPolicy.returnDeliveryFee·exchangeDeliveryFee만 씁니다. 배송이 없는 유형에 주면400 REFUND_POLICY_NOT_APPLICABLE입니다. 기존 상품의 반품비·교환비는 상품refundPolicy로 옮겼습니다. - 호환성 변경: 주문 상품의
fulfillmentType·withdrawalRestricted를fulfillmentSnapshot으로 바꿨습니다(관리 API·스토어프론트 API). 스토어프론트 주문 상품의pickupLocation은fulfillmentSnapshot.pickup.location입니다. - 호환성 변경: 웹훅
ORDER.DELIVERED(비실물 제공)의fulfillmentType은fulfillmentSnapshot,ORDER.FULFILLED의fulfillmentType·fulfillmentMode는fulfillmentSnapshot·fulfillment.mode입니다. 전환 전에 만들어진 이벤트는 재시도·수동 재전송에서 옛 모양으로 올 수 있고, 0.18.0의webhookEventSchema는 그 모양을 거부합니다. 웹훅 - 호환성 변경: 스토어프론트 상품 카드·장바구니 줄·주문서 줄의
fulfillmentType·requiresShipping(·withdrawalRestricted)을fulfillment로 모았습니다. 상품 상세의delivery·returnPolicy는fulfillment(배송 상품이면fulfillment.shipping)와returnPeriodDays로 바뀌었습니다. 장바구니·주문서·주문의requiresShipping은 항상 실립니다. - 호환성 변경: 에이전트 승인의 상품 가격 필드가 점 경로입니다(
fulfillment.shipping.deliveryFee등). - 추가: 상품 응답
fulfillmentTypeLocked(판매 이력이 있어 유형을 바꿀 수 없음). 오류400 PICKUP_ADDRESS_REQUIRED,409 PRODUCT_CHANGED. - 변경: 주문 뒤의 다운로드 횟수·기간, 반품지, 방문 수령지, 환불 정책은 주문 시점 값을 씁니다. 상품을 고쳐도 이미 들어온 주문은 바뀌지 않습니다.
- 변경: 수령 전 방문 수령 주문이 쓰는 방문 수령지는 삭제할 수 없습니다(
409 ADDRESS_IN_USE). - 변경: 전환 시점에 결제하지 않은 주문서와 결제 대기 중인 결제는 만료됐습니다. 주문서를 다시 만드십시오.
- SDK 응답의 유형은 열린 유니온입니다. 모르는 유형은
{ type: "OTHER", rawType }(스토어프론트는requiresShipping포함)입니다.
| 표면 | 이전 | 이후 |
|---|---|---|
| 관리 API 상품 | deliveryType · deliveryFee · conditionalFreeAmount | fulfillment.shipping.deliveryType · deliveryFee · conditionalFreeAmount |
| 관리 API 상품 | shippingAddressId · returnAddressId | fulfillment.shipping.shippingAddressId · returnAddressId |
| 관리 API 상품 | returnFee · exchangeFee | refundPolicy.returnDeliveryFee · exchangeDeliveryFee |
| 관리 API 상품 | fulfillmentType | fulfillment.type |
| 관리 API 상품 | fulfillmentMode | fulfillment.code.mode · fulfillment.service.mode |
| 관리 API 상품 | downloadLimit · downloadDays · stockTracking | fulfillment.download.limit · days · stockTracking |
| 관리 API 상품 | withdrawalRestricted | fulfillment.download.withdrawalRestricted · fulfillment.code.withdrawalRestricted |
| 관리 API 상품 | pickupAddressId | fulfillment.pickup.addressId |
| 주문 상품 | fulfillmentType · withdrawalRestricted | fulfillmentSnapshot.type · fulfillmentSnapshot.{download,code}.withdrawalRestricted |
웹훅 ORDER.DELIVERED | fulfillmentType | fulfillmentSnapshot |
웹훅 ORDER.FULFILLED | fulfillmentType · fulfillmentMode | fulfillmentSnapshot · fulfillment.mode |
| 스토어프론트 상품 카드 | fulfillmentType · requiresShipping | fulfillment.type · fulfillment.requiresShipping |
| 스토어프론트 상품 상세 | delivery · returnPolicy | fulfillment.shipping · returnPeriodDays |
| 스토어프론트 장바구니·주문서 줄 | fulfillmentType · requiresShipping · withdrawalRestricted | fulfillment.type · requiresShipping · withdrawalRestricted |
| 스토어프론트 주문 상품 | fulfillmentType · withdrawalRestricted · pickupLocation | fulfillmentSnapshot(pickup.location) |
2026-09-28
앱 토큰의 상점 범위와 구성원 변경 제한
- 호환성 변경: 직접 등록한 앱(
POST /v1/oauth2/register)으로 받은 토큰은 앱을 등록한 상점에서만 쓸 수 있습니다. 다른 상점을X-Store-Id로 부르면403 CLIENT_STORE_MISMATCH, 다른 상점을audience로 교환하면400 invalid_target입니다.GET /v1/me/stores는 앱 토큰에 등록한 상점만 돌려줍니다. 여러 상점에서 쓰는 앱은 상점마다 따로 등록합니다. - 호환성 변경: 구성원·초대 변경(
POST /v1/store/invitations,POST /v1/store/invitations/{invitationId}/resend,DELETE /v1/store/invitations/{invitationId},PATCH /v1/store/members/{userId},DELETE /v1/store/members/{userId})은 상점 플랫폼에서 로그인한 소유자·관리자만 할 수 있습니다. API 토큰·M2M 토큰·직접 등록한 앱의 토큰은403 INSUFFICIENT_ROLE입니다. 조회는 그대로입니다. 구성원 초대·관리 참고.
쿠폰 (@sayren/store-sdk 0.17.0 · @sayren/storefront-sdk 0.14.0 · @sayren/mcp 0.8.0)
- 추가: 관리 API
/v1/coupons/**(생성·수정·중지·재개·종료·지급·발급 내역·사용 내역·통계),POST /v1/coupon-issues/{issueId}/revoke,GET /v1/customers/{customerId}/coupons(customer:r). 쿠폰 API의 스코프는promotion:r·promotion:rw입니다. 이미 발급한 토큰에는 이 스코프가 없으니 쿠폰 API를 쓰려면 토큰을 새로 발급합니다. 쿠폰 참고. - 추가: 스토어프론트 API
POST /storefront/v1/checkout/{checkoutId}/pricing(금액 미리보기),GET /storefront/v1/checkout/{checkoutId}/coupons,GET /storefront/v1/me/coupons, 결제 시작 본문의coupons. 쿠폰 적용이 열리기 전에는 쿠폰을 보낸 요청이409 COUPONS_UNAVAILABLE이고 쿠폰 없는 결제는 그대로입니다. - 추가: 주문
payment.couponDiscountAmount·deliveryDiscountAmount·discounts, 주문 상품couponDiscountAmount, 주문서·결제 시작amounts의 같은 두 금액. 쿠폰이 없으면 0과 빈 배열입니다. 결제 금액은productAmount + deliveryFee − couponDiscountAmount − deliveryDiscountAmount입니다. - 추가: 환불 정책
couponShortfallCharge(상점 단위, 기본true), 클레임 승인·판매자 취소 응답과 웹훅의couponChargeAmount·couponChargeRefundAmount. 쿠폰 없는 주문은 항상 0입니다. - 변경: 쿠폰 할인을 받은 주문 상품의 환불은 실제 결제 금액(
totalPrice − couponDiscountAmount)을 수량 비율로 나눕니다. - 호환성 변경: SDK의
CheckoutSession·PaymentStart타입에서amounts.couponDiscountAmount·deliveryDiscountAmount가 필수 필드입니다. 응답은 옛 서버의 값도 0으로 읽습니다. 이 타입으로 목 객체를 직접 만드는 코드는 두 필드를 더해야 컴파일됩니다. - 추가: MCP 스토어프론트 템플릿 주문서의 쿠폰 코드 입력(미리보기 뒤 결제 시작에 같은 코드를 보냄,
src/lib/coupon-code.ts). - 변경: 템플릿 주문서에서 팝업 결제를 취소하거나 실패한 뒤 입력을 바꾸지 않고 다시 결제하면 새 결제를 만들지 않고
payments.retry로 같은 결제를 이어 갑니다.
비실물 상품 (@sayren/store-sdk 0.17.0 · @sayren/storefront-sdk 0.14.0 · @sayren/mcp 0.8.0)
- 추가: 상품 필드
fulfillmentType(SHIPPING·DOWNLOAD·CODE·SERVICE·PICKUP, 기본SHIPPING)·fulfillmentMode(AUTO·MANUAL, 유형 기본값)·downloadLimit(기본 5)·downloadDays(기본 30)·stockTracking(파일 다운로드 기본false, 그 밖true)·withdrawalRestricted(기본false, 파일 다운로드·코드 발급만)·pickupAddressId. 수정에서fulfillmentType을 생략하면 바꾸지 않습니다. 판매 이력이 있는 상품의 유형 변경은409 FULFILLMENT_TYPE_LOCKED, 아직 쓸 수 없는 유형은409 FULFILLMENT_TYPE_NOT_AVAILABLE입니다. 비실물 상품 판매하기 참고. - 추가: 주소록 유형
PICKUP(방문 수령지).GET /v1/seller-addresses는type=PICKUP을 줄 때만 방문 수령지를 돌려줍니다. - 추가: 제공 처리
POST /v1/order-items/{orderItemId}/fulfill(본문note·codes)·POST /v1/order-items/fulfill(항목별 결과), 안내 메일 재발송POST /v1/order-items/{orderItemId}/fulfillment/mail(주문 상품당 하루 3회). Store SDKorderItems.fulfill·fulfillBulk·resendFulfillmentMail. 주문 목록 필터fulfillmentType. - 추가: 코드 발급
POST·GET /v1/products/{productId}/codes,POST /v1/products/{productId}/codes/{codeId}/void. Store SDKproducts.uploadCodes·listCodes·voidCode. 결제 즉시 배정 코드 상품의 재고는 판매 가능 코드 수이고 직접 바꾸면409 STOCK_MANAGED_BY_CODES입니다. - 추가: 판매 파일
POST·GET /v1/products/{productId}/digital-assets,DELETE …/{assetId}. 업로드 용도digital-asset과 업로드 응답의key·headers(PUT에 반드시 싣는 헤더, 공개 업로드는 빈 객체). Store SDKproducts.attachDigitalAsset·listDigitalAssets·removeDigitalAsset.uploads.upload는headers를 붙여 PUT합니다. - 추가: 주문 상품
fulfillmentType·fulfillment(status·mode·fulfilledAt·note·codes·download·mail)·withdrawalRestricted, 주문requiresShipping·withdrawalAgreedAt. 배송 상품이나 제공 전이면fulfillment는null입니다. 비실물 주문 상품의DELIVERED는 제공 완료입니다. - 추가: 상점 설정
fulfillmentMailEnabled(기본true)·withdrawalNotice(null이면 기본 문구). - 추가: 웹훅 이벤트
ORDER.FULFILLED(orderId·orderItemId·status·fulfillmentType·fulfillmentMode·fulfilledAt·testPayment). 비실물 제공 때ORDER.DELIVERED도 함께 오고 여기에 선택 필드orderItemId·fulfillmentType이 실립니다.type을 닫힌 목록으로 검증한다면 허용하십시오. 웹훅 참고. - 추가: 스토어프론트 API 상품·장바구니·주문서
requiresShipping·fulfillmentType, 주문서withdrawal(required·notice), 결제 시작withdrawalAgreement. 결제 시작의shippingAddress는 선택이고 배송이 필요한데 없으면400 SHIPPING_ADDRESS_REQUIRED입니다. 주문서를 만든 뒤 상품 유형이 바뀌면409 CHECKOUT_STALE입니다. - 추가: 코드 열람
POST /storefront/v1/me/order-items/{orderItemId}/fulfillment/reveal(비회원/guest/orders/{orderId}/order-items/{orderItemId}/fulfillment/reveal), 다운로드POST /storefront/v1/me/order-items/{orderItemId}/downloads(비회원/guest/orders/{orderId}/order-items/{orderItemId}/downloads). Storefront SDKmyOrders.revealCode·revealGuestCode·createDownload·createGuestDownload,payments.start의withdrawalAgreement. 내 주문 상품fulfillment·pickupLocation·withdrawalRestricted, 내 주문withdrawalAgreedAt. - 변경: 배송이 없는 상품은 배송 묶음과 상점 전체 무료배송 기준 금액에서 빠집니다. 배송비·반품 배송비·교환 배송비가 0입니다.
- 변경: 비실물 상품에 발송처리·배송완료를 하면
409 NOT_SHIPPABLE, 배송 조회는404 NOT_SHIPPABLE입니다. - 호환성 변경: 청약철회 제한 상품이 든 주문서는 결제 시작에
withdrawalAgreement: true가 있어야 합니다. 이 필드를 보내지 않는 스토어프론트는 그 주문만400 WITHDRAWAL_AGREEMENT_REQUIRED이고 다른 주문은 그대로입니다. - 호환성 변경: 비실물 주문 상품에 대한 구매자 클레임이 새 코드로 거절될 수 있습니다. 교환은
409 EXCHANGE_NOT_SUPPORTED, 청약철회 제한 상품(파일·코드)의 첫 다운로드·열람 뒤 단순 변심 취소·반품은409 WITHDRAWAL_RESTRICTED입니다. 셀러의 반품 수거 등록은409 COLLECTION_NOT_REQUIRED입니다(바로 환불 승인). - 추가: MCP 스토어프론트 템플릿 — 배송이 없는 주문서는 배송지를 묻지 않고, 청약철회 제한 고지와 동의를 받습니다. 주문 상세에서 코드 열람
(
src/lib/code-reveal.ts)과 파일 다운로드(src/lib/download.ts)를 합니다(비회원 주문 조회 포함).
웹훅 sequence (@sayren/store-sdk 0.17.0)
- 추가: 웹훅 본문의
sequence. 리소스(주문·클레임·문의·리뷰·상품)별 순번이고 같은 리소스의 이벤트마다 1씩 커집니다. 도착 순서는 보장하지 않으므로 같은 리소스의 이벤트는 이 값으로 정렬하십시오. 이 필드가 생기기 전의 이벤트와 테스트 전송에는 없습니다. 웹훅 참고. - 추가: Store SDK
webhookEventSchema의sequence(선택 필드). - 변경: 전송 기록의
attemptCount는 전송을 시작한 횟수입니다. 보내는 도중 장애로 결과를 기록하지 못한 시도도 셉니다. - 추가(0.17.0에 함께 실림): Store SDK
productSchema의discount(상품 상세 응답의 즉시할인, 없으면null)와discountSchema.
2026-09-27
MCP 스토어프론트 템플릿 기본 라이브러리 (@sayren/mcp 0.7.0)
- 추가: 템플릿 기본 의존성
nuqs·@tanstack/react-query(+@tanstack/react-router-ssr-query)·react-hook-form·@hookform/resolvers·query-string.zod는 이전부터 들어 있습니다. - 변경: 상품 목록(
/products)의 검색어·카테고리·정렬·페이지를 nuqs 파서로 읽고 바꿉니다(src/lib/products-search.ts). 정렬 선택을 넣었습니다. 목록 데이터는 loader가ensureQueryData로 서버에서 미리 받고 화면은useSuspenseQuery로 읽습니다 (src/lib/catalog-queries.ts). - 변경: 회원가입·주문서·비회원 주문 조회 폼이 react-hook-form +
zodResolver입니다. 입력 규칙은 SDK 스키마를 재사용하고 칸마다 오류를 보입니다(src/lib/form-schemas.ts). - 변경:
verify_storefront규칙loader-first가 TanStack Query로 받는 화면에 loader의ensureQueryData가 없으면 알립니다. 규칙 수는 그대로 19개입니다.
비회원 주문 조회 시도 한도
- 호환성 변경:
POST /storefront/v1/guest/orders/{orderId}에서 연락처·주문 조회 비밀번호가 틀리면401 INVALID_CREDENTIALS가 아니라404 ORDER_NOT_FOUND입니다. 주문이 없을 때와 같은 응답이라 주문이 있는지 드러나지 않습니다. 두 코드를 함께 처리하던 화면은 그대로 동작합니다. - 추가: 주문번호마다 10분에 5번까지 확인하고, 5번째가 틀리면 30분 동안
429 TOO_MANY_REQUESTS(error.details.retryAfterSeconds)입니다. 잠긴 동안은 맞는 비밀번호로도 조회되지 않고, 맞게 조회하면 횟수가 초기화됩니다. - 추가: 주문번호마다 하루 15번이 상한이고, 상점 전체의 비회원 주문 조회에도 분당 한도가 있습니다. 넘으면 같은
429입니다. - 변경: 조회 본문은 주문서의 비회원 정보와 같은 형식입니다.
phone은01로 시작하는 숫자 1011자,128자이고 어긋나면orderPassword는 6400 VALIDATION_FAILED입니다(시도로 세지 않습니다). - 호환성 변경: 주문서·결제 시작의
guest.orderPassword는 128자까지입니다(400 VALIDATION_FAILED). 스토어프론트 SDK 0.13.0의guestInfoSchema가 같은 상한을 검사하고,myOrders.getGuestOrder문서 주석에 위 오류를 적었습니다.
판매자 취소 웹훅 (@sayren/store-sdk 0.16.0)
- 추가: 웹훅 이벤트
ORDER.CANCELED. 셀러가POST /v1/order-items/{orderItemId}/cancel로 판매자 취소를 하면(일부 수량 포함) 옵니다.data는orderId·orderItemId·status(주문 대표 상태)·itemStatus·reason·quantity·canceledQuantity·refundAmount·deliveryFeeRefundAmount·deliveryFeeChargeAmount·testPayment입니다. 구독해야 옵니다. 웹훅 참고. - 추가: Store SDK
eventTypeSchema의ORDER.CANCELED,orderCanceledWebhookEventSchema·orderCanceledWebhookEventDataSchema.webhookEventSchema로 본문을 검증하던 수신 서버는 SDK를 올리면 이 이벤트를 받습니다.
MCP 스토어프론트 템플릿 (@sayren/mcp 0.6.1)
- 변경: 화면 탭 제목이
{화면} | {상점 이름}입니다(예:회원가입 | 나의첫번째몰). 홈은 상점 이름만 씁니다(src/lib/page-title.ts). - 변경: 비회원 주문 조회 화면이
429에서 남은 시간을 분 단위로 안내합니다(src/lib/guest-order.ts).
MCP 스토어프론트 템플릿 (@sayren/mcp 0.6.0)
- 추가: 회원가입 화면(
/signup). 이메일·비밀번호 로그인을 켠 상점에서 이용약관·개인정보 수집이용(필수)과 마케팅 수신(선택) 동의를 받아 가입하고, 비회원 장바구니를 회원 장바구니로 합칩니다. - 추가: 내 정보의 로그아웃(리프레시 토큰 폐기)과 회원 탈퇴, 비회원 주문 조회 화면(
/guest-order). - 추가: 결제 복귀 화면의 다른 결제수단 재시도(
payments.retry). 주문서가 결제창을 열기 전에 결제 옵션을 탭 저장소에 남깁니다. - 변경: 헤더와 브라우저 탭 제목이 상점 이름·로고(
GET /store)를 씁니다. 파비콘(public/favicon.svg)을 넣었습니다. - 변경: 상품 이미지 대체 텍스트, 장바구니 수량 입력 이름 등 접근성 이름을 정리했습니다.
- 추가:
verify_storefront규칙payment-retry·buyer-signup·buyer-signout. 규칙은 19개입니다. 0.5.x 템플릿으로 만든 프로젝트는 이 세 규칙에 새로 걸릴 수 있습니다. 새 템플릿의src/routes/signup.tsx·src/routes/account.tsx·src/routes/checkout.return.tsx·src/lib/payment-options.ts를 참고해 고칩니다.
구성원 초대
- 추가:
POST /v1/store/invitations가 초대 메일을 보냅니다. 받는 사람은 메일의 링크를 열어 로그인한 뒤 상점 플랫폼에서 수락합니다. 초대받은 이메일 주소의 계정으로만 수락할 수 있습니다. 구성원 초대·관리 참고. - 추가:
POST /v1/store/invitations/{invitationId}/resend. 새 수락 링크로 다시 보내고 만료를 7일 뒤로 다시 정합니다. 이전 링크는 무효가 됩니다. - 추가: 초대 응답의
deliveryStatus(SENDING·SENT·FAILED·NOT_CONFIGURED, 발송 기록이 없는 옛 초대는null)·deliveryErrorCode·lastSentAt·sendCount·acceptedAt. 만료 시각이 지난 대기 초대는status가EXPIRED로 보입니다. - 추가: 초대 메일 발송 한도(초대 + 재발송). 상점마다 한 시간에 20통, 초대한 사람마다 하루 50통, 받는 이메일 주소마다 하루
5통이고 넘으면
429 TOO_MANY_REQUESTS(details.limit:STORE·SENDER·RECIPIENT)입니다. - 추가: 초대 수락은 로그인한 지 10분 안에만 되고(
403 REAUTH_REQUIRED), 이메일 주소 인증을 마친 계정만 할 수 있습니다 (403 EMAIL_NOT_VERIFIED). - 추가: 발송 결과를 확인하지 못한 초대는
deliveryStatus가FAILED,deliveryErrorCode가DELIVERY_UNKNOWN입니다. - 추가: Store SDK
store.invite·store.resendInvitation·store.cancelInvitation·store.updateMemberRole·store.removeMember,store.listInvitations({ status }), 스키마inviteMemberRequestSchema·updateMemberRoleRequestSchema·invitationDeliveryStatusSchema. - 변경: 관리자(ADMIN)는 다른 관리자의 역할을 바꾸거나 내보낼 수 없습니다(
403 INSUFFICIENT_ROLE). 소유자만 합니다. 관리자 초대의 재발송·취소도 소유자만 합니다. 역할이 없는 API 토큰으로는 관리자로 올리거나 관리자를 바꾸거나 내보낼 수 없습니다. - 변경: 초대 이메일은 소문자로 저장하고, 같은 주소의 대기 초대는 대소문자와 관계없이 하나만 둡니다. 동시에 초대하거나
같은 주소에 대기 초대가 있는데 만료된 초대를 재발송하면
409 INVITATION_PENDING입니다. - 변경: 초대 메일 제목에 상점 이름을 싣지 않습니다. 본문의 상점·초대한 사람 이름은 「」 안에 싣고, 링크처럼 보이는 이름은 싣지 않습니다.
- 변경:
GET /v1/store/invitations의status가 허용 값이 아니면400입니다(전에는 빈 목록). - 추가: 초대·재발송·취소·수락·역할 변경·내보내기의 감사 로그(
MEMBER_*).
AI 작업 승인과 감사 로그
- 추가: 에이전트 쓰기 정책. AI 에이전트용 API 토큰이나
@sayren/mcp가 보낸 변경 중 환불·가격·할인처럼 되돌리기 어려운 작업은 실행하지 않고202(meta.code=APPROVAL_REQUIRED)와 승인 요청을 돌려줍니다. 결제 설정·토큰 발급처럼 에이전트에게 맡기지 않는 작업은403 AGENT_OPERATION_DENIED입니다. 판정은 관리 API 문서의x-agent-policy에도 실립니다. 에이전트가 아닌 요청은 바뀌지 않습니다. AI 작업 승인과 감사 로그 참고. - 추가:
POST /v1/store/api-tokens의agent(AI 에이전트(MCP)용 토큰, 생략 =false)와 목록·발급 응답의agent. - 추가: 요청 헤더
x-sayren-dry-run: 1. 변경 요청을 실행하지 않고 판정(decision)과 영향 미리보기(preview)를200(meta.code=DRY_RUN)으로 돌려줍니다. 영향 미리보기 참고. - 추가:
GET /v1/approval-requests·GET /v1/approval-requests/{approvalId}·POST /v1/approval-requests/{approvalId}/approve·POST /v1/approval-requests/{approvalId}/reject. 승인 응답은 실행을 기다리지 않은EXECUTING이고, 원 요청을 한 번 실행한 결과(SUCCEEDED·FAILED·UNKNOWN)는 단건 조회의status·result로 봅니다. 단건 조회는 요청한 토큰도 자기 요청에 한해 할 수 있습니다. Store SDK는approvalRequests입니다. - 추가: 같은
Idempotency-Key로 다시 보낸 에이전트 요청은 같은 승인 요청을 씁니다. 요청 내용이 다르면409 IDEMPOTENCY_KEY_REUSED, 그 승인이 이미 끝났으면200(meta.code=APPROVAL_ALREADY_DECIDED)과 승인 요청입니다. - 추가: Store SDK
ApprovalPendingError. 승인 대기(202 APPROVAL_REQUIRED)와 끝난 승인(APPROVAL_ALREADY_DECIDED) 응답을 성공 값으로 돌려주지 않고 이 에러로 던집니다(approvalId·status·approval). - 추가:
GET /v1/audit-logs감사 로그. 관리 API의 모든 변경 요청을 행위자(USER·AGENT·APP·TOKEN·SYSTEM)·대상·결과· 멱등키·traceId와 함께 남기고 행위자·동작·대상·기간으로 거릅니다. 요청 기록은 1년 보관합니다. Store SDK는auditLogs.list입니다. - 추가: 스코프
audit:r. 상점 플랫폼 로그인에서는 OWNER·ADMIN이 가집니다. - 추가: MCP
call_api_write의dryRun, 도구get_approval_request. 판매자 취소·클레임 승인은 이제 막혀 있지 않고 승인 대기가 됩니다.
2026-09-26
MCP 검증 결과 집계
- 추가:
POST /v1/telemetry/mcp.@sayren/mcp가verify_storefront결과 요약(도구 이름·클라이언트 버전·임의의 세션 값· 호출 순번·실행 시간·통과 여부·검사한 파일 수·규칙별 통과/위반과 위반 개수)을 보냅니다. 파일 경로·소스 코드·위반 상세는 보내지 않습니다. 스코프가 필요 없고 상점은 토큰으로 정해지며 응답은 204입니다. 상점당 분당 60회·하루 2,000회이고, 하루 한도를 넘은 요청은 적재하지 않고 204로 받습니다. - 추가: MCP 환경변수
SAYREN_TELEMETRY.0이면 이 집계를 보내지 않습니다. 검증 결과 집계 참고.
웹훅·API 실패 원인 찾기
- 추가: 에러 응답
error.docs— 그 에러 코드를 설명하는 문서 주소입니다. 문서가 있는 코드에만 실리고 없으면 필드가 빠집니다. Store SDK는ApiError의docs로 읽습니다. 표준 응답 구조 참고. - 추가:
GET /v1/webhooks/{webhookId}/deliveries응답에failureReason— 실패 원인 분류입니다.DNS·TLS·TIMEOUT·CONNECTION·HTTP_4XX·HTTP_5XX·HTTP_OTHER·SSRF_BLOCKED·SUSPENDED이고 성공·미시도면null입니다. 기존errorCode보다 잘게 나눈 값이고 둘은 함께 옵니다. 값이 추가될 수 있어 문자열로 읽습니다. 실패 원인 분류 참고. - 추가: 같은 응답에
resource— 이벤트가 가리키는 대표 리소스{ type, id }입니다.type은 현재ORDER·CLAIM·PRODUCT·REVIEW·INQUIRY이고 특정할 수 없으면null입니다. 값이 추가될 수 있어 문자열로 읽습니다. Store SDK는 두 값을 문자열로 파싱하고 현재 값을WEBHOOK_FAILURE_REASONS·WEBHOOK_RESOURCE_TYPES로 제공합니다. - 변경:
responseBodyExcerpt의 상한이 1,024자에서 4,096자로 늘었습니다. - 추가: 전송 기록 목록 쿼리
eventType·resourceId.resourceId는 대표 리소스뿐 아니라 이벤트data에 실린 모든 ID를 보므로, 주문 ID로 그 주문의 클레임·품절 이벤트까지 찾습니다. - 추가:
GET /v1/webhooks/{webhookId}/deliveries/{deliveryId}전송 기록 상세. 목록 항목에payload(보낸 요청 본문 문자열 그대로)·payloadTruncated(16KB 초과 시true)·payloadMasked(민감 키 마스킹이 본문을 바꿨으면true, 그때는 서명을 맞춰 볼 수 없음)·requestHeaders([{ name, value }],Sayren-Signature는value가null,Content-Length는 실제로 보낸 본문의 바이트 수)를 더합니다. 재시도가 같은 기록에 누적되므로 응답 상태·본문·소요 시간·failureReason은 마지막 시도의 값입니다. 없으면404 WEBHOOK_DELIVERY_NOT_FOUND이고 권한은 전송 기록 조회와 같습니다. SDK는webhooks.getDelivery(webhookId, deliveryId)입니다. 전송 기록 상세 참고. - 추가:
POST /v1/webhooks/{webhookId}/test응답에failureReason·responseBodyExcerpt·requestHeaders·payload. 기존responseStatusCode·responseTimeMs·errorCode는 그대로입니다. - 변경: 응답 본문과 발송 본문은 저장·노출 전에 가립니다. 키 이름에
authorization·token·secret·password·key·signature·credential·cookie가 들어 있으면(부분 일치, 대소문자 무시) 값이***가 되고, 값이 객체·배열이면 통째로 가립니다. 응답 본문은 평문Authorization: …줄·Bearer <토큰>·access_token=…도 가리고, 가린 뒤에 4,096자로 자릅니다. 전송 기록 상세 참고. - 추가:
GET /v1/api-logs에 쿼리traceId(정확히 일치). 에러 응답의error.traceId를 그대로 넣어 그 요청 한 건을 찾습니다. SDK는apiLogs.list({ traceId })입니다. API 로그 › 조회와 필터 참고.
배송비 규칙과 출고지·반품지
- 추가:
GET·PATCH /v1/store에shippingPolicy— 상점 배송비 규칙 네 항목 (baseDeliveryFee기본 3000 ·freeThreshold기본null·jejuSurcharge·isolatedSurcharge기본 0).PATCH는 준 항목만 바꾸고 모르는 항목 이름은400입니다.GET은 정하지 않은 항목을 기본값으로 채워 전부 돌려줍니다. 바꾼 값은 새 주문서부터 적용됩니다. 배송비와 출고지·반품지 참고. - 호환성 변경 배송비가 배송 묶음(같은 출고지 + 같은 배송 정책인 상품)마다 한 번 붙습니다. 이전에는 같은 상품 단위였습니다. 출고지나 배송비가 다른 상품을 함께 주문하면 배송비가 묶음 수만큼 붙습니다.
- 호환성 변경 상품별 조건부 무료배송(
CONDITIONAL_FREE)의 기준액도 묶음 소계로 판정합니다. 출고지·배송비·기준액이 같은 상품은 서로 다른 상품이어도 금액을 합쳐 기준을 채웁니다. 이전에는 상품별 소계로만 판정했습니다. - 추가: 제주·도서산간 추가 배송비 — 배송지 우편번호가 해당 범위면 묶음마다 더합니다. 무료배송이어도 부과합니다. 우편번호 범위는 플랫폼이 고정하고 금액만 상점이 정합니다.
- 추가:
POST /storefront/v1/checkout/{checkoutId}/delivery-quote— 배송비 미리보기. 본문은zipCode(숫자 5자리)이고 응답은amounts·delivery입니다. 주문서를 바꾸지 않는 읽기 계산입니다. SDK는checkout.quoteDelivery()입니다. - 추가: 주문서 조회·배송비 미리보기·결제 시작 응답에
delivery—baseFee·remoteSurcharge·remoteArea·remoteAreaLabel·bundleCount·freeByThreshold·zipCode입니다. - 추가: 결제 시작(
POST /storefront/v1/checkout/{checkoutId}/payment) 응답에amounts— 보낸 배송지로 배송비를 다시 계산한 확정 결제 금액입니다. 주문서 조회 시점의amounts와 다를 수 있습니다(지역 추가 배송비). - 호환성 변경 상품 등록·수정에서
deliveryFee를 생략하면 상점 기본 배송비(shippingPolicy.baseDeliveryFee)로 저장합니다. 이전에는 0이었습니다. 배송비를 받지 않을 상품에는deliveryType: "FREE"또는deliveryFee: 0을 보냅니다. - 추가: 출고지·반품지 주소록
/v1/seller-addresses— 목록·등록·상세·수정·삭제와 기본 주소 지정 (POST /v1/seller-addresses/{addressId}/default). 유형(SHIPPING·RETURN)별 최대 10개이고 첫 주소가 기본 주소입니다. 조회는product:r, 나머지는product:rw입니다.409 ADDRESS_LIMIT_EXCEEDED·409 DEFAULT_ADDRESS_UNDELETABLE·409 ADDRESS_IN_USE·404 ADDRESS_NOT_FOUND. - 추가: 상품 등록·수정·조회에
shippingAddressId·returnAddressId. 생략하면 상점 기본 주소가 들어갑니다. - 추가: 클레임 조회(관리 API
GET /v1/claims·GET /v1/claims/{claimId}, 구매자 클레임 목록)에returnAddress— 수거 안내에 쓸 반품지(name·contactName·phone·zipCode·address1·address2)입니다. 상품이 지정한 반품지, 없으면 상점 기본 반품지이고, 취소 클레임과 반품지를 등록하지 않은 상점은null입니다. - 추가:
@sayren/store-sdk의sellerAddresses.list·create·update·remove·setDefault,@sayren/storefront-sdk의checkout.quoteDelivery. - 변경: 배송비 환불이 묶음 단위입니다. 묶음의 남은 수량이 0이 될 때만 그 묶음의 배송비를 환불하고, 묶음에 붙은 지역 추가 배송비도 함께 환불합니다. 묶음 구성은 주문 시점에 고정됩니다.
- 추가: 상점 플랫폼 설정에 배송(배송비 규칙·추가 배송비 지역)과 주소록(출고지·반품지) 화면이 생겼습니다.
현금영수증 발급
- 추가: 결제 시작(
POST /storefront/v1/checkout/{checkoutId}/payment)과 재시도(POST /storefront/v1/payments/{paymentId}/attempts) 본문에cashReceipt—type(INCOME_DEDUCTION소득공제 ·EXPENSE_PROOF지출증빙)과identityNumber(식별 번호)입니다. 계좌이체·가상계좌 옵션에서만 보낼 수 있고(그 밖의 옵션이면400 CASH_RECEIPT_NOT_AVAILABLE), 결제가 승인되면 결제한 결제사로 발급합니다. 구매자가 결제창에서 따로 입력하지 않습니다. 결제 연동 › 현금영수증 참고. - 식별 번호는 소득공제는 휴대폰 번호(
01X+ 78자리) 또는 현금영수증카드 번호(1319자리), 지출증빙은 사업자등록번호(10자리) 또는 현금영수증카드 번호입니다. 하이픈·공백은 빼고 읽습니다. 주민등록번호는 받지 않습니다 — 보내면400 VALIDATION_FAILED이고fieldErrors의cashReceipt.identityNumber코드가RESIDENT_NUMBER_NOT_ALLOWED입니다. 식별 번호는 암호화해 저장하고 응답에는 가린 값만 나갑니다(원문은 조회할 수 없습니다). - 추가: 관리 API
GET /v1/orders/{orderId}응답payment.cashReceipt,GET /v1/payments/{paymentId}응답cashReceipt—status·type·identityType·identityNumberMasked·amount·issuedAmount·provider·issueNumber·receiptUrl·issuedAt·canceledAt·failCode·failMessage·reissuable입니다. 신청이 없으면null입니다. 상태는REQUESTED결제 전 ·PENDING발급 대기 ·ISSUED발급 ·CANCELED취소 ·FAILED실패 ·SKIPPED발급 대상 아님이고, 값이 추가될 수 있어 문자열로 읽습니다. - 추가:
GET /v1/payments목록 행에cashReceiptStatus. 신청이 없으면null입니다. - 추가:
POST /v1/orders/{orderId}/cash-receipt/reissue재발급. 실패(FAILED)했거나 재시도를 기다리는(PENDING) 현금영수증을 지금 다시 발급·취소합니다. 스코프는order:rw이고 상점 플랫폼에 로그인한 OWNER·ADMIN만 호출할 수 있습니다.404 CASH_RECEIPT_NOT_FOUND·409 CASH_RECEIPT_NOT_REISSUABLE·409 CASH_RECEIPT_IN_PROGRESS. 결제 내역 › 현금영수증 참고. - 추가: 환불하면 발급한 금액을 그만큼 취소합니다. 전액 환불이면
CANCELED, 부분 환불이면 남은 금액으로 맞춥니다. 발급해야 할 금액(amount)은 결제 금액에서 환불 완료 금액을 뺀 값입니다. - 결제사 응답 지연 같은 일시적인 오류는 자동으로 다시 시도합니다. 식별 번호 오류처럼 결제사가 거절한 발급은
FAILED로 남으니failCode·failMessage를 보고 재발급하십시오. 발급이 늦거나 실패해도 결제와 주문은 그대로입니다. - 추가:
@sayren/storefront-sdk의checkout.startPayment·payments.start·payments.retry에cashReceipt와cashReceiptRequestSchema·cashReceiptAvailable·cashReceiptIdentityTypeOf,@sayren/store-sdk의orders.reissueCashReceipt(orderId)와 상태 값 목록CASH_RECEIPT_STATUS_VALUES. - 추가: 상점 플랫폼 주문 상세에 현금영수증 카드와 재발급 버튼이 생겼고, 결제 내역 상세에 현금영수증 상태가 실립니다.
택배 추적
- 추가: 택배 추적 — 택배로 발송한 주문 상품의 송장을 택배사에서 조회해 추적 이력을 보여 줍니다. 택배사가 배송완료를 알려 오면
주문 상품이 자동으로 배송완료로 바뀌고
ORDER.DELIVERED웹훅이 나갑니다. 자동 배송완료 대기일은 그대로 적용됩니다. 주문 처리하기 › 배송 추적 참고. - 추가: 관리 API
GET /v1/order-items/{orderItemId}/delivery에tracking(result·stage·checkedAt·carrierDeliveredAt),trackingEvents[]에stage. 택배 발송이 아니거나 추적을 쓰지 않으면tracking이null입니다.result는FOUND조회됨 ·NOT_FOUND택배사 전산에 송장 없음 ·UNSUPPORTED_CARRIER추적을 지원하지 않는 택배사이고, 값이 추가될 수 있어 문자열로 읽습니다.carrierDeliveredAt은 택배사가 알려 준 배송완료 시각이라 주문 상품의deliveredAt(추적을 반영한 시각)과 다를 수 있습니다. - 추가: 스토어프론트 API
GET /storefront/v1/me/order-items/{orderItemId}/delivery에trackingStage·trackingCheckedAt,trackingEvents[]에stage. 단계 값(ACCEPTED·IN_TRANSIT·OUT_FOR_DELIVERY·DELIVERED)은 늘어날 수 있어 문자열입니다. - 변경:
trackingEvents는 택배사에서 받은 이력입니다. 발송처리 때 넣던 예시 이벤트(집화처리)는 더 넣지 않습니다. 추적 전에는 빈 목록일 수 있습니다. - 추적은 주기적으로 갱신합니다. 발송처리 직후나 택배사에 이력이 올라간 직후 곧바로 반영되지는 않고, 배송완료 자동 전이도
그만큼 늦습니다. 마지막으로 받아 온 시각은
tracking.checkedAt(스토어프론트는trackingCheckedAt)입니다. - 추가: 상점 플랫폼 주문 상세에 배송 추적 카드가 생겼습니다.
구매자 동의 이력
- 추가:
GET·POST /storefront/v1/me/consents— 약관·개인정보·마케팅 동의의 현재 상태 조회와 변경입니다. 필수 동의는 동의(true)만 보낼 수 있고 마케팅은false로 철회합니다. 구매자 인증 › 동의와 재동의 참고. - 추가:
GET /storefront/v1/me에reconsentRequired— 약관이 개정돼 필수 동의를 다시 받아야 하면true입니다. 로그인 응답에는 실리지 않습니다(약관 개정은 로그인한 채로도 일어납니다). - 추가:
GET·PATCH /v1/store에termsVersion·privacyVersion(기본"1")·termsUrl·privacyUrl(https,null로 지웁니다)과 읽기 전용termsVersionUpdatedAt·privacyVersionUpdatedAt. 버전을 올리면 이전 버전에 동의한 구매자에게 재동의를 요구합니다. 이 네 필드는 OWNER만 바꿀 수 있습니다(다른 상점 정보는 그대로입니다). 동의 이력에는 동의한 시점의 문서 주소가documentUrl로 남습니다. - 추가:
POST /storefront/v1/auth/idp/{provider}/authorize에agreements— 소셜 가입 화면에서 받은 동의입니다. 이 로그인으로 가입이 되는 경우에만 이력에 남고, 기존 회원 로그인이면 무시합니다. 보내지 않아도 가입은 됩니다. 그때는 필수 동의 이력이 없어reconsentRequired가true이므로 첫 진입에서POST /me/consents로 받으면 됩니다. - 추가:
GET /v1/customers/{customerId}/consents— 구매자 동의 이력(최근 순,kind필터,customer:r). 가입·소셜 가입·회원 연동·재동의·마케팅 변경이 한 줄씩 남습니다. - 추가:
GET /v1/customers/{customerId}응답에consents— 종류별 현재 동의 상태와 재동의 필요 여부. - 추가:
@sayren/storefront-sdk의member.consents()·member.updateConsents(),@sayren/store-sdk의customers.consents(customerId, params). - 변경: 가입·소셜 가입·자체 회원 연동으로 구매자를 만들 때 동의 이력을 함께 남깁니다. 기존 회원에게는 가입 시각과
버전
"1"로 필수 동의 이력을 채웠습니다(마케팅은 동의 상태인 회원만). - 변경: 구매자 탈퇴·셀러 탈퇴 처리에서 동의 이력도 함께 지웁니다.
- 추가:
POST /storefront/v1/me/consents에 구매자당 분당 10회 한도가 생겼습니다. 넘으면429 TOO_MANY_REQUESTS이고error.details.retryAfterSeconds에 남은 초가 실립니다. - 추가: 상점 플랫폼 설정 › 상점 정보에 약관 카드, 고객 상세에 동의 카드가 생겼습니다.
환불 정책과 수량 단위 부분 취소
- 추가:
GET·PATCH /v1/store에refundPolicy— 취소·반품·교환의 배송비 부담을 정하는 다섯 항목 (preShipmentDeliveryFeeRefund·returnDeliveryFee·exchangeDeliveryFee·sellerFaultFreeShipping·conditionalFreeShortfallCharge).PATCH는 준 항목만 바꾸고GET은 정하지 않은 항목을 기본값으로 채워 전부 돌려줍니다. 환불 정책과 배송비 참고. - 추가: 상품 등록·수정·조회에
refundPolicy— 상품별 덮어쓰기. 준 항목만 상점 기본을 덮어쓰고,null이나 생략은 상점 기본을 씁니다.returnDeliveryFee·exchangeDeliveryFee를 주면returnFee·exchangeFee도 같은 값으로 맞춰집니다. - 추가: 수량 단위 부분 취소 — Storefront API
POST /claims와 관리 APIPOST /v1/order-items/{orderItemId}/cancel에quantity가 생겼습니다. 생략하면 남은 수량 전체입니다. 남은 수량보다 크면400 INVALID_QUANTITY이고, 남은 수량이 0이면 관리 API의 판매자 취소는409 ALREADY_CANCELED, 구매자 요청은409 INVALID_STATUS입니다. - 추가: 주문 상품 응답(관리 API·스토어프론트 API)에
canceledQuantity·activeQuantity. 일부 수량만 취소·반품된 주문 상품은 상태를 유지한 채activeQuantity가 줄고, 남은 수량이 0이 될 때CANCELED가 됩니다. - 추가: 금액 응답 필드 — 판매자 취소에
quantity·canceledQuantity·deliveryFeeRefundAmount·deliveryFeeChargeAmount, 클레임 승인에quantity·deliveryFeeRefundAmount·deliveryFeeChargeAmount, 클레임 접수에quantity·deliveryFeeRefundAmount, 구매자 클레임 목록에quantity. - 변경: 클레임 승인 응답의
deliveryFeeChargeAmount에는 판매자가 넣은 추가 차감(deductAmount)이 들어 있지 않습니다. 두 값을 더해 환불액에서 뺍니다. - 추가: 클레임 조회(관리 API
GET /v1/claims·GET /v1/claims/{claimId}, 구매자 클레임 목록)에expectedDeliveryFeeRefundAmount— 접수 시점의 예상 배송비 환불액입니다. 이 필드가 생기기 전에 접수된 클레임은null입니다.expectedRefundAmount에는 배송비 환불이 들어 있지 않고, 조건부 무료배송 미달 차감은 이미 빠져 있습니다. - 추가:
CLAIM.*웹훅data에quantity·refundAmount·deliveryFeeRefundAmount·deliveryFeeChargeAmount·deductAmount. 이전 이벤트에는 없어0(refundAmount는null)으로 읽습니다. 모르는 필드를 거부하는 방식(strict)으로 검증한다면 다섯 필드를 허용하도록 바꿉니다.deliveryFeeChargeAmount는 배송비 차감(반품·교환 배송비 + 조건부 무료배송 기준 미달)만이고 판매자가 승인에 넣은 추가 차감은deductAmount입니다. 환불액은refundAmount = 상품 금액 + deliveryFeeRefundAmount − deliveryFeeChargeAmount − deductAmount로 읽습니다. - 변경: 취소·반품 환불액이 수량 비율이 됐습니다. 원 단위 반올림을 누적 금액 기준으로 하므로 나눠 처리해도 환불액의 합이 주문 상품 금액과 정확히 같습니다. 재고 복원과 PG 부분 취소도 같은 수량 비율입니다.
- 변경: 배송비는 배송 묶음(같은 상품의 주문 상품)의 남은 수량이 0이 될 때만 환불합니다. 한 묶음의 배송비는 한 번만 정산되고, 주문이 낸 배송비를 넘겨 환불하지 않습니다.
- 변경: 교환 재고 — 수거 완료에서 원래 옵션을 복원하고 재배송 등록에서 구매자가 고른 새 옵션을 차감합니다.
새 옵션의 재고가 부족하면 재배송 등록이
409 OUT_OF_STOCK입니다.
배송완료 처리와 자동 전이
- 추가:
POST /v1/order-items/{orderItemId}/delivered— 발송(DISPATCHED)·배송중(DELIVERING) 주문 상품을 배송완료(DELIVERED)로 바꿉니다. 여러 건은POST /v1/order-items/delivered에{ "orderItemIds": [...] }로 보냅니다. 주문 처리하기 참고. - 추가:
GET·PATCH /v1/store에autoDeliverDays·autoConfirmDays(각 0~30, 기본 7)가 생겼습니다. 발송 후 N일이 지난 주문 상품을 배송완료로, 구매확정 예정일이 지난 주문 상품을 구매확정으로 자동 전이합니다.0이면 그 자동 전이를 하지 않고, 진행 중인 취소·반품·교환이 있는 주문 상품은 빠집니다. - 변경: 배송완료 시점에 구매확정 예정일(
autoDecisionDate)을autoConfirmDays로 다시 잡습니다. 전에는 발송 시점에 7일로 고정해 넣었습니다. - 변경:
ORDER.DELIVERED웹훅이 실제로 발송됩니다.ORDER.PURCHASE_DECIDED는 자동 구매확정에서도 발송됩니다. - 변경: 반품·교환 가능 기간이 고정 7일에서 상점 설정
autoConfirmDays(기본 7일, 연장분 포함)로 바뀌었습니다. 자동 구매확정 기한과 같은 값이라, 구매확정된 뒤에 반품을 받을 수 없는 구간이 생기지 않습니다. 기간이 지난 요청은 그대로409 PERIOD_EXPIRED입니다. - 변경: 구매확정 기한 연장(
POST /v1/order-items/{id}/purchase-decision/extend)의autoDecisionDate를 배송완료 시각 + (autoConfirmDays+ 연장 횟수 × 7일)로 다시 계산합니다. 전에는 기존 예정일에 7일을 더했습니다. - 추가:
@sayren/store-sdk의orderItems.markDelivered(orderItemId)·orderItems.markDeliveredBulk(orderItemIds). - 추가: 상점 플랫폼 주문 상세에 배송완료 버튼과 선택 일괄 처리가 생겼고, 설정 › 상점 정보에 자동 전이 대기일 입력이 생겼습니다.
상품 이미지 업로드 (호환되지 않는 변경)
- 제거:
POST /v1/product-images. 상품 이미지는POST /v1/uploads로 자리를 받아uploadUrl에 파일을 직접PUT하고, 받은url을 상품의images에 넣습니다. 상품 이미지 등록 참고. - 추가:
POST /v1/uploads요청에purpose(product-image·description, 생략하면description)와size가 생겼습니다. 용도에 따라 허용 형식과 장당 최대 크기가 다릅니다 (product-image는 jpg·jpeg·png·webp·avif·gif, 10MB /description은 svg·동영상 포함, 50MB). 제한을 넘으면400 UNSUPPORTED_FILE_TYPE또는413 FILE_TOO_LARGE입니다. - 변경: 상품 등록·수정의
images는https주소만 받고, 주소에 확장자가 있으면 이미지 형식이어야 합니다 (400 INVALID_IMAGE_URL·400 UNSUPPORTED_FILE_TYPE). 사내 CDN 밖의 주소도 그대로 넣을 수 있고, 이미 그 상품에 저장돼 있던 주소는 다시 검사하지 않습니다. - 변경: 스토어프론트 API의
thumbnailUrl이 nullable이 됐습니다(상품 목록·상세, 장바구니, 주문 상품, 작성 가능 리뷰). 전에는 이미지가 없으면 열리지 않는 자리표시 주소를 돌려줬습니다. 이제null이고 자리표시 화면은 스토어프론트가 그립니다.@sayren/storefront-sdk스키마도 nullable입니다. - 추가: 올린 이미지는 주소에
?w=·?h=(1~4096)·?f=webp|avif를 붙여 줄이거나 포맷을 바꿔 받을 수 있습니다. - 추가:
@sayren/store-sdk의uploads.upload(file, { purpose })— 자리 발급과 파일PUT을 한 번에 합니다. - 추가: 상점 플랫폼 상품 등록·수정에 이미지 섹션이 생겼습니다. 올리기·순서 바꾸기·대표 지정·삭제를 합니다.
2026-09-25
결제 흐름 개편 (호환되지 않는 변경)
- 변경: 결제창을 sayren이 그립니다. 결제 시작 응답의 결제 주소(
payUrl)를 팝업이나 현재 탭으로 열면 결제 화면이 PG 결제창을 띄우고 승인까지 끝냅니다. 스토어프론트는 PG 스크립트도 승인 키도 다루지 않습니다. 결제 연동 참고. - 변경: 결제 시작 응답이
{ paymentId, attemptId, option, payUrl, expiresAt, testPayment }로 바뀌었습니다 (pgProvider·pgParams·launch삭제). SDK의checkout.requestPayment는checkout.startPayment로 바뀌었습니다. - 제거: 결제 승인
POST /payments/{paymentId}/confirm과 결제창 실패 보고POST /payments/{paymentId}/attempts/{attemptId}/failure. 공개 결제 API는 결제 시작·재시도·상태 조회 셋뿐입니다. - 추가: 주문서 응답
paymentOptions— PG × 결제수단 × 간편결제사로 된 결제 옵션 목록. 결제 시작은 옵션 하나({ pg, method, provider? })와 복귀 주소(returnUrl)를 보냅니다. 옵션을 바꾸는 것만으로 다른 결제사로 결제합니다. - 추가: 간편결제 — 네이버페이·카카오페이·토스페이·페이코 결제창을 바로 엽니다(
method: "EASY_PAY",provider). 상점 플랫폼 PG 상세에서 켭니다. - 추가: Storefront API
POST /payments/{paymentId}/attempts— 같은 결제를 다른 옵션으로 다시 시도하고 새payUrl을 받습니다.returnUrl을 생략하면 결제 시작 때의 복귀 주소를 씁니다. - 추가:
GET /payments/{paymentId}응답에result(COMPLETED·PROCESSING·CANCELED·FAILED·EXPIRED·PENDING)와lastFailure가 생겼습니다. 결제 결과 판정은 이 값으로 합니다. - 추가: 결과 전달 규약 — 팝업이면 결제 화면이
postMessage({ type: "sayren:payment", … })를 보내고, 리다이렉트면 복귀 주소에sayrenPaymentId가 붙습니다. 둘 다 신호이고 판정의 근거는 상태 조회입니다. SDK 없이 쓰는 방법은 SDK 없이 결제 연동에 있습니다. - 추가: 결제 도메인 — 상점 플랫폼 설정 › 결제에 스토어프론트 주소를 등록하면 복귀 주소가 그 목록으로 제한됩니다.
선택 항목이라 비워 두면 모든 https 복귀 주소를 받습니다(테스트 결제는 localhost 허용). 목록 밖은
400 RETURN_URL_NOT_ALLOWED. 관리 APIPUT /store/payment-settings의checkoutOrigins. - 변경: 자동 전환·라우팅 방식을 없앴습니다. PG 우선순위는 결제 옵션 목록의 순서입니다. 관리 API 결제 설정에서
routingMode·effectiveRoutingMode가 빠졌습니다. - 변경:
@sayren/storefront-sdk/payments가start·retry·open·prepareWindow·result·getStatus로 바뀌었습니다 (complete·launch삭제). 결제창 방식은mode(auto·popup·redirect)로 고르고, 기본값은 모바일 리다이렉트·PC 팝업입니다. PG SDK 의존성(@tosspayments/*·@portone/*)이 빠졌습니다. @sayren/storefront-sdk0.8.0,@sayren/store-sdk0.8.0,@sayren/mcp0.2.0(템플릿 결제 화면·복귀 화면·검사 규칙).
상세설명 에디터
- 수정: API로 등록한 상품처럼 상세설명이 HTML로만 있는 상품도 상점 플랫폼 상세설명 에디터에서 기존 본문(사진 포함)을 불러옵니다. 전에는 빈 에디터로 열려 저장하면 기존 본문이 바뀌었습니다.
- 코드블록으로 끝난 글도 본문 아래 빈 곳을 누르면 이어 쓸 수 있습니다.
- MCP 템플릿의 에디터 의존성을 최신으로 올렸습니다.
@sayren/mcp0.1.11.
구매자 계정 연결·자체 회원 연동
- 추가: Storefront API
GET /me/identities,POST /me/identities/{provider}/authorize,POST /me/identities/{provider},DELETE /me/identities/{provider}— 로그인한 구매자의 소셜 계정 연결·해제.@sayren/storefront-sdk/auth의identities()·linkIdp()·linkIdpCallback()·unlinkIdp(). - 추가: 구매자 위임의
member-uid(자체 회원 시스템의 사용자 id로 지목).@sayren/store-sdk/server의delegateMemberByUid()·delegateMemberByEmail(). - 변경: 소유자가 상점 플랫폼 개발자 › 앱에서 서버 앱에 구매자 위임(
member:delegate)을 줄 수 있습니다. - MCP 템플릿에 내 정보(
/account) 화면: 로그인 수단 보기·소셜 계정 연결·해제.@sayren/mcp0.1.10. @sayren/storefront-sdk0.7.0,@sayren/store-sdk0.7.0.
방문 분석 2단계
- 추가: 관리 API
GET /analytics/realtime(최근 5분 방문자·세션·페이지),GET /analytics/devices(기기별 세션 퍼널),GET /analytics/pages(첫 페이지·이탈 페이지),GET /analytics/search(검색어별 검색·결과 없음·검색 후 구매, 결과 없는 검색어zeroResultTerms),GET /analytics/checkout(결제 요청의 결과별 수, 진행 중은IN_PROGRESS). - 추가:
GET /analytics/overview의excludedBotSessions(집계에서 뺀 봇 세션 수),GET /analytics/products행의clickThroughRate(목록 노출 → 상세 조회). - 상점 플랫폼 분석 › 애널리틱스: 개요의 이탈률을 반송률로 바꿨습니다(정의는 같습니다). 개요에 실시간 방문, 전환 퍼널에 결제 단계 결과·기기별 퍼널, 상품 분석에 노출 → 조회, 유입 경로에 첫 페이지·이탈 페이지, 새 검색 탭. 좌측 메뉴로 다시 들어와도 마지막으로 고른 기간을 유지합니다.
- 원본 이벤트가 남아 있는 날(최근 89일)의 집계도 새 기준으로 다시 계산됩니다(10분마다 조금씩).
@sayren/store-sdk0.7.0:analytics.realtime·devices·pages·search·checkout.
구매자 토큰 갱신
- 변경: 같은 리프레시 토큰으로 동시에 갱신해도 로그아웃되지 않습니다. 쓴 토큰은 30초 안에 3번까지 더 받아 새 쌍을 주고, 30초가 지나거나 3번을 넘으면
401 INVALID_REFRESH_TOKEN입니다.
클레임 처리
- 추가:
GET /claims의status가 쉼표로 여러 상태를 받습니다(예:REQUESTED,HELD,COLLECTED). 모르는 값은400 VALIDATION_FAILED입니다. - 추가: 클레임 응답의
holdExpiresAt(보류 자동 해제 시각)·holdUsed(보류 사용 여부). 보류는 해제한 뒤에도 다시 할 수 없고, 7일이 지나면 자동으로 풀려 접수로 돌아옵니다. 끝난 클레임은 보류할 수 없습니다. - 추가:
POST /claims/{claimId}/complete-exchange교환 완료. 재배송 중인 교환을 끝내고CLAIM.COMPLETED웹훅을 보냅니다. - 변경: 같은 클레임을 동시에 처리하면 한 요청만 적용되고 나머지는
409 INVALID_STATUS입니다. 동시 승인으로 환불이 두 번 나가지 않습니다. - 변경: 보류는 접수(
REQUESTED) 상태에서만 할 수 있습니다. 그 밖의 상태는409 INVALID_STATUS입니다. - 변경: 재배송 중(
REDELIVERING)인 교환은 거절할 수 없습니다(409 INVALID_STATUS). 교환 완료로 마칩니다. - 이미 재배송 중인 교환은 셀러가 교환 완료를 눌러야 끝납니다. 끝나기 전에는 진행 중인 클레임으로 남습니다.
- 상점 플랫폼: 판매 › 클레임이 처리 필요·진행 중·전체 탭과 행마다 다음 처리 버튼(수거 등록·수거 완료·환불 승인·재배송 등록·교환 완료)으로 바뀌었습니다. 반품 환불 승인에 추가 차감, 보류·보류 해제, 상세 보기(단계·처리 이력)가 생겼습니다.
@sayren/store-sdk0.6.0:claims.completeExchange,claims.list의status배열. 클레임 응답의holdExpiresAt·holdUsed를 필수로 읽습니다.
2026-09-24
스토어프론트 템플릿 TanStack Router 전환
- 변경: MCP가 내려주는 스토어프론트 템플릿이 React Router에서 TanStack Router(TanStack Start, SSR)로 바뀌었습니다. 화면과 구매 흐름은 같고 파일 구성이
app/에서src/(파일 기반 라우트)로 바뀌었습니다. 이미 만든 쇼핑몰은 그대로 동작합니다. MCP로 만들기를 참고하십시오. @sayren/mcp0.1.9.
상점 플랫폼 시작하기
- 상점 플랫폼: 로그인 화면을 새로 만들었고, 상점 만들기가 대화상자에서 전용 화면으로 바뀌었습니다. 상점이 없는 계정은 로그인 직후 이 화면으로 갑니다.
- 상점 플랫폼: 상점 선택 화면을 최근 사용 순으로 바꿨습니다. 상점이 많으면 검색·역할 필터가 생기고, 이용정지·폐점 상점은 들어갈 수 없게 표시합니다.
- 상점 플랫폼: 새 상점의 시작하기(스토어프론트 만들기·테스트 결제 연결·첫 상품 등록). 화면에서 MCP 토큰을 바로 발급하고 연결을 확인합니다. MCP로 만들기를 참고하십시오.
소셜 로그인
- 추가: 구매자 카카오·네이버·구글 로그인. 스토어프론트 API
POST /auth/idp/{provider}/authorize,POST /auth/idp/token(PKCE).@sayren/storefront-sdk/auth의idp()·idpCallback(). - 추가: 관리 API
GET·PATCH /store/login-settings,PUT·PATCH·DELETE /store/auth-providers/{provider},POST /store/auth-providers/{provider}/test(상점 플랫폼 OWNER 전용). - 추가:
PATCH /store·GET /store의storefrontOrigins(스토어프론트 도메인). 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓰는 목록입니다.analyticsAllowedOrigins는 같은 값의 옛 이름으로 남습니다. - 추가: 상점 공개 설정
loginMethods. 이메일·비밀번호를 끄면 비밀번호 가입·로그인이403 PASSWORD_LOGIN_DISABLED입니다. - 변경: 구매자
email이null일 수 있습니다(소셜 가입에서 이메일을 받지 못한 경우). 소셜 전용 구매자의 탈퇴는 비밀번호 대신 최근 로그인 토큰으로 확인합니다(403 REAUTH_REQUIRED). - 상점 플랫폼: 설정 › 로그인(로그인 방법 카드, 스토어프론트 도메인, 자체 회원 연동). 방문 분석 수집 도메인 카드는 여기로 옮겼습니다.
@sayren/store-sdk0.5.0,@sayren/storefront-sdk0.6.0.
구매자 관리와 비회원 주문 설정
- 추가: 관리 API
GET /customers(검색·가입일·마케팅 수신·정렬),GET /customers/{customerId},GET /customers/{customerId}/orders(전체 기간),POST /customers/{customerId}/withdraw(탈퇴 처리). 새 스코프customer:r(OWNER·ADMIN·STAFF)·customer:rw(OWNER·ADMIN). - 추가:
PATCH /store·GET /store의guestCheckoutEnabled.false면 비회원의 주문서 생성·결제 요청이403 GUEST_CHECKOUT_DISABLED입니다. - 추가: 스토어프론트 API
GET /store상점 공개 설정(guestCheckout포함). - 상점 플랫폼: 고객 › 구매자(목록·상세·탈퇴 처리), 설정 › 상점 정보 › 비회원 주문.
@sayren/store-sdk0.4.0(customers.*),@sayren/storefront-sdk0.5.0(store.get).
구매자 인증
- 추가:
POST /auth/withdraw구매자 탈퇴. 비밀번호로 본인 확인을 하고 계정·배송지·위시리스트·장바구니·적립금을 지웁니다. 주문·클레임·리뷰·문의 기록은 남습니다. 진행 중인 주문·클레임·결제가 있으면409 WITHDRAWAL_BLOCKED입니다.@sayren/storefront-sdk0.4.0에auth.withdraw가 추가됐습니다. - 추가:
POST /auth/anonymous비회원 세션 발급({ cartToken, expiresAt }). - 변경: 비회원 장바구니 토큰(
X-Cart-Token)이 비회원 세션이 됐습니다. 마지막 활동 후 30일이 지나면 만료되고 장바구니도 지워집니다. 담은 적 없는 세션은 하루 뒤 지워집니다. 로그인으로 회원 장바구니에 합친 토큰은 더는 쓸 수 없고, 만료·종료된 토큰으로 장바구니를 부르면 새 토큰이 발급됩니다. - 추가:
POST /auth/signup의cartToken. 가입과 함께 비회원 장바구니를 합칩니다. @sayren/storefront-sdk0.3.0에@sayren/storefront-sdk/auth(createStorefrontAuth:anonymous·session·signUp·refresh·signOut)와auth.anonymous가 추가됐습니다. 사용법은 구매자 인증을 참고하십시오.
상점 플랫폼 메뉴
- 메뉴 순서가 대시보드 → 상품 → 판매 → 고객 → 분석으로 바뀌었습니다. 매출 리포트·결제 내역은 분석 섹션으로 옮겼습니다.
- 애널리틱스는 메뉴 한 항목(분석 › 애널리틱스)이 되고, 개요·전환 퍼널·상품 분석·유입 경로는 화면 안 탭으로 오갑니다. 주소(
/analytics/funnel등)는 그대로입니다.
방문 분석 수집 도메인 제한
- 추가:
PATCH /store의analyticsAllowedOrigins, 응답analyticsAllowedOrigins. 목록을 정하면 그 오리진에서 보낸 방문 분석 수집만 받고, 목록 밖은403 ORIGIN_NOT_ALLOWED입니다. 비우면(기본) 이전처럼 모두 받습니다. - store-sdk에
store.update가 추가됐습니다. - MCP
verify_storefront가 방문 분석 시작(analytics-start)과 서버 API 클라이언트의 방문 식별자(analytics-ids)를 검사합니다.
방문 분석 수집
- 쿼리만 다른 페이지(페이지 넘기기·검색어·필터 변경)를 서로 다른 페이지뷰로 셉니다. 이전에는 같은 경로를 10초 안에 다시 보면 한 번으로 셌습니다.
- 수집 한도가 방문자당 분당 120개로 늘었습니다.
@sayren/storefront-sdk0.2.1은 전체 분당 100개까지만 보내고, 상한으로 버린 페이지뷰의 상품 조회·체류는 보내지 않습니다.
2026-09-23
방문 분석 통계 조회
- 추가:
GET /analytics/overview·GET /analytics/products·GET /analytics/sources. 스토어프론트에서 수집한 방문을 날짜별로 집계해 개요·퍼널·상품·유입 통계를 돌려줍니다. 방문 분석 참고. - 새 스코프
analytics:r. 상점 플랫폼 로그인에서는 OWNER·ADMIN이 가집니다. API 토큰·앱에는 발급할 때 지정합니다. - store-sdk에
analytics.overview·analytics.products·analytics.sources가 추가됐습니다.
방문 분석
- 스토어프론트 SDK에 방문 분석 모듈
@sayren/storefront-sdk/analytics가 추가됐습니다. 페이지뷰·상품 조회·목록 노출·검색·체류 시간을 수집합니다. 방문 분석 참고. - 추가:
POST /storefront/v1/events(수집), SDKanalyticsIdsFromCookie,createStorefrontClient의visitorId·sessionId옵션. - 스토어프론트 API 요청에
x-sayren-visitor·x-sayren-session헤더를 실으면 장바구니 담기·빼기, 결제 시작, 구매가 서버에서 그 방문에 이어 기록됩니다.
문서 주소
- 문서가
https://docs.sayren.app/(루트)로 옮겨졌습니다. 예를 들어 웹훅 가이드는https://docs.sayren.app/guides/webhooks입니다. 옛 주소https://docs.sayren.app/docs/…는 새 주소로 영구 리다이렉트(301)합니다.
OpenAPI 문서 주소
- OpenAPI 문서 주소가 바뀌었습니다. 관리 API는
https://api.sayren.app/openapi/store.json, 스토어프론트 API는https://api.sayren.app/openapi/storefront.json입니다(YAML은 확장자만.yaml). 옛 주소/docs/admin.json·/docs/storefront.json은 새 주소로 리다이렉트(308)합니다. - 모든 오퍼레이션에 요청 본문·응답 스키마가 실립니다. 오퍼레이션별 필요 스코프는
x-required-scopes, 상점 플랫폼 로그인이 필요한 오퍼레이션은x-console-only: true로 표시됩니다. 멱등키를 받는 오퍼레이션에는Idempotency-Key헤더가 문서화됐습니다. GET /products의status쿼리가 문서에 추가됐습니다.
MCP로 상점 운영
- MCP에 관리 API 도구 4개(
list_operations·describe_operation·call_api_read·call_api_write)가 추가됐습니다. 대화로 상점을 조회하고 바꿀 수 있습니다. AI로 상점 운영하기 참고. get_store_context의productCount는 등록된 상품 전체 수입니다. 구매자에게 보이는 수는publicProductCount입니다.npx @sayren/mcp create <폴더>로 스토어프론트 템플릿을 한 번에 받습니다.
2026-09-19
결제(PG) 연결
- 셀러가 직접 계약한 토스페이먼츠·포트원으로 결제를 받습니다. 결제 대금은 PG가 셀러에게 바로 정산합니다. 결제 설정 참고.
- PG마다 테스트 키와 라이브 키를 따로 등록하고, 샌드박스 모드(기본 켜짐)로 어느 키로 결제할지 정합니다. 샌드박스 모드를 끄려면 라이브 전환 조건 5개를 채워야 합니다. 샌드박스에서 라이브로 전환하기 참고.
- 추가:
GET·PUT /store/payment-settings,PUT /store/payment-providers/tosspayments,PUT /store/payment-providers/portone,PATCH·DELETE /store/payment-providers/{provider},DELETE /store/payment-providers/{provider}/credentials/{environment},POST /store/payment-providers/{provider}/verify. 상점 플랫폼에 로그인한 OWNER만 호출할 수 있습니다. 새 에러409 LIVE_GATE_NOT_MET·LIVE_PAYMENTS_DISABLED(error.details.conditions에 조건별 충족 여부),409 PAYMENT_PROVIDER_VERIFICATION_FAILED·PAYMENT_CREDENTIAL_ACTIVE·PAYMENT_CREDENTIAL_CHANGED·PAYMENT_PROVIDER_CHANGED,404 PAYMENT_CREDENTIAL_NOT_FOUND. 토스페이먼츠 결제위젯 키는400 VALIDATION_FAILED로 거부되고fieldErrors에credentials.clientKey·credentials.secretKey가 담깁니다. GET /store/payment-settings응답의candidates·environment로 지금 결제에 쓰는 PG와 결제 환경을,providers[].routingExclusion으로 후보에서 빠진 사유를 확인합니다.- 가맹점을 바꾸거나 연결을 해제해도 이전 키는 보관돼 그 가맹점으로 받은 결제의 취소·환불에 계속 쓰입니다.
- 두 PG를 모두 쓰면 라우팅 방식으로
AUTO_FAILOVER(기본) 또는PRIORITY_DISPLAY를 고릅니다. - 샌드박스 모드에서 받은 결제는 테스트 결제입니다. 관리 API
GET /orders·GET /orders/{orderId}·GET /order-items와 주문상품 처리 응답, 스토어프론트 API 내 주문·비회원 주문 조회 응답에testPayment가 추가됐습니다.GET /orders·GET /order-items는 쿼리testPayment=true|false로 거를 수 있습니다. 세 주문 조회 API가 API 레퍼런스에 문서화됐습니다. - 웹훅
ORDER.*·CLAIM.*의data에testPayment가 추가됐습니다. 수신 측에서data를 모르는 필드를 거부하는 방식(strict)으로 검증한다면 이 필드를 허용하도록 바꿔야 합니다. 웹훅 참고. - 테스트 결제 주문에는 리뷰를 쓸 수 없습니다. 작성 가능 목록에서 빠지고, 작성하면
409 REVIEW_NOT_ALLOWED_FOR_TEST_ORDER입니다. - 결제 요청
POST /storefront/v1/checkout/{checkoutId}/payment에 새 에러409 PAYMENT_NOT_CONFIGURED,503 PAYMENT_PROVIDER_UNAVAILABLE이 추가됐습니다.pgProvider는tosspayments또는portone입니다. 주문서 생성과 결제 요청 응답에testPayment가 추가됐습니다. - 호환성 변경
pgParams에서successUrl·failUrl을 제거하고attemptId·provider·mock·environment를 추가했습니다.popupUrl만 쓰는 연동은 영향이 없습니다. - 추가:
GET /storefront/v1/payments/{paymentId}. 결제 상태(status)·주문번호·테스트 결제 여부·만료 시각을 인증 없이 조회합니다. 팝업의 결과 메시지를 받지 못했을 때 쓰십시오. 결제 연동 참고. - 결제 승인
POST /storefront/v1/payments/{paymentId}/confirm본문에 선택 필드attemptId가 추가됐습니다. 새 에러402 PAYMENT_NOT_APPROVED,409 PAYMENT_RESULT_UNKNOWN·ATTEMPT_NOT_CURRENT·INVALID_ATTEMPT_STATE·PAYMENT_SESSION_OUTDATED·PG_AMOUNT_MISMATCH·PG_ENVIRONMENT_MISMATCH·LATE_APPROVAL_CANCELED,502 PG_REQUEST_FAILED,503 PG_CREDENTIALS_UNAVAILABLE·PG_MERCHANT_MISMATCH. (이 API는 2026-09-25에 제거됐습니다.) - 호환성 변경 카드 거절처럼 승인되지 않은 것이 확정되면 결제 세션이
failed가 아니라pending으로 남습니다. 같은 세션에서 다른 결제사나 같은 결제사로 다시 결제할 수 있습니다. - 호환성 변경 결제수단의 뜻이 요청한 결제수단에서 실제 결제수단으로 바뀌었습니다. 실제 결제수단은 PG가 알려 준 수단이고,
알려 주지 않으면 요청한 수단입니다. 카드로 요청하고 결제창에서 간편결제로 결제하면 두 값이 다릅니다. 필드 형태와 값 목록은 그대로입니다.
GET /sales-report:method쿼리 필터와rows[].method. 카드였던 행 일부가EASY_PAY등으로 옮겨 갈 수 있습니다.GET /orders/{orderId}의payment.method. 관리 API 결제수단에는 간편결제가 없어 간편결제는 종전처럼CARD로 나갑니다. 실제 결제수단을 그대로 보려면 새로 추가한payment.approvedMethod를 쓰십시오(추가). 결제 기록이 없는 오래된 주문은null입니다.- 스토어프론트
GET /me/orders,GET /me/orders/{orderId},POST /guest/orders/{orderId}의payment.method.EASY_PAY가 그대로 나갑니다. - 주문 응답은 새 주문부터 적용되고, 기존 주문은 요청한 결제수단 그대로입니다. 웹훅과 결제 요청·주문서의
paymentMethod는 바뀌지 않았습니다.
- 호환성 변경 새로 만드는 결제 id(
paymentId)가 길어졌습니다(pay_뒤 32자). 이미 만든 결제는 그대로입니다. id의 형식이나 길이를 가정해 저장·검증했다면 바꿔야 합니다. - 결제 시작과 결제 승인의 에러 응답이 API 레퍼런스에 문서화됐습니다.
- 결제 관련 에러 메시지(
error.message)의 문구를 바꿨습니다. 에러 코드는 그대로이니 분기는error.code로 하십시오. - Storefront SDK:
checkout.confirmPayment의 세 번째 인자{ attemptId },payments.getStatus, 상태 값 목록PAYMENT_STATUS_VALUES를 추가했습니다. - Store SDK:
paymentSettings.*,liveGateErrorDetailsSchema,PAYMENT_ROUTING_EXCLUSION_CODES, 주문 목록testPayment인자를 추가했습니다. 토스페이먼츠 결제위젯 키는 요청 전 검증에서ZodError로 거부됩니다.
매출 리포트
- 추가:
GET /sales-report. 기간·PG·결제수단별 결제·환불·순매출을 집계하며settlement:r스코프가 필요합니다. 테스트 결제는 기본으로 빠지고includeTest=true로 포함합니다. 매출 리포트 참고. - 호환성 변경 구매확정 때 정산 내역을 쌓지 않습니다. 플랫폼 수수료를 공제하는 정산은 폐기됐고, 기존 정산 내역은 그대로 조회됩니다.
GET /settlements,GET /settlements/{settlementId}는 폐기 예정입니다. 응답에Deprecation: true와Link: </v1/sales-report>; rel="successor-version"헤더가 붙습니다.- Store SDK:
salesReport.get을 추가했고settlements.*는 폐기 예정입니다. - 상점 플랫폼 정산 › 정산 내역은 매출 › 매출 리포트로 바뀌었습니다.
스토어프론트 만들기 (MCP)
- 추가: sayren MCP 서버(
npx @sayren/mcp). 코딩 도구에 붙이면 상점 컨텍스트·검증된 템플릿·생성 규칙· 결과 검증을 도구로 제공합니다. 스토어프론트 만들기 참고. - 템플릿은 React Router(SSR) 기반이고 구매 흐름 전체(홈·목록·상세·장바구니·주문서·결제·주문 내역)를 담습니다.
- 상점 플랫폼 개발자 › 스토어프론트 만들기에서 연결 설정과 프롬프트를 복사할 수 있습니다.
결제 내역
- 추가:
GET /payments,GET /payments/{paymentId}. 결제 건 단위 조회이고settlement:r스코프가 필요합니다. 주문이 만들어지지 않은 결제(카드 거절·결제창 이탈·승인 결과 확인 중)도 나오고, 상세에는 시도 이력과 환불 이력이 함께 담깁니다. 실패한 환불 요청도 남습니다. 결제 내역 참고. - 기간 기준은 결제 시작 시각이고 최대 92일입니다. 생략하면 최근 30일이며, 테스트 결제는
includeTest=true일 때만 포함합니다. - Store SDK:
payments.list·payments.get을 추가했습니다. - 상점 플랫폼 매출 › 결제 내역을 추가했습니다.
공통
- 에러 엔벨로프
$.error에 선택 필드details를 추가했습니다. 일부 에러 코드에만 보조 데이터가 담기며, 없으면 필드가 빠집니다.
웹훅 전송
- 등록한 주소로 이벤트를 실제로 전송합니다. 요청 형식, 헤더, 이벤트별
data는 웹훅을 참고하십시오.ORDER.DELIVERED,ORDER.ADDRESS_CHANGE_REQUESTED, 교환 클레임의CLAIM.COMPLETED는 아직 발송되지 않습니다. Sayren-Signature헤더로 서명합니다(t=<unix 초>,v1=<HMAC-SHA256 hex>). 시크릿 교체 후 24시간 동안은 새 시크릿과 기존 시크릿 서명을 함께 싣습니다.- 실패하면 1분·5분·30분·2시간 뒤에 재시도합니다. 첫 실패부터 24시간 이상 성공 없이 실패가 이어지면 구독이
SUSPENDED로 바뀝니다. - 추가:
POST /webhooks/{webhookId}/resume,POST /webhooks/{webhookId}/deliveries/{deliveryId}/redeliver,POST /webhooks/{webhookId}/deliveries/redeliver-failed. 재전송은 원본 기록당 한 번입니다. 새 에러 코드WEBHOOK_DELIVERY_NOT_FOUND(404),DELIVERY_NOT_FAILED·DELIVERY_ALREADY_REDELIVERED·WEBHOOK_SUSPENDED(409). GET /webhooks/{webhookId}/deliveries가 실제 전송 기록을 반환합니다(최근 30일).status·limit쿼리를 받습니다. 응답에status: PENDING과url·errorCode·attemptCount·attemptedAt·nextAttemptAt·responseBodyExcerpt·redeliveryOf·redeliveredAs필드가 추가됐습니다.POST /webhooks/{webhookId}/test가 등록한 주소로 실제 요청을 보내고 측정한 응답 코드와 응답 시간을 반환합니다. 응답에errorCode가 추가됐습니다.- 웹훅 응답에
suspendedAt이 추가됐고,createdAt등 일시 필드가 ISO 8601 형식으로 통일됐습니다. PUT /webhooks/{webhookId}는 정지를 해제하면서 연속 실패 기록도 초기화합니다.DELETE /webhooks/{webhookId}는 전송 기록도 함께 삭제합니다.- 호환성 변경 등록·수정 때 구독 주소를 검사합니다. 내부 대역으로 해석되는 호스트나 사용자 정보(
user:pass@)가 들어간 주소는400 VALIDATION_FAILED로 거부됩니다. - Store SDK:
webhooks.resume·webhooks.redeliver·webhooks.redeliverFailed,listDeliveries의status·limit인자, 요청 본문 스키마webhookEventSchema, 서명 검증verifyWebhookSignature(@sayren/store-sdk/server)를 추가했습니다.
API 로그
- 상점으로 들어온 관리 API 요청을 7일간 기록하고 상점 플랫폼에서 조회할 수 있습니다. API 로그 참고.
앱 관리
- 추가:
GET /store/api-clients,GET /store/api-clients/{clientId},POST /store/api-clients/{clientId}/rotate-secret,POST /store/api-clients/{clientId}/deactivate - 비활성화한 앱이 발급한 토큰과, 그 토큰을 교환해 받은 storeToken은 즉시
401로 거부됩니다. - 호환성 변경 앱 토큰의 권한은 사용자 역할, 토큰 scope, 앱 등록 scope가 모두 허용하는 범위로 제한됩니다.
X-Store-Id직접 호출과 token-exchange에 모두 적용됩니다. - 호환성 변경 API 토큰 발급, 클라이언트 등록(DCR), 앱 관리는 상점 플랫폼에서 로그인한 OWNER·ADMIN만 할 수 있습니다.
- 웹훅 시크릿을 교체하면 기존 시크릿이 24시간 동안 함께 유효합니다. 유효한 시크릿은 최대 2개입니다.
2026-09-18
- 호환성 변경 상품 옵션을 옵션 축(
optionGroups) × 값 → 판매 단위(variants) 구조로 바꿨습니다. 재고는 판매 단위별로 관리하고, 상품의stockQuantity는 판매 가능한 판매 단위의 재고 합계입니다. GET·PUT /products/{productId}/options가 옵션 모델 전체를 다룹니다.PUT에서 판매 단위의stockQuantity를 생략하면 기존 재고를 유지합니다.- 재고 변경 경로가
PATCH /products/{productId}/variants/{variantId}/stock으로 바뀌었습니다. - 판매 단위에
sku·barcode·costPrice·weightGram이 추가됐습니다. - 장바구니·주문·클레임·리뷰의
optionId는 판매 단위의variantId와 같은 값입니다. ID 형식은 고정되어 있지 않으니 접두어로 판별하지 마십시오. - 스토어프론트 상품 상세가
options대신optionGroups·variants를 반환합니다.
2026-09-17
- 셀러 로그인이 외부 IdP로 일원화됐습니다.
GET /oauth2/authorize는 IdP 로그인 화면으로 이동하고, 인증이 끝나면 이전과 같이redirect_uri로 code를 돌려줍니다. 토큰 발급·교환 방식은 바뀌지 않았습니다.
2026-07-19
- 1:1 문의 API를 추가했습니다. 셀러용
/customer-inquiries, 구매자용/storefront/v1/me/customer-inquiries.
2026-07-16
- Store SDK·Storefront SDK: 로그인 세션 관리
createStoreSession·createStorefrontSession을 추가했습니다. 토큰 저장, refresh token 회전, 무음 갱신을 SDK가 처리합니다.
2026-07-14
userToken과X-Store-Id헤더로 token-exchange 없이 상점 리소스를 호출할 수 있습니다.- 카테고리에 표시 상태, PC·모바일 노출, 상품 진열, SEO 설정 필드가 추가됐습니다.
2026-07-11
- 클레임 승인과 셀러 직권취소가 결제 취소(환불)까지 처리합니다.
2026-07-10
- 카테고리 관리 API(
/categories, 트리·검색·생성·수정·이동·삭제)와category:r|rw스코프를 추가했습니다.
2026-07-09
- 호환성 변경 모든 응답이 표준 엔벨로프
{ meta, data, error }를 따릅니다. OAuth 엔드포인트는 예외입니다. - 호환성 변경 관리 API 인증을 OAuth 2.1로 바꿨습니다. authorization_code + PKCE, refresh token 회전,
client_credentials, token-exchange(
audience={storeId})를 지원합니다.passwordgrant는 제거했습니다. - API 토큰(
/store/api-tokens), 클라이언트 등록(POST /oauth2/register), 구매자 위임 토큰 발급을 추가했습니다. - 토큰 서명을 RS256으로 바꾸고
/.well-known/jwks.json,/.well-known/oauth-authorization-server를 제공합니다. - 호환성 변경 상점 생성·폐쇄·양도와 초대 수락을 관리 API에서 제거했습니다. 상점 플랫폼에서 처리합니다.