하위 프로젝트의 결제(PG)·커머스 서버 키를 조회·발급·폐기·재발급합니다. 리셀러 API 를 부르는 키의 권한을 좁히는 방법도 여기에 있습니다.
인증·권한 오류는 각 표에 없어도 공통 오류 가 날 수 있습니다.
1 키 생성·조회
프로젝트의 서버 연동 키(Client Key / Secret Key)를 조회하고 새로 발급합니다. 결제(PG) 키와 커머스 키를 target 으로 구분합니다.
동작 규칙
조회는 GET, 발급은 POST, 폐기는 DELETE입니다. 모두 app_id 로 프로젝트를 지정합니다.
target: pg 키는 셀러 프로젝트로 결제 REST API(Basic Auth)를 호출할 때 사용합니다. target: commerce 키는 커머스 API 를 호출할 때 사용합니다.
목록의 secret_key 는 앞 5자 + ***** 로 마스킹됩니다. secret_key 가 평문으로 나오는 응답은 발급 응답뿐입니다.
발급 응답은 다시 볼 수 없습니다. 받은 즉시 셀러 레코드에 안전하게 저장합니다.
target: commerce 는 커머스 프로젝트가 있어야 합니다. 없으면 먼저 커머스 연동 재시도 를 부릅니다.
커머스 키 이름 reseller-default 는 리셀러 전용 키 자리라 이 API 로 만들 수도, 폐기할 수도 없습니다. 그 키를 새로 받으려면 키 재발급 을 사용합니다.
api_scopes 에 넣을 scope id 는 키 발급 스코프 목록 에서 받습니다.
폐기는 새 키 없이 그 키만 막습니다(연동을 끝내거나 남는 키를 정리할 때). 응답을 받는 순간부터 그 키로 하는 호출은 실패합니다(결제 키는 APP_CLIENT_KEY_REVOKED, HTTP 401). 키 문서는 지우지 않고 폐기 시각을 남기며, 이미 폐기한 키를 다시 폐기하면 처음 폐기 시각을 그대로 돌려줍니다.
조회 목록에는 지금 쓸 수 있는 키만 옵니다. 폐기했거나 만료한 키는 나오지 않습니다.
API 정보 GET https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/:app_idBasic Auth (리셀러 계정 키)
POST https://api.bootpay.co.kr/v2/reseller/seller/app/key-chainBasic Auth (리셀러 계정 키)
DELETE https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/:key_chain_id?app_id=:app_id&target=pgBasic Auth (리셀러 계정 키)
1-1. 요청 파라미터 조회 (GET /v2/reseller/seller/app/key-chain/:app_id)
파라미터
타입
필수
설명
app_id
String
필수
키를 조회할 프로젝트의 app_id (URL 경로)
발급 (POST /v2/reseller/seller/app/key-chain)
파라미터
타입
필수
설명
app_id
String
필수
키를 발급할 프로젝트의 app_id
target
String
필수
발급 대상. pg 또는 commerce
name
String
필수
키 이름
is_supervisor
Boolean
선택
true 이면 모든 API 를 허용합니다. 기본 false
api_scopes
Array
선택
허용할 API scope id 목록. is_supervisor 가 false 일 때 사용합니다. id 는 키 발급 스코프 목록 에서 받습니다
expires_at
String
선택
만료일 (ISO8601). 그날 23:59:59 까지 쓸 수 있습니다. 없으면 2099-12-31T23:59:59+09:00 으로 저장합니다
폐기 (DELETE /v2/reseller/seller/app/key-chain/:key_chain_id)
파라미터
타입
필수
설명
key_chain_id
String
필수
막을 키의 id (URL 경로) — 조회 응답의 app_key_chain_id(pg) 또는 project_key_chain_id(commerce)
app_id
String
필수
그 키가 속한 프로젝트의 app_id (쿼리)
target
String
필수
pg 또는 commerce (쿼리)
RESELLER_AUTH = $( printf '%s' " $BOOTPAY_RESELLER_CLIENT_KEY : $BOOTPAY_RESELLER_SECRET_KEY " | base64 )
curl -X DELETE "https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/65a1c0ab8f1b5b00367a0030?app_id=65a1c0ab8f1b5b00367a0002&target=commerce" \
-H "Authorization: Basic $RESELLER_AUTH " bash 폐기 응답:
{
"app_id" : "65a1c0ab8f1b5b00367a0002" ,
"target" : "commerce" ,
"revoked" : {
"key_id" : "65a1c0ab8f1b5b00367a0030" ,
"name" : "주문 서버" ,
"revoked_at" : "2026-10-27T15:00:00+09:00"
}
} json 1-2. 코드 예제 Node.js Python cURL
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 appId = '65a1c0ab8f1b5b00367a0002'
// 조회
const list = await fetch ( `https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/${ appId }` , {
method: 'GET' ,
headers: { 'Authorization' : RESELLER_AUTH }
})
console. log ( await list. json ())
// 발급
const res = await fetch ( 'https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : RESELLER_AUTH
},
body: JSON . stringify ({
app_id: appId,
target: 'pg' ,
name: '주문 서버' ,
is_supervisor: false ,
api_scopes: [ 'example_scope_id' ],
expires_at: '2027-10-20T00:00:00+09:00'
})
})
const data = await res. json ()
// data.secret_key 는 이 응답에서만 평문이다. 즉시 저장한다
console. log (data) javascript Node.js Python cURL
import base64, os, requests
auth = 'Basic ' + base64.b64encode(
f " { os.environ[ 'BOOTPAY_RESELLER_CLIENT_KEY' ] } : { os.environ[ 'BOOTPAY_RESELLER_SECRET_KEY' ] } " .encode()
).decode()
app_id = '65a1c0ab8f1b5b00367a0002'
# 조회
res = requests.get(
f 'https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/ { app_id } ' ,
headers = { 'Authorization' : auth}
)
print (res.json())
# 발급
res = requests.post(
'https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain' ,
json = {
'app_id' : app_id,
'target' : 'pg' ,
'name' : '주문 서버' ,
'is_supervisor' : False ,
'api_scopes' : [ 'example_scope_id' ],
'expires_at' : '2027-10-20T00:00:00+09:00'
},
headers = { 'Authorization' : auth}
)
# secret_key 는 이 응답에서만 평문이다. 즉시 저장한다
print (res.json()) python Node.js Python cURL
RESELLER_AUTH = $( printf '%s' " $BOOTPAY_RESELLER_CLIENT_KEY : $BOOTPAY_RESELLER_SECRET_KEY " | base64 )
APP_ID = '65a1c0ab8f1b5b00367a0002'
# 조회
curl -X GET "https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain/ $APP_ID " \
-H "Authorization: Basic $RESELLER_AUTH "
# 발급
curl -X POST 'https://api.bootpay.co.kr/v2/reseller/seller/app/key-chain' \
-H "Authorization: Basic $RESELLER_AUTH " \
-H 'Content-Type: application/json' \
-d '{
"app_id": "65a1c0ab8f1b5b00367a0002",
"target": "pg",
"name": "주문 서버",
"is_supervisor": false,
"api_scopes": ["example_scope_id"],
"expires_at": "2027-10-20T00:00:00+09:00"
}' bash
1-3. 응답 조회 응답 secret_key 는 마스킹되어 옵니다. 커머스 프로젝트가 없으면 commerce 는 null 입니다. 커머스 쪽 키를 읽지 못하면 commerce_error 가 함께 옵니다.
{
"pg" : [
{
"app_key_chain_id" : "65a1c0ab8f1b5b00367a0020" ,
"name" : "서버 연동용" ,
"client_key" : "65a1c0ab8f1b5b00367a0021" ,
"secret_key" : "Ab3dE*****" ,
"is_supervisor" : true ,
"expires_at" : "2099-12-31T23:59:59+09:00" ,
"api_scopes" : [],
"created_at" : "2026-10-20T10:00:00+09:00" ,
"server_at" : "2026-10-20T10:00:00+09:00" ,
"is_copiable" : false ,
"status" : 1
}
],
"commerce" : [
{
"project_key_chain_id" : "65a1c0ab8f1b5b00367a0030" ,
"name" : "서버 연동용" ,
"client_key" : "65a1c0ab8f1b5b00367a0031" ,
"secret_key" : "Ab3dE*****" ,
"is_supervisor" : true ,
"expires_at" : "2099-12-31T23:59:59+09:00" ,
"api_scopes" : [],
"created_at" : "2026-10-20T10:00:00+09:00" ,
"server_at" : "2026-10-20T10:00:00+09:00" ,
"is_copiable" : false ,
"status" : 1
}
]
} json 발급 응답 발급된 키체인 하나가 옵니다. secret_key 가 평문입니다.
{
"app_key_chain_id" : "65a1c0ab8f1b5b00367a0020" ,
"name" : "주문 서버" ,
"client_key" : "65a1c0ab8f1b5b00367a0021" ,
"secret_key" : "example_secret_key_plaintext" ,
"is_supervisor" : false ,
"expires_at" : "2027-10-20T23:59:59+09:00" ,
"api_scopes" : [ "example_scope_id" ],
"created_at" : "2026-10-20T10:00:00+09:00" ,
"server_at" : "2026-10-20T10:00:00+09:00" ,
"is_copiable" : true ,
"status" : 1
} json 응답 파라미터
파라미터
타입
설명
pg
Array
결제(PG) 키체인 배열
commerce
Array / null
커머스 키체인 배열. 커머스 프로젝트가 없으면 null
commerce_error
Object
(조회에서 커머스 키를 읽지 못했을 때만) status(none·failed)·error_code·message
app_key_chain_id
String
PG 키체인 식별자
project_key_chain_id
String
커머스 키체인 식별자 (커머스 항목에만 있습니다)
name
String
키 이름
client_key
String
Client Key
secret_key
String
Secret Key. 조회에서는 앞 5자 + *****, 발급 응답에서만 평문
is_supervisor
Boolean
전체 권한 키 여부
expires_at
String
만료 시각. 발급 때 정하지 않았으면 2099-12-31T23:59:59+09:00
api_scopes
Array
허용된 API scope id 목록
created_at
String
생성 시각
server_at
String
서버 기록 시각
is_copiable
Boolean
secret_key 를 그대로 복사할 수 있는지. 발급 응답에서만 true
status
Number
키 상태
revoked
Object
(폐기 응답) 막은 키 key_id·name·revoked_at
1-4. 에러 코드
코드
메시지
대처 방법
API_ONLY_RESELLER
리셀러만 이용이 가능한 API입니다
리셀러 권한 계정 키로 호출합니다
API_SCOPE_INVALID
허용되지 않은 API 권한의 키입니다
키에 이 API 의 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출합니다
APP_NOT_FOUND
프로젝트를 찾지 못했습니다
app_id 가 올바른지 확인합니다
APP_NOT_PERMIT
본인 하위 프로젝트가 아닙니다
app_id 가 본인 리셀러 하위 셀러의 프로젝트인지 확인합니다
PARAMS_INVALID
요청 파라미터가 올바르지 않습니다
target 을 pg 또는 commerce 로 보냅니다. 커머스 키 이름 reseller-default 는 쓸 수 없습니다
APP_API_SCOPE_NOT_MATCHED
허용되지 않은 API scope입니다
api_scopes 에 존재하는 scope id 만 보냅니다
APP_API_SCOPE_EXPIRES_INVALID (1220)
(결제 키 발급) expires_at 형식이 틀렸습니다 (HTTP 400)
ISO8601 형식으로 보냅니다
COMMERCE_KEY_CHAIN_FAILED (8140)
커머스 연동 키를 발급하지 못했습니다
message 와 payload.commerce_error_code(커머스 쪽 원인)를 확인합니다. 커머스 프로젝트가 없으면 커머스 연동 재시도 를 먼저 부릅니다
APP_KEY_CHAIN_NOT_FOUND (1214)
(폐기) 그 프로젝트의 키가 아니거나 없는 키입니다 (HTTP 404)
조회 응답의 키 id 와 app_id·target 이 맞는지 확인합니다. 커머스면 payload.commerce_error_code 도 봅니다
RESELLER_KEY_CHAIN_RESERVED (8180)
(폐기) 리셀러 전용 키 reseller-default 는 폐기할 수 없습니다
그 키를 바꾸려면 키 재발급 의 target: commerce 를 사용합니다
COMMERCE_REQUEST_FAILED (8182)
(폐기) 커머스 연동 서버에 요청하지 못했습니다
잠시 뒤 다시 부릅니다. 키는 막히지 않았을 수 있으니 조회로 확인합니다
API_NOT_PERMIT_LV (10000) · API_NOT_PERMIT (10001)
(발급·폐기) 허가된 API 권한이 아닙니다 (HTTP 401)
계정에 이 API 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
2 키 재발급
하위 프로젝트의 키를 새로 만들고 기존 키는 그 자리에서 막습니다 . 결제(PG) 쪽은 프로젝트 Private Key 를, 커머스 쪽은 생성 응답에서 받은 리셀러 전용 커머스 서버 키(reseller-default)를 바꿉니다.
동작 규칙
유예 시간이 없습니다. 응답을 받는 순간 기존 키로 하는 호출은 실패합니다. 새 키를 서버 설정에 먼저 넣을 준비를 하고 부릅니다.
새 비밀키 원문은 이 응답에서만 나옵니다. 받은 즉시 안전하게 저장합니다.
target: pg — 프로젝트의 private_key 를 바꿉니다. 같은 프로젝트를 쓰는 모든 서버가 영향을 받습니다. 이미 받아 둔 액세스 토큰은 만료(최대 30분)까지 그대로 쓸 수 있습니다.
target: commerce — 리셀러 전용 커머스 서버 키(reseller-default)를 새로 만들고 기존 것을 막습니다. 기존 키가 없었으면 새로 만들기만 하고 revoked 는 null 입니다. 키 생성·조회 로 따로 만든 키는 건드리지 않습니다.
API 정보 POST https://api.bootpay.co.kr/v2/reseller/seller/app/keys/reissueBasic Auth (리셀러 계정 키)
2-1. 요청 파라미터
파라미터
타입
필수
설명
app_id
String
필수
키를 바꿀 하위 프로젝트의 app_id
target
String
필수
pg 또는 commerce
2-2. 코드 예제 Node.js Python cURL
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/app/keys/reissue' , {
method: 'POST' ,
headers: { 'Authorization' : RESELLER_AUTH , 'Content-Type' : 'application/json' },
body: JSON . stringify ({ app_id: '65a1c0ab8f1b5b00367a0002' , target: 'commerce' })
})
const { keys , revoked } = await res. json ()
// keys.secret_key 를 바로 저장한다 — 다시 볼 수 없다 javascript Node.js Python cURL
import base64, os, requests
auth = 'Basic ' + base64.b64encode(
f " { os.environ[ 'BOOTPAY_RESELLER_CLIENT_KEY' ] } : { os.environ[ 'BOOTPAY_RESELLER_SECRET_KEY' ] } " .encode()
).decode()
res = requests.post(
'https://api.bootpay.co.kr/v2/reseller/seller/app/keys/reissue' ,
headers = { 'Authorization' : auth},
json = { 'app_id' : '65a1c0ab8f1b5b00367a0002' , 'target' : 'pg' }
)
new_private_key = res.json()[ 'keys' ][ 'private_key' ] python Node.js Python cURL
RESELLER_AUTH = $( printf '%s' " $BOOTPAY_RESELLER_CLIENT_KEY : $BOOTPAY_RESELLER_SECRET_KEY " | base64 )
curl -X POST 'https://api.bootpay.co.kr/v2/reseller/seller/app/keys/reissue' \
-H "Authorization: Basic $RESELLER_AUTH " \
-H 'Content-Type: application/json' \
-d '{"app_id":"65a1c0ab8f1b5b00367a0002","target":"commerce"}' bash
2-3. 응답 commerce pg
{
"app_id" : "65a1c0ab8f1b5b00367a0002" ,
"target" : "commerce" ,
"keys" : {
"project_key_chain_id" : "65a1c0ab8f1b5b00367a0021" ,
"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"
},
"revoked" : {
"key_id" : "65a1c0ab8f1b5b00367a0020" ,
"revoked_at" : "2026-10-27T15:00:00+09:00"
}
} json commerce pg
{
"app_id" : "65a1c0ab8f1b5b00367a0002" ,
"target" : "pg" ,
"keys" : { "private_key" : "example_new_private_key" },
"revoked" : { "key_id" : null , "revoked_at" : "2026-10-27T15:00:00+09:00" }
} json
응답 파라미터
파라미터
타입
설명
app_id
String
프로젝트 식별자
target
String
pg 또는 commerce
keys
Object
새 키. commerce 는 키 생성·조회 발급 응답과 같은 모양, pg 는 { private_key }
revoked
Object / null
막은 기존 키. key_id(커머스 키체인 id, pg 는 null)·revoked_at. 커머스에 기존 키가 없었으면 null
2-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 호출 권한이 열려 있는지 부트페이 관리자에게 문의합니다
PARAMS_INVALID
target 이 pg·commerce 가 아닙니다
pg 또는 commerce 로 보냅니다
APP_NOT_FOUND (200)
프로젝트를 찾지 못했습니다 (HTTP 404)
app_id 가 올바른지 확인합니다
APP_NOT_PERMIT (201)
본인 하위 프로젝트가 아닙니다 (HTTP 401)
app_id 가 본인 리셀러 하위 셀러의 프로젝트인지 확인합니다
COMMERCE_KEY_CHAIN_FAILED (8140)
커머스 연동 키를 발급하지 못했습니다
payload.commerce_error_code 를 확인합니다. 커머스 프로젝트가 없으면 커머스 연동 재시도 를 먼저 부릅니다. 실패하면 기존 키는 그대로 살아 있습니다
3 키 발급 스코프 목록
키 생성·조회 로 하위 프로젝트 키를 만들 때 api_scopes 에 넣을 스코프 id 를 돌려줍니다. 결제(PG) 키와 커머스 키는 스코프가 다르므로 target 으로 나눠 부릅니다.
동작 규칙
api_scopes 에는 이 목록의 api_scope_id 를 넣습니다. key·name 은 사람이 고를 때 보는 값입니다.
사용 중인 스코프만 나옵니다. 같은 그룹끼리 묶여 그룹 순서 → 스코프 순서로 옵니다.
모든 리셀러가 같은 목록을 봅니다. 자주 바뀌지 않으므로 받아 두고 써도 됩니다.
리셀러 API 자체를 부르는 범위 키(reseller:* 스코프)는 범위 키(리셀러 스코프) 를 봅니다. 이 문서는 하위 프로젝트 키용 목록입니다.
API 정보 GET https://api.bootpay.co.kr/v2/reseller/scopes?target=pgBasic Auth (리셀러 계정 키)
3-1. 요청 파라미터
파라미터
타입
필수
설명
target
String
필수
pg(결제 키) 또는 commerce(커머스 키) (쿼리)
3-2. 코드 예제 Node.js Python cURL
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/scopes?target=pg' , {
headers: { 'Authorization' : RESELLER_AUTH }
})
const { list } = await res. json ()
const readOnly = list. filter ( scope => scope.key. endsWith ( ':read' )). map ( scope => scope.api_scope_id)
// readOnly 를 키 발급(POST /v2/reseller/seller/app/key-chain)의 api_scopes 에 넣는다 javascript Node.js Python cURL
import base64, os, requests
auth = 'Basic ' + base64.b64encode(
f " { os.environ[ 'BOOTPAY_RESELLER_CLIENT_KEY' ] } : { os.environ[ 'BOOTPAY_RESELLER_SECRET_KEY' ] } " .encode()
).decode()
res = requests.get( 'https://api.bootpay.co.kr/v2/reseller/scopes' , params = { 'target' : 'commerce' }, headers = { 'Authorization' : auth})
print ([(s[ 'key' ], s[ 'api_scope_id' ]) for s in res.json()[ 'list' ]]) python Node.js Python cURL
RESELLER_AUTH = $( printf '%s' " $BOOTPAY_RESELLER_CLIENT_KEY : $BOOTPAY_RESELLER_SECRET_KEY " | base64 )
curl "https://api.bootpay.co.kr/v2/reseller/scopes?target=pg" -H "Authorization: Basic $RESELLER_AUTH " bash
3-3. 응답 {
"target" : "pg" ,
"list" : [
{
"api_scope_id" : "6098a1b2c3d4e5f600000301" ,
"key" : "receipt:read" ,
"name" : "결제 조회" ,
"description" : "결제 단건·목록 조회" ,
"group_key" : "payment" ,
"group_name" : "결제"
}
]
} json
필드
타입
필수
설명
target
String
필수
요청한 target
list
Array
필수
스코프 목록
api_scope_id
String
필수
키 발급 api_scopes 에 넣는 값
key
String
필수
스코프 키
name
String
필수
스코프 이름
description
String
선택
설명
group_key
String
필수
묶음 키
group_name
String
필수
묶음 이름
3-4. 에러 코드
코드
메시지
대처 방법
API_ONLY_RESELLER (601)
리셀러만 이용이 가능한 API입니다
리셀러 권한 계정 키로 호출합니다
API_SCOPE_INVALID
허용되지 않은 API 권한의 키입니다 (HTTP 401)
키에 이 API 의 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출합니다
PARAMS_INVALID (-33)
target 이 없거나 pg·commerce 가 아닙니다
target=pg 또는 target=commerce 로 보냅니다
COMMERCE_REQUEST_FAILED (8182)
커머스 연동 서버에 요청하지 못했습니다
target=commerce 일 때만 발생합니다. 잠시 뒤 다시 부릅니다. payload.commerce_error_code 에 커머스 쪽 원인이 있습니다
4 범위 키(리셀러 스코프)
리셀러 API 는 전체 권한(supervisor) 키 대신, 필요한 API 만 허용한 범위 키 로도 호출할 수 있습니다. 키에 그 API 의 reseller:* 스코프가 있어야 합니다.
동작 규칙
Basic Auth 의 리셀러 키가 전체 권한(supervisor) 키면 지금처럼 모든 리셀러 API 를 부를 수 있습니다.
전체 권한이 아닌 키(범위 키)는 아래 표에서 그 API 의 스코프를 받은 경우에만 부를 수 있습니다. 없으면 API_SCOPE_INVALID (HTTP 401).
스코프는 API 묶음 단위입니다. 예를 들어 reseller:seller:read 만 받은 키는 가맹점 목록·조회만 되고 가맹점 생성은 막힙니다.
테스트 데이터 삭제(DELETE /v2/reseller/test/seller/:provider_id)는 스코프가 없습니다 — 전체 권한 키로만 부릅니다.
결제 조회용 등 다른 용도로 만든 범위 키로는 리셀러 API 를 부를 수 없습니다. 리셀러 연동 서버용 키를 따로 만듭니다.
Bearer 토큰(Application ID + Private Key 로 받은 레거시 토큰)은 이 검사를 받지 않습니다.
4-1. 스코프 목록
스코프
허용하는 API
문서
reseller:seller:read
GET /v2/reseller/seller · GET /v2/reseller/seller/:provider_id · GET /v2/reseller/me · GET /v2/reseller/billing
가맹점 목록 · 가맹점 조회 · 리셀러 내 정보 · 알림톡 이용료 대납
reseller:seller:write
POST /v2/reseller/seller · PUT /v2/reseller/seller/:provider_id
가맹점 생성 · 가맹점 정보 수정
reseller:app:read
GET /v2/reseller/seller/app · GET /v2/reseller/seller/app/:app_id · GET /v2/reseller/seller/app/:app_id/payment-methods · GET /v2/reseller/pgs · GET /v2/reseller/seller/app/commerce/:app_id/webhook
프로젝트 목록 · 프로젝트 조회 · 결제수단 목록 · PG·필수 연동 값 목록 · 커머스 웹훅 설정
reseller:app:write
POST /v2/reseller/seller/app · PATCH /v2/reseller/seller/app/resource/:app_id · PUT /v2/reseller/seller/app/commerce/:app_id · PUT /v2/reseller/seller/app/commerce/:app_id/webhook · POST /v2/reseller/alimtalk/channel/link · PUT /v2/reseller/seller/app/:app_id/payment-lock
프로젝트 생성 · PG 리소스 갱신 · 커머스 연동 재시도 · 커머스 웹훅 설정 · 알림톡 채널 일괄 연결 · 결제 설정 잠금
reseller:key:read
GET /v2/reseller/seller/app/key-chain/:app_id · GET /v2/reseller/scopes
키 생성·조회 · 키 발급 스코프 목록
reseller:key:write
POST /v2/reseller/seller/app/key-chain · DELETE /v2/reseller/seller/app/key-chain/:key_chain_id · POST /v2/reseller/seller/app/keys/reissue
키 생성·조회 · 키 재발급
reseller:onboarding:read
GET /v2/reseller/seller/:provider_id/onboarding · GET /v2/reseller/seller/:provider_id/onboarding/:onboarding_id/documents · GET /v2/reseller/agreements
등록 상태 조회 · 신청서 서류 열기 · 등록 API 접수
reseller:onboarding:write
POST /v2/reseller/seller/:provider_id/onboarding/session · POST /v2/reseller/seller/:provider_id/onboarding · PUT /v2/reseller/seller/:provider_id/onboarding/:onboarding_id · POST /v2/reseller/seller/:provider_id/files/grant
등록 폼 세션 발급 · 등록 API 접수
reseller:webhook:read
GET /v2/reseller/webhook
리셀러 웹훅
reseller:webhook:write
PUT /v2/reseller/webhook
리셀러 웹훅
reseller:invite:write
POST /v2/reseller/invite
프로젝트 초대
*:write 스코프는 같은 묶음의 *:read 를 포함하지 않습니다. 조회도 하려면 두 스코프를 함께 줍니다.
4-2. 범위 키 만드는 법 리셀러 계정으로 관리자 콘솔 → 개발자 설정 > 결제 연동키 에서 리셀러 프로젝트의 새 키를 발급하고, 권한 범위(Scope) 에서 리셀러 그룹의 필요한 스코프만 고릅니다. 화면 사용법은 연동키 발급 과 같습니다.
호출 방법은 전체 권한 키와 같습니다.
Authorization: Basic base64(client_key:secret_key)
가맹점 가입을 받는 서버: reseller:seller:write · reseller:app:write · reseller:onboarding:write
대시보드처럼 읽기만 하는 서버: reseller:seller:read · reseller:app:read · reseller:onboarding:read
키 발급·재발급은 따로 둔 관리 서버 키에만 reseller:key:write
범위 키 검사를 통과해도, 부트페이가 리셀러 계정에 열어 둔 API 권한이 꺼져 있으면 쓰기 API 는 막힙니다. 두 검사를 모두 통과해야 합니다.
4-3. 오류 코드
코드
메시지
대처 방법
API_SCOPE_INVALID
키에 이 API 의 스코프가 없습니다 (HTTP 401)
위 표에서 그 API 의 스코프를 키에 추가하거나 전체 권한 키로 호출합니다. 테스트 데이터 삭제는 전체 권한 키만 됩니다
API_ROLE_NOT_SUPPORT
이 API 의 스코프가 아직 준비되지 않았습니다 (HTTP 401)
전체 권한 키로 호출하고 부트페이에 문의합니다
APP_KEY_CHAIN_EXPIRED
키가 만료됐습니다 (HTTP 401)
만료일을 확인하고 새 키를 발급합니다