마켓플레이스

하위 가맹점

리셀러 하위 가맹점(셀러)을 만들고 읽고 고칩니다. 만들 때 첫 프로젝트와 결제수단까지 한 번에 붙일 수 있습니다.

API 하는 일
1. 가맹점 생성 하위 가맹점 생성(셀러 + 기본 프로젝트 + 첫 결제수단)
2. 가맹점 목록 하위 가맹점 목록
3. 가맹점 조회 하위 가맹점 단건 조회
4. 가맹점 정보 수정 사업자 정보 수정(보낸 칸만)
5. 테스트 데이터 삭제 테스트용 가맹점·프로젝트·권한 일괄 삭제(개발 환경 전용)

인증·권한 오류는 각 표에 없어도 공통 오류 가 날 수 있습니다.

1가맹점 생성

리셀러 계정으로 하위 가맹점(셀러)을 만들고, 셀러의 기본 프로젝트와 첫 결제수단(PG·메서드) 까지 한 트랜잭션 안에서 같이 등록합니다.

동작 규칙

  • 셀러를 식별할 외부 키 primary_key 가 필수입니다. 본사 DB 의 회원 ID 와 묶어두면 동일 리셀러 안에서 중복도 자동으로 막힙니다.
  • 가맹점과 함께 프로젝트 하나를 만듭니다. project 로 이름·통화·상품 종류·시간대를 정하고, 안 보내면 기본프로젝트 · KRW · 비실물 · Asia/Seoul 로 만듭니다.
  • resources 배열을 함께 보내면 그 프로젝트에 PG·결제수단까지 한 번에 붙습니다. 비워두면 빈 프로젝트만 만들어집니다.
  • 응답으로 받은 apps[].application_keys 가 곧 셀러가 결제창(SDK) 에 쓸 키입니다. apps[].private_key 는 프로젝트 단위 백엔드 키입니다. 둘 다 안전한 자리에 저장합니다.
  • 한 트랜잭션이라 중간에 어디가 실패하면 셀러·프로젝트 둘 다 만들어지지 않습니다. 같은 키로 다시 호출하면 됩니다.

API 정보

POSThttps://api.bootpay.co.kr/v2/reseller/sellerBasic Auth (리셀러 계정 키)

1-1. 요청 파라미터

파라미터 타입 필수 설명
primary_key String 필수 본사가 관리하는 셀러 식별자. 동일 리셀러 안에서 유일해야 합니다
company_name String 필수 셀러 회사명(사업자 명의)
email String 필수 셀러 대표 이메일. 이 이메일로 부트페이 계정이 함께 생성됩니다. 이미 있는 계정이면 새로 만들지 않고 그 계정에 프로젝트 권한을 줍니다
owner_name String 선택 대표자명
manager_name String 선택 담당자명
regist_no String 선택 사업자등록번호. 하이픈은 무시됩니다
phone String 선택 담당자/대표 연락처. 하이픈은 무시됩니다
homepage String 선택 서비스 URL
zip String 선택 우편번호
address1 String 선택 기본 주소
address2 String 선택 상세 주소
send_email Boolean 선택 가입 안내 메일 발송 플래그. 기본 false. 현재 구현에서는 이 값을 true 로 보내도 메일이 실제로 발송되지 않습니다
project Object 선택 함께 만들 프로젝트. 형식은 아래 참고. 안 보내면 기본프로젝트·KRW·비실물·Asia/Seoul
resources Array 선택 첫 프로젝트에 함께 등록할 PG·결제수단 배열. 형식은 아래 참고

project 객체 형식

프로젝트 생성 과 같은 값·기본값을 사용합니다.

필드 타입 필수 설명
name String 선택 프로젝트명. 기본 기본프로젝트
unit String 선택 결제 통화 KRW·USD. 기본 KRW
real String 선택 상품 종류 비실물(digital)·실물(real)·실물&비실물(both). 기본 비실물
timezone String 선택 시간대(IANA 이름). 기본 Asia/Seoul
desc String 선택 프로젝트 설명

resources 배열 형식

각 원소는 PG · 결제수단 · 발급키를 한 묶음으로 가집니다.

필드 타입 필수 설명
pg String 필수 PG 심볼 (예: nicepay, kcp, inicis, tosspayments). 전체 목록은 PG 코드 참고
method String 필수 결제수단 심볼 (예: 카드, 계좌이체, 가상계좌, 카드자동).
sandbox Boolean 선택 true 면 테스트 모드(부트페이 테스트 키로 결제)로 설정합니다
resource Object 선택 PG 가 발급한 가맹점 키 묶음. 키 이름은 PG·메서드마다 다릅니다. 연동 값 없이 테스트 모드로만 쓰려면 생략하고 sandbox: true 를 보냅니다

