프로젝트의 서버 연동 키(Client Key / Secret Key)를 조회하고 새로 발급한다. 결제(PG) 키와 커머스 키를
target으로 구분한다.
핵심 요약
- 조회는
GET, 발급은POST다. 모두app_id로 프로젝트를 지정한다. target: pg키는 셀러 프로젝트로 결제 REST API(Basic Auth)를 호출할 때 쓴다.target: commerce키는 커머스 API 를 호출할 때 쓴다.- 목록의
secret_key는 앞 5자 +*****로 마스킹된다.secret_key가 평문으로 나오는 응답은 발급 응답뿐이다. - 발급 응답은 다시 볼 수 없다. 받은 즉시 셀러 레코드에 안전하게 저장한다.
target: commerce는 커머스 프로젝트가 있어야 한다. 없으면 먼저 커머스 연동 재시도 를 부른다.
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 (리셀러 계정 키)요청 파라미터
조회 (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 일 때 쓴다 |
expires_at |
String | 선택 | 만료 시각 (ISO8601). 없으면 무기한 |
코드 예제
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)javascriptimport 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())pythonRESELLER_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응답
조회 응답
secret_key 는 마스킹되어 온다. 커머스 프로젝트가 없으면 commerce 는 null 이다.
{
"pg": [
{
"app_key_chain_id": "65a1c0ab8f1b5b00367a0020",
"name": "서버 연동용",
"client_key": "65a1c0ab8f1b5b00367a0021",
"secret_key": "Ab3dE*****",
"is_supervisor": true,
"expires_at": null,
"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": null,
"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-20T00:00:00+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 |
| 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 / null | 만료 시각. 무기한이면 null |
| api_scopes | Array |
허용된 API scope id 목록 |
| created_at | String | 생성 시각 |
| server_at | String | 서버 기록 시각 |
| is_copiable | Boolean | secret_key 를 그대로 복사할 수 있는지. 발급 응답에서만 true |
| status | Number | 키 상태 |
에러 코드
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
API_ONLY_RESELLER |
리셀러만 이용이 가능한 API 다 | 리셀러 권한 계정 키로 호출한다 |
API_SCOPE_INVALID |
허용되지 않은 API 권한의 키다 | 리셀러 프로젝트의 전체 권한(supervisor) Client Key 로 호출한다 |
APP_NOT_FOUND |
프로젝트를 찾지 못했다 | app_id 가 올바른지 확인한다 |
APP_NOT_PERMIT |
본인 하위 프로젝트가 아니다 | app_id 가 본인 리셀러 하위 셀러의 프로젝트인지 확인한다 |
PARAMS_INVALID |
요청 파라미터가 올바르지 않다 | target 을 pg 또는 commerce 로 보낸다 |
APP_API_SCOPE_NOT_MATCHED |
허용되지 않은 API scope 다 | api_scopes 에 존재하는 scope id 만 보낸다 |
COMMERCE_API_TOKEN_ERROR |
커머스 키 발급에 실패했다 | message 의 사유를 확인한다. 커머스 프로젝트가 없으면 커머스 연동 재시도 를 먼저 부른다 |
다음 단계
- 커머스 프로젝트를 먼저 연결하려면 → 커머스 연동 재시도
- 프로젝트의 연동키 전체를 보려면 → 프로젝트 조회