상품 전체 수정
accessTokenAuthorizationBearer <token>Sayren 계정 토큰(로그인 토큰 또는 개인 액세스 토큰, RFC 9068 JWT)
productId*stringX-Store-Id*string대상 상점 id. 토큰의 상점 범위 밖이면 403 STORE_NOT_GRANTED, 없으면 400 STORE_ID_REQUIRED다
application/json- body
name*string1 <= length <= 100categoryId*string1 <= lengthsalePrice*integer판매가. 원(KRW) 단위 정수, 최소 10원, 10원 단위
1010 <= valueoriginalPrice?integer정가(할인 전 표시 가격). 원 단위. 비교용 표시 값이고 결제 금액은 판매가(즉시할인이 있으면 할인 적용가)다. 스토어프론트가 판매가보다 클 때 취소선·할인율로 보인다. 즉시할인은 PUT /v1/products/{productId}/discount로 따로 정한다
pointEarnRateBp?|구매 적립률 덮어쓰기(만분율, 100 = 1%, 0~3000, 이슈 #93). null이면 상점 기본 적립률, 0이면 이 상품은 적립하지 않는다. 결제 확정 시점 값이 주문상품에 남는다. 전체 수정(PUT)에서 생략하면 지금 값을 유지한다
0 <= value <= 3000description?stringdescriptionJson?string|nullimages?array<>상품 이미지 주소 목록. 첫 장이 대표 이미지(썸네일)다
1 <= items <= 10attributes?array<>refundPolicy?|상품별 환불 정책 — 준 항목만 상점 기본을 덮어쓴다. null이나 생략은 상점 기본을 그대로 쓴다는 뜻이다. 반품·교환 배송비(returnDeliveryFee·exchangeDeliveryFee)는 배송 상품에만 줄 수 있다(다른 유형은 400)
optionGroups?array<>items <= 3[]variants*array<>1 <= items <= 500addonGroups?array<>추가 선택 옵션명 전체(이슈 #59). 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 끄려면 빈 배열을 보낸다. 기능이 열리기 전에는 비어 있지 않은 값이 409 OPTION_ADDONS_UNAVAILABLE이다
items <= 5customInputs?array<>직접 입력 항목 전체(이슈 #59). 배열 순서가 표시 순서다. 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 항목명에 개인정보성 단어(CUSTOM_INPUT_FORBIDDEN_WORDS)가 있으면 400 CUSTOM_INPUT_LABEL_FORBIDDEN, 기능이 열리기 전에는 비어 있지 않은 값이 409 OPTION_ADDONS_UNAVAILABLE이다
items <= 5optionSort?string옵션 값 정렬 순서(이슈 #59). 서버가 이 순서로 값의 sortOrder를 다시 매긴다. 생략하면 등록은 REGISTERED, 수정은 현재 값이다
"REGISTERED""NAME""PRICE_ASC""PRICE_DESC"sourceOptionSetIds?array<string>쓰기 전용(이슈 #59) — 이 저장으로 옵션을 불러온 저장 옵션 id. 상품 저장과 같은 트랜잭션에서 불러오기 기록을 남겨 저장 옵션의 importedProductCount를 센다. 없는 id는 무시한다
items <= 10inventoryMode?string재고 방식(이슈 #118). DATED면 날짜별 달력(PUT /products/{id}/calendar)이 재고·가격이고 주문서 줄은 숙박 기간(stay)을 받는다. 생략하면 등록은 STANDARD, 수정은 지금 값. 판매 이력이 있으면 바꿀 수 없다(409 INVENTORY_MODE_LOCKED)
"STANDARD""DATED"flowId?|주문 흐름(이슈 #115) — 게시한 흐름 id. null이면 카테고리의 흐름(없으면 기본 흐름)을 쓴다. 생략하면 등록은 null, 수정은 지금 값. 게시하지 않은 흐름은 409 FLOW_NOT_PUBLISHED. 이미 결제된 주문은 결제 때 붙은 흐름을 그대로 따른다
fulfillment?|상품 이행. 생략하면 바꾸지 않는다. 주면 유형 안 필드를 모두 담아 통째로 바꾼다(현재 값과 병합하지 않는다). 판매 이력이 있으면 유형을 바꿀 수 없다(409 FULFILLMENT_TYPE_LOCKED)
성공
application/json- response
meta*data*error*|nullcurl -X PUT 'https://api.sayren.io/v1/products/string' \ -H 'X-Store-Id: string' \ -H 'Content-Type: application/json' \ -d '{ "name": "string", "categoryId": "string", "salePrice": 10, "variants": [ {} ]}'{ "meta": { "status": 200, "code": "OK", "message": "OK", "isSuccess": true }, "data": { "productId": "string", "productNo": null, "name": "string", "status": "SALE", "salePrice": 0, "discountedPrice": 0, "stockQuantity": 0, "categoryId": "string", "thumbnailUrl": "http://example.com", "hasOptions": true, "fulfillment": { "type": "SHIPPING", "shipping": { "deliveryType": "FREE", "deliveryFee": 0, "conditionalFreeAmount": 0, "shippingAddressId": "string", "returnAddressId": "string" }, "methods": [ "string" ] }, "updatedAt": "string", "sample": false, "description": "string", "descriptionJson": "string", "originalPrice": 0, "pointEarnRateBp": 0, "images": [ "http://example.com" ], "attributes": [ { "attributeId": "string", "value": "string" } ], "optionGroups": [ { "groupId": "string", "name": "string", "sortOrder": 0, "values": [ { "valueId": "string", "name": "string", "sortOrder": 0 } ] } ], "variants": [ { "variantId": "string", "variantNo": null, "valueIds": [ "string" ], "name": "string", "additionalPrice": 0, "stockQuantity": 0, "sku": "string", "barcode": "string", "costPrice": 0, "weightGram": 0, "sellerCode": "string", "usable": true, "attributes": { "property1": "string", "property2": "string" }, "hasOrders": true } ], "addonGroups": [], "customInputs": [], "optionSort": "REGISTERED", "inventoryMode": "string", "flowId": "string", "fulfillmentTypeLocked": true, "refundPolicy": { "preShipmentDeliveryFeeRefund": true, "returnDeliveryFee": 0, "exchangeDeliveryFee": 0, "sellerFaultFreeShipping": true, "conditionalFreeShortfallCharge": true }, "discount": { "productId": "string", "discountType": "RATE", "discountValue": 0, "discountedPrice": 0, "startAt": "string", "endAt": "string" }, "createdAt": "string" }, "error": null}