resource 안에 들어가는 키 이름은 PG 사가 정한 그대로입니다. 나이스페이먼츠 카드라면 mid, mkey(카드자동은 cancel_pwd 까지) 같은 식이고, KCP 라면 site_cd, site_key 같은 식입니다. 가맹점 발급 통보서에 있는 값을 그대로 넣으면 됩니다. 꼭 넣어야 하는 키는 PG·필수 연동 값 목록 에서 required: true 인 키입니다(부트페이 관리자 화면과 같은 기준) — 하나라도 비면 RESOURCE_KEY_BLANK 로 가맹점도 만들어지지 않습니다.

1-2. 코드 예제

import fetch from 'node-fetch'

const RESELLER_AUTH = 'Basic ' + Buffer
  .from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
  .toString('base64')

const res = await fetch('https://api.bootpay.co.kr/v2/reseller/seller', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': RESELLER_AUTH
    },
    body: JSON.stringify({
        primary_key:  'host-member-1024',
        company_name: '한입가게',
        email:        'owner@hanip.shop',
        owner_name:   '김대표',
        manager_name: '박매니저',
        regist_no:    '1234567890',
        phone:        '01012345678',
        homepage:     'https://hanip.shop',
        zip:          '06236',
        address1:     '서울 강남구 테헤란로 123',
        address2:     '4층',
        send_email:   true,
        project:      { name: '한입가게', real: '실물' },   // 안 보내면 기본프로젝트·KRW·비실물·Asia/Seoul
        resources: [
            {
                pg:     'nicepay',
                method: '카드',
                resource: {
                    mid:          'nicepay00m',
                    mkey:         'EYzu8jGGMfqaDEp76gSckuvnaHHu+...='
                }
            }
        ]
    })
})
const data = await res.json()
// data.provider_id, data.apps[0].application_keys 저장
console.log(data)javascript

1-3. 응답

생성된 셀러 정보와 함께 첫 프로젝트가 apps[] 안에 같이 담겨 옵니다.

{
  "provider_id":              "65a1c0aa8f1b5b00367a0001",
  "company_alias":            null,
  "email":                    "owner@hanip.shop",
  "company_name":             "한입가게",
  "owner_name":               "김대표",
  "manager_name":             "박매니저",
  "mail_order_sales_number":  null,
  "information_manager_name": null,
  "biz_tel":                  null,
  "biz_email":                null,
  "phone":                    "01012345678",
  "homepage":                 "https://hanip.shop",
  "lv":                       1,
  "regist_no":                "1234567890",
  "zip":                      "06236",
  "address1":                 "서울 강남구 테헤란로 123",
  "address2":                 "4층",
  "apps": [
    {
      "app_id":      "65a1c0ab8f1b5b00367a0002",
      "app_name":    "한입가게",
      "real":        { "name": "실물", "value": 1, "desc": "" },
      "unit":        "KRW",
      "application_keys": [
        { "type": 1, "name": "WEB",     "key": "65a1c0ab8f1b5b00367a0003" },
        { "type": 2, "name": "Android", "key": "65a1c0ab8f1b5b00367a0004" },
        { "type": 3, "name": "iOS",     "key": "65a1c0ab8f1b5b00367a0005" },
        { "type": 4, "name": "REST",    "key": "65a1c0ab8f1b5b00367a0006" }
      ],
      "private_key": "kQ3f8vB2pN7sXq1wE5rT9yU0iO4aS6dF8gH2jK5lZ0c=",
      "payment_apps": [
        {
          "payment_resource_id": "65a1c0ab8f1b5b00367a0007",
          "pg_id":               "6098a1b2c3d4e5f600000101",
          "pg_name":             "나이스페이먼츠",
          "pg_alias":            "nicepay",
          "method_id":           "6098a1b2c3d4e5f600000201",
          "method_name":         "카드",
          "method_alias":        "card",
          "resource_mode":       null,
          "sandbox_mode":        false,
          "easypay":             false,
          "updated_at":          "2024-01-12T18:04:11+09:00",
          "status":              1,
          "resource": {
            "mid":          "nicepay00m",
            "mkey":         "EYzu8jGGMfqaDEp76gSckuvnaHHu+..."
          }
        }
      ],
      "status": 20,
      "commerce": {
        "status":     "created",
        "seller_id":  "65a1c0ab8f1b5b00367a0008",
        "project_id": "65a1c0ab8f1b5b00367a0009",
        "client_key": "example_commerce_client_key",
        "core_app_id": "65a1c0ab8f1b5b00367a0002",
        "key_chain": {
          "project_key_chain_id": "65a1c0ab8f1b5b00367a0020",
          "name":                 "reseller-default",
          "client_key":           "example_commerce_server_client_key",
          "secret_key":           "example_commerce_server_secret_key",
          "is_supervisor":        true,
          "expires_at":           "2099-12-31T23:59:59+09:00"
        }
      }
    }
  ]
}json

