상품

상품 등록

이전 시스템의 상품이나 오프라인·제휴로 들어온 상품을 옮겨 담을 때 써요.

v1 API 상세: 상품

판매할 상품 정보를 등록해요. 가격, 이름, 구독 설정 등을 지정해요.

기존에 운영 중이던 상품 정보를 등록하는 API예요. 이전 시스템의 상품 데이터를 이전하거나, 오프라인/제휴 유입 상품을 등록할 때 사용해요.

API 엔드포인트

POSThttps://api.bootapi.com/v1/productsBasic Auth

필요 권한: user:product_create

요청 파라미터

파라미터 타입 필수 설명
name String 필수 상품명 (서버가 비어 있는지 검사하지 않으니 꼭 보내요)
desc String 선택 상품 요약 설명
content String 선택 상품 상세 설명 (HTML 지원)
images File[] 선택 대표 이미지 파일. 파일을 올릴 때는 multipart/form-data 를 사용해요
category_id String 선택 카테고리 ID
display_price Integer 필수 판매가 (표시가). 0보다 커야 해요 — 0원은 사용량 기반·수시결제 구독 상품만 돼요
tax_free_price Integer 선택 비과세 가격
use_stock Boolean 선택 재고 관리 사용 여부
stock Integer 선택 재고 수량
use_subscription Boolean 선택 구독 상품 여부
subscription_setting_id String 선택 구독 설정 템플릿 ID
usage_api_url String 선택 사용량 조회 URL. 종량제(사용량 기반) 구독 상품이면 필수이고, 비어 있으면 SUBSCRIPTION_SETTIGN_NEED_USAGE_API_URL 로 거절돼요. 구독 설정이 아니라 상품에 저장해요 (종량제 구독)
use_discount Boolean 선택 할인 사용 여부
discount_price Integer 선택 할인 금액 또는 할인율. 판매가에서 이만큼 빼요 (discount_price_type 참고)
discount_price_type Integer 선택 할인 단위 — 1 퍼센트 / 2 정액. 보내지 않으면 정액으로 계산해요
status_display Boolean 선택 쇼핑몰 노출 여부
status_sale Boolean 선택 판매 상태
ex_uid String 선택 외부 시스템 고유 ID (external_uid 로 보내도 돼요)
save_by Integer 선택 저장 방식 (1 시스템 임시저장 / 2 사용자 임시저장 / 3 발행). 구독·배송 설정 검증은 3 을 명시해야 동작​​해요. 생략하면 발행 상태로 저장되지만 이 검증을 건너뛰어요. 1·2 로 저장한 상품은 목록·상세·주문에 나오지 않아요
구독 상품은 save_by 를 함께 보내요

use_subscription: true 로 구독 상품을 만들 때는 save_by: 3 을 함께 보내야 구독 설정·가격 검증이 실행돼요. 생략하면 발행 상태로 저장되지만 해당 검증을 건너뛰므로 구독 상품 등록에 사용하지 마세요.

save_by 는 저장 방식이에요 — 1 시스템 임시저장 / 2 사용자 임시저장 / 3 발행. 배송·구독 설정 검증은 3 일 때만 동작해요.

발행 상태의 구독 상품은 관리자에서 만들어요

이 API 는 구독 기간별 가격(subscription_periods)을 받지 않아요. 옵션 없는 구독 상품을 save_by: 3 으로 발행하면 기간별 가격이 없어 PRODUCT_PRICE_INVALID(HTTP 409)로 거절돼요.

구독 상품은 관리자 > 상품 관리에서 만들고, 받은 product_id 를 체크아웃·구독에 써요.

코드 예제

const { BootpayCommerce } = require('@bootpay/backend-js')

const commerce = new BootpayCommerce({
    client_key: 'your-commerce-client-key',
    secret_key: 'your-commerce-secret-key',
    mode: 'production'
})

const response = await commerce.product.create({
    name: '드립백 커피 10개입',
    desc: '매일 아침 한 잔',
    display_price: 29900,
    save_by: 3,
    tax_type: 1,
    ex_uid: 'shop-coffee-10',
    status_visible: true,
    status_display: true,
    status_sale: true
})
console.log('product_id:', response.product_id)javascript

응답

성공 응답

{
  "product_id": "67c95e64d01640bb9859c629",
  "save_by": 3
}json
알려진 문제 — 등록은 되는데 응답이 500 으로 와요

지금은 상품이 저장된 뒤에 SERVER_ERROR(HTTP 500)가 돌아와요. 같은 요청을 다시 보내면 상품이 하나 더 만들어질 수 있어요.

등록할 때 ex_uid 를 함께 보내요. 500 을 받으면 재시도하기 전에 상품 목록에서 ex_uid 로 저장 여부와 product_id 를 확인해요. 중복 생성 방지 여부를 ex_uid 만으로 단정하지 마세요.

에러 응답

HTTP/1.1 409 Conflict
Content-Type: application/json
{
  "error_code": "PRODUCT_PRICE_INVALID",
  "message": "상품가격은 0원 이상이여야 합니다."
}json

에러 코드

공통 에러

인증·권한 관련 에러는 에러 코드표를 참고해요.

코드 메시지 대처 방법
PRODUCT_PRICE_INVALID 상품가격은 0원 이상이어야 해요. (HTTP 409) display_price 를 0보다 크게 넣어요. 0원은 사용량 기반·수시결제 구독 상품만 돼요
알려진 문제 — 판매가를 0 으로 보내거나 빼면 500 이에요

지금은 일반 상품의 display_price 가 0 이거나 없으면 PRODUCT_PRICE_INVALID 대신 SERVER_ERROR(HTTP 500)가 와요. display_price 는 항상 0보다 큰 값으로 보내요.

product_id는 주문서 요청 시 products[].product_id에 사용돼요.