하위 가맹점 한 곳의 PG 가맹 신청 화면(등록 폼)을 열 수 있는 토큰을 발급한다. 받은
token을 등록 폼 열기 (JS SDK) 에 넘기거나url을 그대로 열면, 판매자는 부트페이 계정 없이 신청서를 작성해 접수한다.
핵심 요약
- 토큰은 하위 가맹점 1곳 · 30분 · 접수 1회로 묶인다. 접수하면 소진되고, 30분이 지나면 열리지 않는다.
- 토큰 평문은 이 응답에서만 나온다. 부트페이는 해시만 저장하므로 다시 조회할 수 없다. 필요하면 새로 발급한다.
- 같은 하위 가맹점·같은 종류로 다시 발급하면 아직 쓰지 않은 이전 토큰은 바로 만료된다.
- 지금 열 수 있는 종류(
kind)는pg_join(PG 가맹 신청) 하나다. - 신청 단계가 바뀔 때마다 리셀러 웹훅 이 오고, 놓친 단계는 등록 상태 조회 로 다시 맞춘다.
서버에서만 발급한다
이 API 는 리셀러 계정 키(Client Key·Secret Key)로 부른다. 브라우저·앱에 리셀러 키를 두지 말고, 리셀러 서버에서 발급한 token 만 판매자 화면에 넘긴다. 토큰을 로그에 남기면 30분 동안 누구나 그 가맹점 이름으로 신청서를 낼 수 있다.
API 정보
POST
https://api.bootpay.co.kr/v2/reseller/seller/:provider_id/onboarding/sessionBasic Auth (리셀러 계정 키)요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
provider_id |
String | 필수 | 신청을 받을 하위 가맹점의 provider_id (URL 경로) |
kind |
String | 필수 | 등록 폼 종류. 지금은 pg_join 만 |
mode |
String | 선택 | new 새 신청(기본) · edit 기존 신청서 수정·재제출 |
pg_wait_id |
String | 선택 | mode=edit 일 때 필수. 고칠 신청서의 onboarding_id |
allowed_pgs |
Array | 선택 | 신청할 PG 별칭. new 는 정확히 1개 필수, edit 는 비우면 신청서의 PG |
allowed_methods |
Array | 선택 | 고를 수 있는 결제수단 별칭. 비우면 그 PG 의 결제수단 전부 |
app_id |
String | 선택 | PG 승인 뒤 MID 를 연결할 하위 프로젝트. 비우면 그 가맹점에서 가장 먼저 만든 프로젝트 |
prefill |
Object | 선택 | 신청서에 미리 채울 값 ({키: 값}, 값은 문자열·숫자, 1000자 이하) |
locked |
Array | 선택 | 판매자가 고칠 수 없게 잠글 키. prefill 에 있는 키만 |
return_url |
String | 선택 | 접수 뒤 돌아갈 주소. https:// 만, 2048자 이하 |
brand |
Object | 선택 | 신청 화면 상단 브랜드 {name(30자 이하), logo_url(https)} |
prefill·locked 에 쓸 수 있는 키는 아래와 같다. 이 밖의 키를 보내면 400 ONBOARDING_PREFILL_INVALID 로 거부된다(오타를 바로 알 수 있게 조용히 버리지 않는다). pg_alias 를 보내면 allowed_pgs 의 PG 와 같아야 한다.
| 묶음 | 키 |
|---|---|
| 사업자 | company_name seller_type regist_no corp_reg_no owner_name owner_birth_date corp_capital zip addr1 addr2 biz_email biz_tel biz_fax tax_type |
| 서비스 | service_name site_url business_type business_item real_type good_type desc max_term month_price good_price policy type |
| 담당자 | name email phone tel |
| 정산 계좌 | bank_code account_number account_owner |
| PG | pg_alias pay_method expect_mid |
코드 예제
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}/onboarding/session`, {
method: 'POST',
headers: {
'Authorization': RESELLER_AUTH,
'Content-Type': 'application/json'
},
body: JSON.stringify({
kind: 'pg_join',
allowed_pgs: ['nicepay'],
prefill: { company_name: '예시상점', regist_no: '1234567890' },
locked: ['company_name', 'regist_no'],
return_url: 'https://reseller.example.com/onboarding/done',
brand: { name: '예시 리셀러', logo_url: 'https://reseller.example.com/logo.png' }
})
})
const { token, url, expires_at } = await res.json()
// token 만 판매자 화면에 넘긴다 — 로그에 남기지 않는다javascriptimport base64, os, requests
auth = 'Basic ' + base64.b64encode(
f"{os.environ['BOOTPAY_RESELLER_CLIENT_KEY']}:{os.environ['BOOTPAY_RESELLER_SECRET_KEY']}".encode()
).decode()
provider_id = '65a1c0aa8f1b5b00367a0001'
res = requests.post(
f'https://api.bootpay.co.kr/v2/reseller/seller/{provider_id}/onboarding/session',
headers={'Authorization': auth},
json={
'kind': 'pg_join',
'allowed_pgs': ['nicepay'],
'prefill': {'company_name': '예시상점', 'regist_no': '1234567890'},
'locked': ['company_name', 'regist_no'],
'return_url': 'https://reseller.example.com/onboarding/done'
}
)
session = res.json() # token 은 판매자 화면에만 넘긴다pythonRESELLER_AUTH=$(printf '%s' "$BOOTPAY_RESELLER_CLIENT_KEY:$BOOTPAY_RESELLER_SECRET_KEY" | base64)
PROVIDER_ID='65a1c0aa8f1b5b00367a0001'
curl -X POST "https://api.bootpay.co.kr/v2/reseller/seller/$PROVIDER_ID/onboarding/session" \
-H "Authorization: Basic $RESELLER_AUTH" \
-H 'Content-Type: application/json' \
-d '{"kind":"pg_join","allowed_pgs":["nicepay"]}'bash응답
{
"token": "rst_example_token",
"url": "https://admin.bootpay.co.kr/onboarding/s/rst_example_token",
"expires_at": "2026-10-27T15:30:00+09:00"
}json응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| token | String | 등록 폼 토큰(rst_ 로 시작). 이 응답에서만 나온다 |
| url | String | 토큰으로 바로 여는 신청 화면 주소. SDK 없이 새 창·리다이렉트로 열 때 쓴다 |
| expires_at | String | 만료 시각(ISO 8601, 발급 + 30분) |
판매자가 열었을 때
| 상황 | 신청 화면 |
|---|---|
| 30분이 지남 | "신청 주소를 쓸 수 있는 시간이 지났어요" — 새로 발급한다 |
| 이미 접수함 | "이미 접수한 신청 주소예요" — 고칠 내용은 mode=edit 로 새로 발급한다 |
| 같은 가맹점에 새 토큰을 발급함 | 이전 토큰은 만료로 안내된다 |
| 리셀러 사용이 멈춤 | 열리지 않는다 |
에러 코드
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
API_ONLY_RESELLER (601) |
리셀러만 이용이 가능한 API 다 | 리셀러 권한 계정 키로 호출한다 |
API_SCOPE_INVALID |
허용되지 않은 API 권한의 키다 (HTTP 401) | 키에 이 API 의 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출한다 |
RESELLER_SUSPENDED (343) |
본사가 리셀러 사용을 멈췄다 (HTTP 403) | 부트페이에 문의한다 |
ONBOARDING_KIND_INVALID |
kind 가 없거나 모르는 값이다 |
pg_join 으로 보낸다 |
ONBOARDING_KIND_NOT_READY |
아직 열지 않은 종류다(sub_mall) |
지금은 pg_join 만 쓴다 |
ONBOARDING_KIND_TYPE_MISMATCH (8168) |
이 리셀러 유형으로는 만들 수 없는 등록 폼이다 (HTTP 403). PG 가맹 신청(pg_join)은 B형(영업대행) 리셀러만 만들 수 있다 — 메시지에 이 계정의 유형이 나온다 |
지금 유형은 리셀러 내 정보 의 reseller_contract.type 으로 확인한다. 바꾸려면 부트페이에 문의한다 |
PROVIDER_NOT_FOUND (300) |
본인 하위 가맹점이 아니다 (HTTP 404) | provider_id 가 본인 하위 가맹점인지 확인한다 |
ONBOARDING_MODE_INVALID |
mode 가 new·edit 가 아니다 |
new 또는 edit 로 보낸다 |
PG_WAIT_NOT_FOUND (11000) |
그 가맹점의 신청서가 아니다 (HTTP 404) | pg_wait_id 를 등록 상태 조회 의 onboarding_id 로 보낸다 |
PW_NOT_EDITABLE_STATUS (2232) |
신청이 끝난 건은 고칠 수 없다 | 새 신청은 mode=new 로 발급한다 |
APP_NOT_FOUND (200) |
그 가맹점의 사용 중인 프로젝트가 아니다 (HTTP 404) | app_id 를 확인하거나 비운다 |
ONBOARDING_ALLOWED_PGS_INVALID |
allowed_pgs 가 1개가 아니거나 신청서의 PG 와 다르다 |
PG 별칭을 하나만 보낸다 |
PG_NOT_FOUND |
없거나 쓰지 않는 PG 다 (HTTP 404) | PG 코드 에서 별칭을 확인한다 |
ONBOARDING_ALLOWED_METHODS_INVALID |
그 PG 에서 쓸 수 없는 결제수단이 있다 | 결제수단 별칭을 확인하거나 비운다 |
ONBOARDING_PREFILL_INVALID |
prefill·locked 에 받을 수 없는 키나 값이 있다 |
위 허용 키 표를 확인한다 |
ONBOARDING_RETURN_URL_INVALID |
return_url 이 https 가 아니거나 너무 길다 |
2048자 이하의 https:// 주소로 보낸다 |
ONBOARDING_BRAND_INVALID |
brand 값이 올바르지 않다 |
name 30자 이하, logo_url 은 https:// |


