리셀러 채널을 하위 프로젝트에 연결하고, 하위 가맹점의 유료 알림톡 이용료를 대신 냅니다. 발송·템플릿 API 는 커머스 매뉴얼 을 봅니다.
| API | 하는 일 |
|---|---|
| 1. 알림톡 채널 일괄 연결 | 리셀러 알림톡 채널을 하위 프로젝트에 한 번에 연결 |
| 2. 알림톡 이용료 대납 | 이용료 대납 옵션과 내 잔액·기간 대납 금액 조회 |
인증·권한 오류는 각 표에 없어도 공통 오류 가 날 수 있습니다.
1알림톡 채널 일괄 연결
리셀러가 자기 프로젝트에서 OTP 로 등록한 카카오 알림톡 채널을 하위 프로젝트들의 알림 설정에 연결합니다. 하위 판매자마다 채널 OTP 를 다시 받지 않아도 되고, 그 채널에 이미 승인된 템플릿도 그대로 쓸 수 있습니다. 이 API 는 알림톡을 보내지 않습니다 — 보내기는 아래 「하위 판매자 명의로 보내기」를 봅니다.
동작 규칙
- 연결할 수 있는 채널은 리셀러가 소유한 채널뿐입니다: 리셀러 프로젝트에서 OTP 로 새로 발급받은 채널이고, 지금 리셀러 프로젝트에 연결돼 있어야 합니다. 다른 가맹점이 발급한 채널을 키나 목록으로 가져와 연결만 한 경우는 소유가 아닙니다.
app_ids는 본인 리셀러 하위 프로젝트만, 한 번에 20개까지. 결과는 프로젝트마다 하나씩(linked·exists·failed) 옵니다 — 일부가 실패해도 나머지는 연결됩니다.- 하위 프로젝트가 자기 채널을 이미 쓰고 있으면 덮어쓰지 않습니다(
RESELLER_CHANNEL_TARGET_IN_USE). 판매자가 그 채널 연결을 해제한 뒤 다시 부릅니다. 같은 리셀러 소유의 다른 채널을 쓰던 프로젝트는 바꿔 끼웁니다. - 이미 같은 채널이 연결된 프로젝트는
exists로 오고 아무것도 바뀌지 않습니다 — 실패한 것만 골라 다시 불러도 되고, 같은 목록으로 다시 불러도 안전합니다. - 연결하면 그 채널의 자체 템플릿을 하위 프로젝트도 보고·쓸 수 있습니다(템플릿은 채널 단위입니다). 하위 판매자가 콘솔에서 템플릿을 고칠 수 있다는 점을 알고 사용합니다.
- 판매자가 콘솔에서 리셀러 채널을 스스로 가져다 쓸 수는 없습니다. 연결은 이 API 로 리셀러만 합니다.
API 정보
https://api.bootpay.co.kr/v2/reseller/alimtalk/channel/linkBasic Auth (리셀러 계정 키)1-1. 요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
ksp_id |
String | 필수 | 연결할 채널(발신 프로필) id. 리셀러 프로젝트 키로 GET /alimtalk/senders 를 부르면 나옵니다 |
app_ids |
Array | 필수 | 채널을 연결할 하위 프로젝트 app_id 목록. 1~20개, 같은 값은 한 번만 처리합니다 |
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/alimtalk/channel/link', {
method: 'POST',
headers: {
'Authorization': RESELLER_AUTH,
'Content-Type': 'application/json'
},
body: JSON.stringify({
ksp_id: '6718a0aa8f1b5b00367a0300',
app_ids: ['65a1c0ab8f1b5b00367a0002', '65a1c0ab8f1b5b00367a0003']
})
})
const data = await res.json()
data.list.filter((row) => row.status === 'failed').forEach((row) => console.log(row.app_id, row.error_code))javascriptimport 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/alimtalk/channel/link',
headers={'Authorization': auth},
json={
'ksp_id': '6718a0aa8f1b5b00367a0300',
'app_ids': ['65a1c0ab8f1b5b00367a0002', '65a1c0ab8f1b5b00367a0003']
}
)
print(res.json())pythonRESELLER_AUTH=$(printf '%s' "$BOOTPAY_RESELLER_CLIENT_KEY:$BOOTPAY_RESELLER_SECRET_KEY" | base64)
curl -X POST 'https://api.bootpay.co.kr/v2/reseller/alimtalk/channel/link' \
-H "Authorization: Basic $RESELLER_AUTH" \
-H 'Content-Type: application/json' \
-d '{"ksp_id":"6718a0aa8f1b5b00367a0300","app_ids":["65a1c0ab8f1b5b00367a0002","65a1c0ab8f1b5b00367a0003"]}'bash1-3. 응답
{
"ksp_id": "6718a0aa8f1b5b00367a0300",
"list": [
{
"app_id": "65a1c0ab8f1b5b00367a0002",
"status": "linked",
"project_id": "65a1c0ab8f1b5b00367a0006",
"ksp_id": "6718a0aa8f1b5b00367a0300",
"yellow_id": "@example_channel",
"channel_name": "예시 채널",
"group_key_registered": true
},
{
"app_id": "65a1c0ab8f1b5b00367a0003",
"status": "failed",
"error_code": "RESELLER_CHANNEL_TARGET_IN_USE",
"message": "하위 프로젝트에 이미 다른 알림톡 채널이 연결되어 있습니다. 하위 가맹점이 연결을 해제한 뒤 다시 시도해 주세요."
}
],
"success_count": 1,
"failure_count": 1
}json응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| ksp_id | String | 요청한 채널 id |
| list | Array | 프로젝트별 결과(요청 순서, 중복 제거) |
| list[].app_id | String | 하위 프로젝트 식별자 |
| list[].status | String | linked 이번에 연결 · exists 이미 연결돼 있음 · failed 실패 |
| list[].project_id | String | 커머스 프로젝트 식별자(성공일 때) |
| list[].yellow_id | String | 채널 검색용 아이디(성공일 때) |
| list[].channel_name | String | 채널 이름(성공일 때) |
| list[].group_key_registered | Boolean | 공식 템플릿을 쓸 수 있는 채널인지(부트페이 그룹 등록). false 면 자체 템플릿만 쓸 수 있습니다 |
| list[].error_code | String | 실패 원인 코드(failed 일 때, 아래 표) |
| list[].message | String | 실패 사유(failed 일 때) |
| success_count | Number | linked + exists 수 |
| failure_count | Number | failed 수 |
1-4. 프로젝트별 실패 원인 (list[].error_code)
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
RESELLER_ |
리셀러가 직접 등록한 알림톡 채널만 하위 프로젝트에 연결할 수 있습니다 | 리셀러 프로젝트에서 그 채널을 OTP 로 직접 등록한 경우에만 연결할 수 있습니다 |
SENDER_ |
연결된 발신 프로필이 없습니다 | ksp_id 가 맞는지, 그 채널이 지금 리셀러 프로젝트에 연결돼 있고 막히지 않았는지 봅니다 |
RESELLER_ |
하위 프로젝트에 이미 다른 알림톡 채널이 연결되어 있습니다 | 판매자가 알림 설정에서 기존 채널 연결을 해제한 뒤 다시 부릅니다 |
PROJECT_ |
커머스 프로젝트가 없습니다 | 커머스 연동 재시도 로 먼저 만듭니다 |
APP_ |
프로젝트를 찾지 못했습니다 | app_id 가 올바른지 확인합니다 |
APP_ |
본인 하위 프로젝트가 아닙니다 | 본인 리셀러 하위 셀러의 프로젝트인지 확인합니다 |
(없음) |
커머스 연동 서버에 닿지 못했습니다 | 그 뒤 프로젝트는 부르지 않고 같은 사유로 실패 처리됩니다. 잠시 뒤 같은 목록으로 다시 부릅니다 |
요청 전체 오류: ALIMTALK_CHANNEL_LINK_INVALID(8193, HTTP 400) — ksp_id 가 비었거나 app_ids 가 0개·21개 이상. 인증·권한 오류는 공통 오류 를 봅니다.
1-5. 하위 판매자 명의로 보내기
하위 판매자(강사)의 채널로 수강생에게 보내는 흐름입니다. 새 발송 API 는 없고, 기존 알림톡 API(https://message.bootapi.com/alimtalk)를 하위 프로젝트의 커머스 키로 부릅니다.
- 채널 준비 — 둘 중 하나.
- 리셀러 프로젝트 키로 그 판매자의 카카오 채널을 OTP 로 등록합니다(
POST /alimtalk/senders/otp→POST /alimtalk/senders). 그다음 이 API 로 판매자의 하위 프로젝트에 연결합니다. 리셀러 프로젝트에는 채널이 하나만 연결되므로, 다음 판매자 채널을 등록하기 전에 먼저 연결해 둡니다. - 또는 처음부터 하위 프로젝트 커머스 키로 OTP 등록을 합니다. 이때 채널은 그 판매자 것이 되고 이 API 는 필요 없습니다.
- 리셀러 프로젝트 키로 그 판매자의 카카오 채널을 OTP 로 등록합니다(
- 템플릿 — 자체 템플릿은 채널에 묶입니다. 그 채널에 승인된 자체 템플릿은 연결된 모든 하위 프로젝트에서 쓸 수 있습니다. 공식 템플릿은
group_key_registered: true인 채널에서 쓸 수 있습니다. - 보내기 — 리셀러 서버가
POST https://message.bootapi.com/alimtalk/send를 하위 프로젝트의 커머스 키(생성 응답의commerce.key_chain)로 부릅니다. 채널은 그 프로젝트에 연결된 채널로 정해지고, 발송 결과 웹훅은 하위 프로젝트 설정이나 요청의webhook_url로 받습니다. - 요금 — 발송 비용은 기본으로 그 하위 판매자의 메시지 요금제에서 나갑니다. 하위 판매자가 선불(첫 충전 완료) 또는 직접 납부 요금제가 아니면
NOTIFICATION_NEED_PAYMENT(3503)·SERVICE_PAYMENT_BLOCKED(11100)·MESSAGE_PREPAID_NOT_CHARGED(11101, 선불 첫 충전 전)로 막힙니다. 리셀러의 알림톡 이용료 대납 옵션이 켜져 있으면 리셀러 선불 잔액에서 나가고, 이 검사도 리셀러를 기준으로 합니다. 이때 리셀러가 선불 요금제가 아니면MESSAGE_BILLING_PAYER_NOT_PREPAID(16315)로 막힙니다.
2알림톡 이용료 대납
알림톡 이용료 대납은 리셀러의 비용 납부 옵션입니다. 켜면 그 리셀러의 하위 가맹점 전체가 보내는 유료 알림톡 이용료가 리셀러의 선불 잔액에서 빠지고, 하위 가맹점은 충전하지 않아도 보낼 수 있습니다. 하위 가맹점마다 따로 정하지 않습니다.
동작 규칙
- 옵션은 리셀러를 만들 때 리셀러 가입 화면에서 고릅니다. 처음 값은 「하위 가맹점이 직접 낸다」입니다.
- 만든 뒤에는 부트페이 관리자만 바꿀 수 있습니다. 바꾸려면 부트페이에 문의합니다. 리셀러 API 와 리셀러 관리자 콘솔은 보기만 합니다.
- 지금 값은 리셀러 내 정보
GET /v2/reseller/me의reseller_contract.message_billing_payer와 리셀러 관리자 콘솔 「설정 › 계약·동의」에서 봅니다. - 옵션이 켜져 있으면 하위 가맹점의 모든 프로젝트에서 보내는 유료 알림톡이 리셀러 잔액에서 빠집니다.
- 대납하려면 리셀러가 선불 요금제여야 합니다. 리셀러는 부트페이 관리자의 이용요금 화면에서 자기 잔액을 충전합니다(자동충전도 그대로 쓸 수 있습니다). 옵션이 켜져 있는데 리셀러가 선불 요금제가 아니면 하위 가맹점의 유료 알림톡이 400(16315)으로 막힙니다. 하위 가맹점의 잔액으로 대신 내지 않습니다.
- 대납 중에 리셀러 잔액이 모자라면 하위 가맹점의 유료 알림톡이 잔액 부족(16312)으로 막힙니다. 문구는 「알림톡 이용료를 내는 리셀러의 잔액이 부족해 보낼 수 없습니다」입니다.
- 부트페이가 옵션을 끄거나 리셀러 사용을 중지하면 하위 가맹점이 직접 내게 되고, 하위 가맹점 담당자에게 알림톡으로 알립니다. 사용 중지가 풀리면 옵션이 켜져 있는 한 다시 리셀러가 냅니다.
- 부트페이가 무료로 보내는 커머스 주문·구독 알림은 대납과 상관없이 계속 무료입니다.
2-1. 대납하면 바뀌는 것
| 하위 가맹점이 직접 납부(옵션 꺼짐) | 리셀러 대납(옵션 켜짐) | |
|---|---|---|
| 유료 알림톡 이용료가 빠지는 곳 | 하위 가맹점 선불 잔액 | 리셀러 선불 잔액 |
| 하위 가맹점 충전 | 필요(처음 한 번은 충전해야 보낼 수 있습니다) | 필요 없음 |
| 잔액이 모자랄 때 | 그 하위 가맹점 발송이 16312 | 하위 가맹점 발송이 모두 16312 |
| 리셀러 잔액 내역(이용요금 화면) | — | 「알림톡 발송 이용료 차감 · 하위 가맹점 이름」으로 남습니다 |
바뀐 뒤에 접수된 발송부터 적용됩니다. 이미 접수돼 처리 중인 발송은 접수할 때의 납부자 기준으로 끝납니다.
2-2. 대납 현황 조회
내 선불 잔액과, 기간 동안 하위 가맹점 대신 낸 금액을 봅니다. 리셀러 관리자 콘솔의 「알림톡 › 하위 가맹점 사용량」 화면과 같은 값입니다.
https://api.bootpay.co.kr/v2/reseller/billingBasic Auth (리셀러 계정 키)| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
s_at |
String | 선택 | 시작일 YYYY-MM-DD(한국 시간). 비우면 이번 달 1일 |
e_at |
String | 선택 | 종료일 YYYY-MM-DD. 비우면 지금. 기간이 92일을 넘으면 시작일을 당깁니다 |
page |
Integer | 선택 | 쪽 번호(기본 1). 하위 가맹점은 새로 만든 순 |
limit |
Integer | 선택 | 한 쪽 가맹점 수(기본 20, 최대 100) |
RESELLER_AUTH=$(printf '%s' "$BOOTPAY_RESELLER_CLIENT_KEY:$BOOTPAY_RESELLER_SECRET_KEY" | base64)
curl "https://api.bootpay.co.kr/v2/reseller/billing?s_at=2026-11-01&e_at=2026-11-30" \
-H "Authorization: Basic $RESELLER_AUTH"bash{
"period": { "from": "2026-11-01T00:00:00+09:00", "to": "2026-11-30T23:59:59+09:00" },
"balance": 52300.5,
"available": 51600.5,
"held": 700,
"paid_total": 11161.15,
"payer_count": 2,
"pays_children": true,
"children": [
{ "provider_id": "65a1c0aa8f1b5b00367a0001", "name": "하위 가맹점 가", "payer": "reseller", "success": 1243, "paid_amount": 8887.45 },
{ "provider_id": "65a1c0aa8f1b5b00367a0002", "name": "하위 가맹점 나", "payer": "reseller", "success": 318, "paid_amount": 2273.7 }
],
"count": 2,
"page": 1,
"limit": 20
}json| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
balance |
Number | 필수 | 선불 잔액(VAT 포함). 건당 차감액에 소수가 있어 소수 둘째 자리까지 옵니다 |
available |
Number | 필수 | 지금 쓸 수 있는 금액 = balance − held |
held |
Number | 필수 | 보내는 중이라 잡아 둔 금액. 발송 결과가 나오면 차감되거나 풀립니다 |
paid_total |
Number | 필수 | 기간 동안 하위 가맹점 대신 낸 금액 합계. page 와 상관없이 기간 전체입니다 |
payer_count |
Integer | 필수 | 지금 대납 중인 하위 가맹점 수. 옵션이 켜져 있으면 하위 가맹점 전부, 꺼져 있으면 0 |
pays_children |
Boolean | 필수 | 대납 옵션이 지금 켜져 있는지. 사용 중지 중이면 false |
children |
Array | 필수 | 이 쪽의 하위 가맹점 |
payer |
String | 필수 | reseller 내가 냅니다 · self 가맹점이 냅니다 |
success |
Integer | 필수 | 기간 동안 성공한 유료 알림톡 건수 |
paid_amount |
Number | 필수 | 기간 동안 내가 대납한 금액. 옵션이 꺼져도 그 기간에 이미 대납한 금액은 남습니다 |
count |
Integer | 필수 | 하위 가맹점 수(전체) |
paid_amount 는 발송 결과가 확정된 건마다 「단가 × 1.1(VAT), 소수 둘째 자리 버림」으로 계산한 금액의 합입니다. 잔액에서 건마다 빼는 금액과 같은 계산입니다(보내는 순간 잔액을 확인해 막으므로 드물지만, 결과가 확정될 때 잔액이 모자라 빼지 못한 건도 여기에는 들어갑니다). 이 API 는 reseller:seller:read 범위로 부릅니다. 기간 형식이 틀리거나 시작일이 종료일보다 늦으면 PARAMS_INVALID(HTTP 400), 그 밖의 실패는 COMMERCE_REQUEST_FAILED(8182)입니다.
2-3. 에러 코드
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
API_ (601) |
리셀러만 이용이 가능한 API입니다 | 리셀러 권한 계정 키로 호출합니다 |
API_ |
허용되지 않은 API 권한의 키입니다 (HTTP 401) | reseller:seller:read 리셀러 스코프 를 주거나 전체 권한(supervisor) 키로 호출합니다 |
PARAMS_ (-33) |
기간 형식이 틀렸거나 시작일이 종료일보다 늦습니다 (HTTP 400) | s_at·e_at 을 YYYY-MM-DD 로, 시작일을 종료일 이전으로 보냅니다 |
COMMERCE_ (8182) |
커머스 연동 서버에 요청하지 못했습니다 (HTTP 400) | 잠시 후 다시 부릅니다. 원인은 payload.commerce_error_code |