응답 파라미터

파라미터 타입 설명
provider_id String 생성된 셀러의 식별자. 이후 가맹점 조회·프로젝트 추가에 사용
email String 등록된 셀러 이메일
company_name String 셀러 회사명
lv Number 가맹점 레벨 (1 = 셀러)
apps Array 함께 생성된 프로젝트 배열
apps[].app_id String 프로젝트(=app) 식별자
apps[].app_name String 프로젝트명. project.name 이 없으면 기본프로젝트
apps[].real Object 거래 상품 유형. { name, value, desc } 구조입니다
apps[].unit String 결제 통화
apps[].application_keys Array 플랫폼별 SDK 연동키 묶음. WEB / Android / iOS / REST 4 건이 내려옵니다
apps[].application_keys[].type Number 플랫폼 코드. 1 = WEB, 2 = Android, 3 = iOS, 4 = REST
apps[].application_keys[].name String 플랫폼 이름 (WEB / Android / iOS / REST)
apps[].application_keys[].key String SDK 초기화에 넣는 application_id. Basic Auth 에 쓰는 client_key 와는 다른 값입니다
apps[].private_key String 프로젝트 단위의 백엔드 키. 32바이트 난수를 Base64 로 만든 값입니다
apps[].payment_apps Array resources 로 등록한 PG·결제수단 결과. 프로젝트를 만들 때 함께 붙는 부트페이 기본 결제수단도 나옵니다
apps[].payment_apps[].payment_resource_id String 등록된 결제수단 리소스 식별자
apps[].payment_apps[].pg_id / pg_name / pg_alias String 매칭된 PG 식별자·이름·심볼
apps[].payment_apps[].method_id / method_name / method_alias String 매칭된 결제수단 식별자·이름·심볼
apps[].payment_apps[].resource_mode String / null PG 연동 방식(일부 PG 만)
apps[].payment_apps[].sandbox_mode Boolean 테스트 모드 여부
apps[].payment_apps[].easypay Boolean 간편결제 여부
apps[].payment_apps[].updated_at String 리소스 갱신 시각 (ISO 8601)
apps[].payment_apps[].status Number 결제수단 상태
apps[].payment_apps[].resource Object 등록된 PG 발급키 묶음. 요청에 보낸 값이 그대로 다시 내려옵니다
apps[].status Number 프로젝트 상태. 기본값 20 (심사통과)
apps[].commerce Object 함께 만든 부트페이 커머스 프로젝트 정보
apps[].commerce.status String created 새로 생성, exists 기존 프로젝트 연결, failed 커머스 생성 실패 (error_code·message 포함)
apps[].commerce.project_id String 커머스 프로젝트 식별자
apps[].commerce.client_key String 커머스 공개키. 프론트 SDK 용이며 서버용 secret 은 키 생성·조회 에서 발급합니다
apps[].commerce.core_app_id String 커머스 프로젝트에 연결된 결제 프로젝트(app_id)
apps[].commerce.key_chain Object 리셀러 전용 커머스 서버 키(이름 reseller-default, 전체 권한·만료 없음). 커머스 프로젝트를 이 호출에서 처음 만든 경우(created)에만 오고, secret_key 원문은 이 응답에서만 보입니다. 모양은 키 생성·조회 의 발급 응답과 같습니다. 잃어버리면 키 재발급
apps[].commerce.key_error String 커머스 프로젝트는 만들었지만 서버 키 발급에 실패한 사유. 키 재발급 의 target: commerce 로 다시 받습니다
apps[].commerce.error_code String failed 일 때 원인 코드
키 저장

apps[].application_keys[].key 는 셀러가 자체적으로 결제창을 띄울 때 SDK 에 넣는 값입니다. 본사 DB 의 셀러 레코드에 묶어 안전하게 저장해두면 됩니다. 분실하면 프로젝트 조회 로 다시 확인하거나 콘솔에서 확인·재발급합니다.

커머스 생성 실패

commerce.status 가 failed 이면 커머스 쪽 생성만 실패한 것입니다. 결제(PG) 가맹점·프로젝트는 정상 생성돼 있으므로 같은 생성 API 를 다시 부르지 않습니다. PUT /v2/reseller/seller/app/commerce/:app_id 로 커머스만 다시 시도합니다. 자세한 내용은 커머스 연동 재시도 를 참고합니다.

응답 시간

