하위 프로젝트의 키를 새로 만들고 기존 키는 그 자리에서 막는다. 결제(PG) 쪽은 프로젝트 Private Key 를, 커머스 쪽은 생성 응답에서 받은 리셀러 전용 커머스 서버 키(reseller-default)를 바꾼다.
핵심 요약
- 유예 시간이 없다. 응답을 받는 순간 기존 키로 하는 호출은 실패한다. 새 키를 서버 설정에 먼저 넣을 준비를 하고 부른다.
- 새 비밀키 원문은 이 응답에서만 나온다. 받은 즉시 안전하게 저장한다.
target: pg — 프로젝트의 private_key 를 바꾼다. 같은 프로젝트를 쓰는 모든 서버가 영향을 받는다. 이미 받아 둔 액세스 토큰은 만료(최대 30분)까지 그대로 쓸 수 있다.
target: commerce — 리셀러 전용 커머스 서버 키(reseller-default)를 새로 만들고 기존 것을 막는다. 기존 키가 없었으면 새로 만들기만 하고 revoked 는 null 이다. 키 생성·조회 로 따로 만든 키는 건드리지 않는다.
API 정보
POSThttps://api.bootpay.co.kr/v2/reseller/seller/app/keys/reissueBasic Auth (리셀러 계정 키)
요청 파라미터
| 파라미터 |
타입 |
필수 |
설명 |
app_id |
String |
필수 |
키를 바꿀 하위 프로젝트의 app_id |
target |
String |
필수 |
pg 또는 commerce |
코드 예제
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
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
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
응답
{
"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
{
"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 |
에러 코드
| 코드 |
메시지 |
대처 방법 |
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 를 확인한다. 커머스 프로젝트가 없으면 커머스 연동 재시도 를 먼저 부른다. 실패하면 기존 키는 그대로 살아 있다 |