커머스 프로젝트 생성까지 기다렸다가 응답하므로 10초 가까이 걸릴 수 있습니다. 호출 쪽 HTTP 타임아웃은 15초 이상으로 둡니다. 중간에 끊겼다면 같은 생성 API 를 다시 부르지 말고 커머스 연동 재시도 로 확인합니다(이미 만들어졌으면 exists).

응답 로깅 주의

apps[].payment_apps[].resource 에는 PG 가 발급한 가맹점 키가 평문으로 들어 있습니다. 이 응답을 그대로 로그·APM·에러 리포팅에 남기지 않습니다. 저장이 필요하면 resource 를 마스킹하거나 제거한 뒤 기록합니다.

1-4. 에러 코드

공통 에러

인증·권한 관련 에러는 에러 코드표를 참고합니다.

코드 메시지 대처 방법
API_ONLY_RESELLER 리셀러만 이용이 가능한 API입니다 리셀러 권한이 부여된 계정 키로 호출합니다
API_NOT_PERMIT_LV (10000) 허가된 API 권한이 아닙니다 (HTTP 401) 계정에 이 API 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
API_NOT_PERMIT (10001) 허가된 API 권한이 아닙니다 (HTTP 401) 계정에 이 API 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
PROVIDER_PK_BLANK primary_key 가 비어 있습니다 primary_key 를 본사 회원 ID 와 묶어 항상 보냅니다
PROVIDER_PK_EXIST 동일 primary_key 가 이미 존재합니다 본사 DB 에서 기존 셀러를 먼저 조회합니다. 신규일 때만 호출합니다
PROVIDER_NAME_INVALID 회사명이 비어 있습니다 company_name 을 채워서 보냅니다
PROVIDER_EMAIL_INVALID 이메일이 비어 있거나 형식이 맞지 않습니다 RFC 5322 형식의 이메일을 보냅니다
PG_RESOURCE_NOT_FOUND resources[].pg 심볼을 찾지 못했습니다 PG 코드 에서 PG 심볼을 확인합니다
METHOD_RESOURCE_NOT_FOUND resources[].method 심볼을 찾지 못했습니다 PG 가 지원하는 결제수단 심볼인지 확인합니다
RESOURCE_KEY_BLANK resources[].resource 에 필수 키(required: true)가 빠져 있습니다 (빠진 키 이름이 메시지에 나옵니다) PG·필수 연동 값 목록 에서 required: true 인 키를 채워서 보냅니다
PM_NOT_SUPPORT_SANDBOX_MODE (1101) sandbox: true 로 연동 값 없이 붙이려는 결제수단이 테스트 모드를 지원하지 않습니다 (어느 원소인지 메시지에 나옵니다) PG·필수 연동 값 목록 에서 sandbox_supported 를 확인하고, 지원하지 않으면 resource 와 함께 보냅니다
PARAMS_INVALID project 가 객체가 아닙니다 project 는 { "name": … } 처럼 객체로 보내거나 뺍니다
APP_UNIT_INVALID project.unit 이 KRW·USD 가 아닙니다 빼면 KRW
APP_REAL_GOOD_INVALID (221) project.real 이 정해진 값이 아닙니다 비실물·실물·실물&비실물 중 하나. 빼면 비실물
APP_TIMEZONE_INVALID (223) project.timezone 이 모르는 시간대입니다 Asia/Seoul 같은 IANA 이름. 빼면 Asia/Seoul
PROVIDER_CREATE_FAILED 셀러 생성이 트랜잭션 도중 실패했습니다 같은 요청을 다시 호출합니다. 반복되면 부트페이에 문의

2가맹점 목록

리셀러 본인의 하위에 속한 셀러를 최근 생성 순으로 나열합니다. 본사 콘솔의 가맹점 목록 화면을 그릴 때 사용합니다.

동작 규칙

  • 목록은 최근 생성 순입니다. 리셀러 본인은 목록에 포함되지 않습니다.
  • list 의 각 원소는 가맹점 조회 의 셀러 객체(프로젝트 목록 apps 포함)에 목록 전용 세 필드(pg_wait·commerce_status·monthly_amount)가 더해진 형태입니다.
  • pg_wait 는 가장 최근 PG 가맹 신청서의 진행 상태입니다. 신청서가 없으면 null. 자세한 내용은 등록 상태 조회 로 봅니다.
  • monthly_amount 는 이번 달 1일 0시부터 지금까지 결제 완료 금액에서 취소 금액을 뺀 값입니다. 하루 단위 통계로 모으므로 방금 난 결제는 늦게 반영될 수 있고, 통화를 나누지 않고 더합니다.
  • commerce_status 는 부트페이 커머스 쪽 판매자 계정이 있으면 exists, 없으면 none입니다. 커머스 쪽을 잠시 읽지 못하면 그 페이지 전부 failed 이고 목록은 그대로 옵니다.
  • count 는 페이지와 무관한 전체 하위 가맹점 수입니다.
  • apps 에는 프로젝트 기본 정보만 옵니다. 연동키와 커머스 정보는 프로젝트 조회 로 봅니다.

API 정보

GEThttps://api.bootpay.co.kr/v2/reseller/sellerBasic Auth (리셀러 계정 키)

2-1. 요청 파라미터

파라미터 타입 필수 설명
page Number 선택 페이지 번호 (쿼리). 기본 1
limit Number 선택 페이지당 건수 (쿼리). 기본 20, 최대 100

2-2. 코드 예제

import fetch from 'node-fetch'

const RESELLER_AUTH = 'Basic ' + Buffer
  .from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
  .toString('base64')

const res = await fetch('https://api.bootpay.co.kr/v2/reseller/seller?page=1&limit=20', {
    method: 'GET',
    headers: {
        'Authorization': RESELLER_AUTH
    }
})
const data = await res.json()
console.log(data.count, data.list)javascript

2-3. 응답

{
  "list": [
    {
      "provider_id":              "65a1c0aa8f1b5b00367a0001",
      "company_alias":            null,
      "email":                    "owner@hanip.shop",
      "company_name":             "한입가게",
      "owner_name":               "김대표",
      "manager_name":             "박매니저",
      "mail_order_sales_number":  null,
      "information_manager_name": null,
      "biz_tel":                  null,
      "biz_email":                null,
      "phone":                    "01012345678",
      "homepage":                 "https://hanip.shop",
      "lv":                       1,
      "regist_no":                "1234567890",
      "zip":                      "06236",
      "address1":                 "서울 강남구 테헤란로 123",
      "address2":                 "4층",
      "seller_name":              "한입가게",
      "pg_wait": {
        "status": 1,
        "stage":  "doc_wait",
        "due_at": "2026-10-30T18:00:00+09:00"
      },
      "commerce_status": "exists",
      "monthly_amount":  1250000,
      "apps": [
        {
          "app_id":      "65a1c0ab8f1b5b00367a0010",
          "provider_id": "65a1c0aa8f1b5b00367a0001",
          "app_name":    "기본프로젝트",
          "real":        { "name": "비실물", "value": 0, "desc": "" },
          "desc":        null,
          "unit":        "KRW",
          "status":      20
        }
      ]
    }
  ],
  "count": 37
}json

응답 파라미터

파라미터 타입 설명
list Array 하위 가맹점 배열. 원소 형식은 가맹점 조회 에 아래 세 필드가 더해집니다
list[].pg_wait Object / null 가장 최근 PG 가맹 신청서. 없으면 null
list[].pg_wait.status Number 신청서 상태 번호(등록 상태 조회 의 status 와 같습니다)
list[].pg_wait.stage String 진행 단계(intake·doc_wait·doc_review·pg_submit·pg_review·done·closed)
list[].pg_wait.due_at String / null 그 단계 처리 기한
list[].commerce_status String 커머스 판매자 계정 exists·none, 읽지 못했으면 failed
list[].monthly_amount Number 이번 달 결제 합계(완료 - 취소). 하루 단위 통계라 늦게 반영될 수 있고 통화를 나누지 않습니다
list[].apps Array 그 가맹점의 프로젝트 목록(최신순, 없으면 빈 배열). 원소는 프로젝트 목록 과 같습니다(app_id·provider_id·app_name·real·desc·unit·status)
count Number 전체 하위 가맹점 수

2-4. 에러 코드

코드 메시지 대처 방법
API_ONLY_RESELLER 리셀러만 이용이 가능한 API입니다 리셀러 권한 계정 키로 호출합니다
API_SCOPE_INVALID 허용되지 않은 API 권한의 키입니다 키에 이 API 의 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출합니다

3가맹점 조회

리셀러 본인의 하위에 속한 셀러를 provider_id 로 단건 조회합니다. 본사 콘솔에서 셀러 상세 화면을 그릴 때, 또는 가입 직후 캐시 동기화 용도로 사용합니다.

동작 규칙

  • 리셀러 본인의 하위에 묶이지 않은 provider_id 를 넣으면 PROVIDER_NOT_FOUND 가 떨어집니다. 다른 리셀러의 셀러를 들여다보는 건 막혀 있습니다.
  • 리셀러가 아닌 계정으로 부르면 API_ONLY_RESELLER, 본사가 사용을 멈춘 리셀러면 RESELLER_SUSPENDED 로 막힙니다(목록·생성·수정과 같습니다).
  • 응답은 가맹점 생성 의 셀러 필드와 동일한 형태에 seller_name 이 추가됩니다.
  • 그 셀러의 프로젝트 목록(apps)이 함께 옵니다. 형식은 프로젝트 목록 과 같고 최신순입니다. 연동 키·결제수단·커머스 연결은 프로젝트 조회 로 봅니다.

API 정보

GEThttps://api.bootpay.co.kr/v2/reseller/seller/:provider_idBasic Auth (리셀러 계정 키)

3-1. 요청 파라미터

파라미터 타입 필수 설명
provider_id String 필수 조회할 셀러의 provider_id (URL 경로)

3-2. 코드 예제

import fetch from 'node-fetch'

const RESELLER_AUTH = 'Basic ' + Buffer
  .from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
  .toString('base64')

const providerId = '65a1c0aa8f1b5b00367a0001'
const res = await fetch(`https://api.bootpay.co.kr/v2/reseller/seller/${providerId}`, {
    method: 'GET',
    headers: {
        'Authorization': RESELLER_AUTH
    }
})
const data = await res.json()
console.log(data)javascript

3-3. 응답

{
  "provider_id":              "65a1c0aa8f1b5b00367a0001",
  "company_alias":            null,
  "email":                    "owner@hanip.shop",
  "company_name":             "한입가게",
  "owner_name":               "김대표",
  "manager_name":             "박매니저",
  "mail_order_sales_number":  null,
  "information_manager_name": null,
  "biz_tel":                  null,
  "biz_email":                null,
  "phone":                    "01012345678",
  "homepage":                 "https://hanip.shop",
  "lv":                       1,
  "regist_no":                "1234567890",
  "zip":                      "06236",
  "address1":                 "서울 강남구 테헤란로 123",
  "address2":                 "4층",
  "seller_name":              "한입가게",
  "apps": [
    {
      "app_id":      "65a1c0ab8f1b5b00367a0010",
      "provider_id": "65a1c0aa8f1b5b00367a0001",
      "app_name":    "기본프로젝트",
      "real":        { "name": "비실물", "value": 0, "desc": "" },
      "desc":        null,
      "unit":        "KRW",
      "status":      20
    }
  ]
}json

응답 파라미터

파라미터 타입 설명
provider_id String 셀러 식별자
email String 셀러 대표 이메일
company_name String 회사명
owner_name String 대표자명
manager_name String 담당자명
phone String 연락처
homepage String 서비스 URL
lv Number 가맹점 레벨 (1 = 셀러, 2 = 리셀러)
regist_no String 사업자등록번호
zip / address1 / address2 String 주소
seller_name String 콘솔 표시용 셀러명
apps Array 이 셀러의 프로젝트 목록(최신순, 없으면 빈 배열). 원소는 프로젝트 목록 과 같습니다
apps[].app_id · apps[].app_name String 프로젝트 식별자 · 이름
apps[].real · apps[].unit · apps[].status Object · String · Number 상품 종류(name·value) · 통화 · 프로젝트 상태(20 심사통과)

3-4. 에러 코드

코드 메시지 대처 방법
API_ONLY_RESELLER 리셀러만 이용이 가능한 API입니다 리셀러 권한 계정 키로 호출합니다
RESELLER_SUSPENDED (343) 본사가 리셀러 사용을 멈췄습니다 (HTTP 403) 부트페이에 문의합니다
PROVIDER_NOT_FOUND 본인 하위에 해당 셀러가 없습니다 provider_id 가 본인 리셀러 소속인지 확인합니다

4가맹점 정보 수정

본인 하위 가맹점의 사업자 정보를 고칩니다. 보낸 키만 바뀌고 보내지 않은 키는 그대로입니다. 응답은 가맹점 조회 와 같은 셀러 객체이고, 프로젝트 목록 apps 만 없습니다.

동작 규칙

  • 바꿀 수 있는 키는 아래 표에 있는 것뿐입니다. 표에 없는 키(primary_key·lv 등)는 보내도 무시됩니다.
  • 아무 키도 보내지 않으면 PARAMS_INVALID 로 거부됩니다.
  • regist_no·phone 은 가맹점 생성 과 같이 - 를 빼고 저장합니다.
  • 값에 null 이나 빈 문자열을 보내면 그 값을 비웁니다. 단 company_name 은 비울 수 없고 email 은 이메일 형식이어야 합니다.
  • 상호·사업자등록번호가 바뀌면 변경 이력이 부트페이 관리자 화면에 남습니다.
  • 커머스 쪽 판매자 정보는 이 호출로 바뀌지 않습니다.
  • 본인 하위가 아니거나 리셀러 자신이면 PROVIDER_NOT_FOUND입니다.

API 정보

PUThttps://api.bootpay.co.kr/v2/reseller/seller/:provider_idBasic Auth (리셀러 계정 키)

PATCH 로 불러도 같습니다.

4-1. 요청 파라미터

파라미터 타입 필수 설명
provider_id String 필수 고칠 하위 가맹점의 provider_id (URL 경로)
company_name String 선택 상호. 빈 값 불가
email String 선택 대표 이메일. 이메일 형식이어야 합니다
regist_no String 선택 사업자등록번호. - 는 빼고 저장합니다
owner_name String 선택 대표자 이름
manager_name String 선택 담당자 이름
phone String 선택 연락처. - 는 빼고 저장합니다
homepage String 선택 홈페이지 주소
zip String 선택 우편번호
address1 String 선택 주소
address2 String 선택 상세 주소
mail_order_sales_number String 선택 통신판매업 신고번호
information_manager_name String 선택 개인정보 관리 책임자
biz_tel String 선택 대표 전화
biz_email String 선택 대표 메일

4-2. 코드 예제

import fetch from 'node-fetch'

const RESELLER_AUTH = 'Basic ' + Buffer
  .from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
  .toString('base64')

const providerId = '65a1c0aa8f1b5b00367a0001'

const res = await fetch(`https://api.bootpay.co.kr/v2/reseller/seller/${providerId}`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json', 'Authorization': RESELLER_AUTH },
    body: JSON.stringify({ company_name: '한입가게 본점', phone: '010-1234-5678', address2: '5층' })
})
console.log(await res.json())javascript

4-3. 응답

{
  "provider_id":              "65a1c0aa8f1b5b00367a0001",
  "company_alias":            null,
  "email":                    "owner@hanip.shop",
  "company_name":             "한입가게 본점",
  "owner_name":               "김대표",
  "manager_name":             "박매니저",
  "mail_order_sales_number":  null,
  "information_manager_name": null,
  "biz_tel":                  null,
  "biz_email":                null,
  "phone":                    "01012345678",
  "homepage":                 "https://hanip.shop",
  "lv":                       1,
  "regist_no":                "1234567890",
  "zip":                      "06236",
  "address1":                 "서울 강남구 테헤란로 123",
  "address2":                 "5층",
  "seller_name":              "한입가게"
}json

응답 필드는 가맹점 조회 와 같습니다.

4-4. 에러 코드

코드 메시지 대처 방법
API_ONLY_RESELLER (601) 리셀러만 이용이 가능한 API입니다 리셀러 권한 계정 키로 호출합니다
API_SCOPE_INVALID 허용되지 않은 API 권한의 키입니다 (HTTP 401) 키에 이 API 의 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출합니다
API_NOT_PERMIT_LV (10000) 허가된 API 권한이 아닙니다 (HTTP 401) 계정에 이 API 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
API_NOT_PERMIT (10001) 허가된 API 권한이 아닙니다 (HTTP 401) 계정에 이 API 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
PROVIDER_NOT_FOUND (300) 본인 하위 가맹점이 아닙니다 (HTTP 404) provider_id 가 본인 리셀러 하위인지 확인합니다
PARAMS_INVALID (-33) 바꿀 값이 없거나 값이 문자열이 아닙니다 위 표의 키를 하나 이상, 문자열로 보냅니다
PROVIDER_NAME_INVALID (322) 상호가 비었습니다 company_name 을 채워 보냅니다
PROVIDER_EMAIL_INVALID (321) 이메일 형식이 아닙니다 email 을 올바른 형식으로 보냅니다

5테스트 데이터 삭제

리셀러 본인 하위에 만들어둔 테스트 셀러 한 곳을 삭제합니다. 셀러 자신, 셀러의 모든 프로젝트(app), 프로젝트에 발급된 SDK 연동키(AppKey), 프로젝트 멤버 권한(AppRole), 셀러 단위 멤버 권한(ProviderRole) 이 정리됩니다.

테스트 전용

이 엔드포인트는 통합 테스트·CI 에서 만들어둔 데이터를 정리하기 위한 용도입니다. 운영 주소(api.bootpay.co.kr)에서는 막혀 있어 아무것도 지우지 않고 404 를 돌려줍니다. 개발 환경 주소·키는 부트페이에 요청합니다. 삭제된 셀러·프로젝트는 복구할 수 없습니다.

삭제되지 않는 것

결제 내역(Receipt)·정산 데이터·회원(Member) 은 이 API 로 삭제되지 않고 그대로 남습니다. 삭제 대상은 아래 삭제 범위 표에 정리된 항목뿐입니다. 결제 내역이 있는 셀러를 삭제하면 소유자가 사라진 결제 데이터가 남게 되므로, 실제 결제가 발생한 셀러에는 호출하지 않습니다.

동작 규칙

  • 리셀러 본인의 하위가 아닌 셀러는 삭제되지 않습니다. provider_id 가 다른 리셀러 소속이면 PROVIDER_NOT_FOUND 가 떨어집니다.
  • 본인(리셀러 자기 자신) 의 provider_id 를 넣어도 거부됩니다. 리셀러 자체는 이 API 로 삭제할 수 없습니다.
  • 한 번에 한 셀러만 삭제됩니다. 대량 정리는 반복 호출이 필요합니다.

API 정보

DELETEhttps://{개발 환경 주소}/v2/reseller/test/seller/:provider_idBasic Auth (리셀러 계정 키)

5-1. 요청 파라미터

파라미터 타입 필수 설명
provider_id String 필수 삭제할 테스트 셀러의 provider_id (URL 경로)

5-2. 코드 예제

import fetch from 'node-fetch'

const RESELLER_AUTH = 'Basic ' + Buffer
  .from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
  .toString('base64')

const providerId = '65a1c0aa8f1b5b00367a0001'

const BASE_URL = process.env.BOOTPAY_TEST_API_URL // 개발 환경 주소(운영 api.bootpay.co.kr 는 404)
const res = await fetch(`${BASE_URL}/v2/reseller/test/seller/${providerId}`, {
    method: 'DELETE',
    headers: { 'Authorization': RESELLER_AUTH }
})
console.log(res.status) // 200javascript

5-3. 삭제 범위

한 번의 호출로 아래가 정리됩니다.

대상 설명
셀러(provider) 셀러 자체 레코드
프로젝트(app) 셀러가 소유한 모든 프로젝트
AppKey 프로젝트에 발급된 SDK 용 application_id 만 삭제됩니다. Basic Auth 에 쓰는 client_key / secret_key (AppKeyChain) 는 그대로 남습니다
ProviderRole 셀러에 묶인 모든 팀 멤버 권한
AppRole 삭제되는 프로젝트들에 묶인 프로젝트 멤버 권한
커머스 데이터는 남습니다

하위 셀러를 만들 때 함께 만들어진 커머스(쇼핑몰) 쪽 Seller·Project 는 이 API 로 지워지지 않고 남습니다.

결제·정산 데이터

이 API 는 셀러와 프로젝트 레코드를 삭제하지만, 결제 내역·정산 데이터·회원 계정은 남깁니다. 실제 결제 내역이 있는 운영 셀러에는 호출하면 안 됩니다. 테스트 환경에서만 사용합니다.

5-4. 응답

성공 시 본문은 비어 있고, HTTP 200 으로 떨어집니다.

5-5. 에러 코드

코드 메시지 대처 방법
API_ONLY_RESELLER 리셀러만 이용이 가능한 API입니다 리셀러 권한 계정 키로 호출합니다
API_SCOPE_INVALID (1222) 범위 키로는 부를 수 없습니다 (HTTP 401) 전체 권한(supervisor) 키로 호출합니다
PROVIDER_NOT_FOUND 셀러가 본인 하위에 없거나 본인 자신입니다 provider_id 가 본인 하위 셀러인지 확인합니다. 리셀러 자기 자신은 삭제 불가
NOT_FOUND (HTTP 404) 테스트 셀러 삭제는 운영 환경에서 쓸 수 없습니다 개발 환경 주소로 호출합니다

5-6. CI 에서 쓰는 패턴

테스트 흐름은 보통 셋업·검증·정리 세 단계로 묶입니다.

// 1) 셋업 — 테스트용 셀러 생성
const seller = await createTestSeller({
    primary_key: `ci-${process.env.GITHUB_RUN_ID}-${Date.now()}`,
    company_name: 'CI Sandbox',
    email: `ci+${Date.now()}@example.com`
})

try {
    // 2) 검증 — 결제 흐름 테스트
    await runPaymentFlow(seller.apps[0].application_keys[0].key)
} finally {
    // 3) 정리 — 어떤 결과든 셀러 일괄 삭제
    await fetch(`${process.env.BOOTPAY_TEST_API_URL}/v2/reseller/test/seller/${seller.provider_id}`, {
        method: 'DELETE',
        headers: { 'Authorization': RESELLER_AUTH }
    })
}javascript

primary_key 에 CI 빌드 식별자를 박아두면 누구의 어떤 실행에서 만든 셀러인지 추적이 쉽습니다. 정리에서 누락된 잔여 셀러가 있어도 primary_key 패턴으로 찾아 일괄 처리할 수 있습니다.

함께 보기