카카오 알림톡 API
사전 승인된 템플릿으로 카카오 알림톡을 발송합니다. 실패 시 SMS로 자동 대체(failover)됩니다.
1. 카카오 비즈 채널 등록 및 카카오 채널 ID 확보
2. 발신 프로필 키(senderKey) 발급
3. 발송할 템플릿 승인 완료 (templateCode 확인)
수신번호 필드: SMS는 receiver, 알림톡은 phone
템플릿 생명주기
가맹점이 imsend 에 등록한 알림톡 템플릿은 4 단계 상태를 갖습니다.
REGISTERED ─[검수요청]─▶ INSPECTING ─[승인]─▶ APPROVED ─[삭제]─▶ DELETED
▲ │
│ ◀─[반려]─┘
└────[수정·재등록]──────────────────────┘
| 상태 | 의미 | 발송 가능? |
|---|---|---|
REGISTERED | imsend 에 등록만 됨 (검수 미요청) | 불가 |
INSPECTING | 관리자 검수 진행 중 | 불가 |
APPROVED | 승인 완료 — 발송에 사용 가능 | 가능 |
REJECTED | 반려 (수정 후 재요청 필요) | 불가 |
DELETED | 소프트 삭제 (로그·감사 추적 보존) | 불가 |
APPROVED 는 imsend 관리자 검수 통과를 의미하며, 실제 알림톡 발송은 카카오 비즈센터에서도 별도 등록·승인된 템플릿만 도달합니다. 자세한 운영 가이드는 docs/operations/ALIMTALK_BUTTONS_AND_TEMPLATE_FORMAT.md 참고.
카카오 설정 조회
GET /api/v1/tenant/kakao
가맹점에 등록된 카카오 채널 ID·발신프로필 키·활성 상태·SMS 자동 대체 설정을 조회합니다. senderKey 는 보안상 마스킹되어 반환됩니다.
GET /api/v1/tenant/kakao
X-API-Key: your_api_key_here
응답 예시
{
"success": true,
"data": {
"kakaoChId": "@문피디",
"senderKey": "2b5cc1be***c371c3",
"enabled": true,
"failover": true,
"updatedAt": "2026-05-26T00:26:53+09:00"
}
}
설정이 없으면 data: null 을 반환합니다.
카카오 설정 등록·수정 (upsert)
PUT /api/v1/tenant/kakao
가맹점이 자신의 카카오 채널과 발신프로필 키를 직접 등록/수정합니다. 이미 있으면 갱신, 없으면 INSERT.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| kakaoChId | string | 필수 | @ 로 시작 2~50자 (A-Z a-z 0-9 _ -) |
| senderKey | string | 필수 | 40자 소문자 16진수 (^[0-9a-f]{40}$) |
| enabled | boolean | 선택 | 기본 true. false 면 알림톡 발송 차단 |
| failover | boolean | 선택 | 미지정 시 기존값 유지. 신규 INSERT 는 기본 true. 이 설정이 SSoT — 발송 시 강제 적용되며 발송 요청의 failover 로는 덮어쓸 수 없습니다. |
PUT /api/v1/tenant/kakao
X-API-Key: your_api_key_here
Content-Type: application/json
{
"kakaoChId": "@myshop",
"senderKey": "2b5cc1be902831e85479985a97012e28e7c371c3",
"enabled": true,
"failover": true
}
템플릿 목록 조회
GET /api/v1/alimtalk/templates
등록된 알림톡 템플릿 목록을 조회합니다.
| 파라미터 | 설명 |
|---|---|
| status | 미지정·빈값·APPROVED → 승인된 것만 (기본). ALL → DELETED 제외 전체. 그 외 값은 해당 상태로 정확히 필터 (예: REGISTERED, INSPECTING, REJECTED, DELETED) |
GET /api/v1/alimtalk/templates?status=ALL
X-API-Key: your_api_key_here
응답 예시
{
"success": true,
"count": 1,
"templates": [
{
"template_id": 123,
"template_code": "WELCOME001",
"template_name": "회원가입 환영",
"content": "안녕하세요 #{name}님, #{serviceName}에 가입하신 것을 환영합니다.",
"buttons": null,
"variables": "[\"name\",\"serviceName\"]",
"status": "APPROVED",
"reject_reason": null,
"inspected_at": null,
"approved_at": "2026-05-25T23:17:38",
"created_at": "2026-05-25T23:14:55"
}
]
}
templates 이며 항목 필드는 snake_case(template_id, template_code, template_name, content, buttons, variables, status, reject_reason, inspected_at, approved_at, created_at)입니다. variables 는 JSON 배열 문자열로 저장된 원본이 반환됩니다.
템플릿 상세
GET /api/v1/alimtalk/templates/{id}
특정 템플릿의 상세 정보(본문·버튼·변수·상태·이력)를 조회합니다.
GET /api/v1/alimtalk/templates/123
X-API-Key: your_api_key_here
응답 예시
{
"success": true,
"template": {
"template_id": 123,
"template_code": "mpd_005",
"template_name": "이용권 만료 안내",
"content": "[문피디] 이용권 만료 안내\n\n#{이름}님, ...",
"buttons": "[{\"name\":\"연장하기\",\"type\":\"WL\",\"url_mobile\":\"...\",\"url_pc\":\"...\"}]",
"variables": "[\"이름\",\"기간\",\"이용권정보\"]",
"msg_type": "A",
"status": "APPROVED",
"reject_reason": null,
"draft_content": null,
"draft_status": null,
"inspected_at": null,
"approved_at": "2026-05-25T23:17:38",
"created_at": "2026-05-25T23:14:55",
"updated_at": "2026-05-25T23:17:38"
}
}
template 객체 필드도 snake_case 이며, 목록 항목보다 msg_type·draft_content·draft_status·updated_at 가 추가로 포함됩니다.
템플릿 등록
POST /api/v1/alimtalk/templates/register
새 알림톡 템플릿을 imsend 에 등록합니다. 등록 시 상태는 REGISTERED 이며, 발송 가능하게 하려면 별도로 검수 요청 → 승인 단계가 필요합니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| templateName | string | 필수 | 템플릿 표시 이름 |
| templateCode | string | 필수 | 가맹점이 지정. 발송 시 식별자. 가맹점 내 중복 불가 |
| content | string | 필수 | 메시지 본문. #{변수} 형태. 라인 끝 공백 자동 제거됨 |
| buttons | array | 선택 | 버튼 목록. 버튼 자동 전송 참조 |
| msgType | string | 선택 | 기본 A (알림톡) |
POST /api/v1/alimtalk/templates/register
X-API-Key: your_api_key_here
Content-Type: application/json
{
"templateName": "이용권 만료 안내",
"templateCode": "mpd_005",
"content": "[문피디] 이용권 만료 안내\n\n#{이름}님, 귀하의 이용권이 #{기간}일 후에 만료됩니다.\n중단 없는 서비스를 원하신다면, 이용권을 갱신해 주세요!\n\n#{이용권정보}",
"buttons": [
{"name":"연장하기","type":"WL","url_mobile":"http://moonpd.ai/Home/H40000/priceInfo","url_pc":"http://moonpd.ai/Home/H40000/priceInfo"}
]
}
응답 예시
{
"success": true,
"templateId": 123,
"templateCode": "mpd_005",
"status": "REGISTERED",
"variables": ["이름","기간","이용권정보"],
"message": "템플릿이 등록되었습니다. 검수 요청 후 카카오 심사가 진행됩니다."
}
content 의 #{변수} 는 imsend 가 자동 추출해 variables 응답 필드로 반환합니다. 본문은 카카오 비즈센터에 등록된 템플릿 본문과 글자 단위로 일치해야 발송 시 거부(K1108)되지 않습니다.
템플릿 수정
PUT /api/v1/alimtalk/templates/{id}
등록된 템플릿을 수정합니다. 현재 상태에 따라 동작이 다릅니다:
REGISTERED·REJECTED→ 본문·버튼 즉시 수정 후 상태REGISTERED로 초기화 (재검수 필요)APPROVED→ draft 컬럼에 저장. 기존 본문은 유지되어 발송에 계속 사용. 재검수 통과 시 draft 가 main 으로 승격INSPECTING→ 거부 (검수 진행 중)
PUT /api/v1/alimtalk/templates/123
X-API-Key: your_api_key_here
Content-Type: application/json
{
"templateName": "이용권 만료 안내 v2",
"content": "[문피디] 이용권 만료 안내\n\n...",
"buttons": [ ... ]
}
검수 요청
POST /api/v1/alimtalk/templates/{id}/inspect
등록·수정된 템플릿(REGISTERED·REJECTED)을 imsend 관리자 검수 요청 상태(INSPECTING)로 전환합니다. 승인 완료 시 카카오 비즈센터 등록·발송에 사용 가능한 상태(APPROVED)로 바뀝니다.
POST /api/v1/alimtalk/templates/123/inspect
X-API-Key: your_api_key_here
응답 예시
{
"success": true,
"templateId": 123,
"status": "INSPECTING",
"message": "검수 요청이 완료되었습니다. 심사 결과는 1~3영업일 내 반영됩니다."
}
INSPECTING 인 템플릿(또는 APPROVED 상태에서 draft 가 이미 재검수 요청됨)에 다시 호출하면 409 "이미 검수 요청된 템플릿입니다." / 409 "이미 재검수 요청된 상태입니다." 를 반환합니다. 존재하지 않는(또는 타 가맹점) 템플릿은 404 입니다.
INSPECTING 상태에서는 수정·삭제가 차단됩니다.
템플릿 삭제
DELETE /api/v1/alimtalk/templates/{id}
등록된 알림톡 템플릿을 삭제합니다. soft delete 방식으로 처리되어 발송 로그·감사 추적은 그대로 보존됩니다.
| 파라미터 | 설명 |
|---|---|
| id | 템플릿 ID (path) — 본인 가맹점 소유 템플릿만 삭제 가능 |
DELETE /api/v1/alimtalk/templates/123
X-API-Key: your_api_key_here
응답 예시
{
"success": true,
"templateId": 123,
"status": "DELETED",
"message": "템플릿이 삭제되었습니다."
}
•
INSPECTING(검수중) 상태의 템플릿은 삭제할 수 없습니다. 검수 완료 또는 반려 후 삭제해 주세요.• 이미
DELETED 상태의 템플릿을 다시 삭제하면 400 을 반환합니다.• 다른 가맹점의 템플릿 ID 로 호출하면 404 를 반환합니다.
status='DELETED' 로 마킹되어 발송 API(WHERE status='APPROVED')에서 자동 제외됩니다. 기본 목록(GET /templates) 및 status=ALL 조회에서도 숨겨지며, status=DELETED 로 명시 조회 시에만 노출됩니다.
알림톡 발송
POST /api/v1/alimtalk/send
승인된 템플릿(status='APPROVED')으로 알림톡을 발송합니다. senderKey·callback·버튼은 서버에서 자동 조회되므로 호출자는 보내지 않아도 됩니다.
요청 파라미터
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| phone | string | 필수 | 수신번호 (숫자만, 예: 01012345678) |
| templateCode | string | 필수 | 승인된 템플릿 코드. 코드 표기는 자유 (예: mpd_005, orderShipped001) |
| variables | object | 권장 | 템플릿 변수 치환 Map. 본문·버튼 URL 모두에 적용 |
| failover | boolean | 무시됨 | 요청값은 적용되지 않습니다. SMS 자동대체는 가맹점 설정(im_tenant_kakao.failover)이 항상 우선이며, 가맹점 관리화면에서만 변경됩니다. (요청에 보낸 값이 가맹점 설정과 다르면 무시되고 경고 로그가 남습니다) |
•
senderKey, kakaoChId — im_tenant_kakao 에서 조회•
callback (발신번호) — 시스템 기본값(0339116510)•
buttons — 템플릿의 buttons 컬럼에서 조회 후 KAKAO_SIDE_INFO 자동 변환
요청 예시
POST /api/v1/alimtalk/send
X-API-Key: your_api_key_here
Content-Type: application/json
{
"phone": "01012345678",
"templateCode": "mpd_005",
"variables": {
"이름": "홍길동",
"기간": "7",
"이용권정보": "프리미엄 이용권",
"상세주소": "Home/H40000/priceInfo"
}
}
응답 예시
{
"success": true,
"batchId": "1e383c58",
"mseq": 38949,
"type": "ALIMTALK",
"templateCode": "mpd_005",
"unitPrice": 10,
"maxChargeIfFailover": 35
}
batchId: 추적용 UUID 앞 8자mseq: GT Agent 큐의 MSEQ. 발송 이력 조회 시 사용unitPrice: 알림톡 단가. 가맹점·설정별로 다를 수 있음 (PriceResolver 가 tenant 단가표 → config → 기본값 순으로 해석; fallback 기본 10원)maxChargeIfFailover: failover 발동 시 청구 가능 최대 금액 (LMS 단가, fallback 기본 35원)
SMS 자동 대체 (Failover)
알림톡이 카카오 측에서 거부되거나 도달 실패한 경우 자동으로 SMS/LMS 로 대체 발송됩니다. 이 설정은 가맹점 단위로 관리되는 정책입니다 (im_tenant_kakao.failover, DB DEFAULT TRUE).
failover 값으로는 가맹점 설정을 덮어쓸 수 없습니다. 변경은 가맹점 관리화면의 'SMS 자동대체' 토글로만 합니다. (요청에 다른 값을 보내면 무시되고 서버에 경고 로그가 남습니다)
RESULT=604 로 실패 처리됩니다. 인증톡 등 의도적으로 대체발송을 끄려면 가맹점 설정을 OFF 로 두면 됩니다.
변수 치환
템플릿 본문과 버튼 URL 안의 #{변수명} 패턴을 variables 맵 값으로 치환합니다. 변수명은 카카오 비즈센터 등록본과 정확히 일치해야 합니다 (typo 포함).
// 템플릿 본문: "[문피디] #{이름}님, 귀하의 이용권이 #{기간}일 후에 만료됩니다."
// 템플릿 버튼 URL: "http://moonpd.ai/#{상세주소}"
// 요청 variables:
{
"이름": "홍길동",
"기간": "7",
"상세주소": "Home/H40000/priceInfo"
}
// 발송 본문: "[문피디] 홍길동님, 귀하의 이용권이 7일 후에 만료됩니다."
// 발송 URL: "http://moonpd.ai/Home/H40000/priceInfo"
#{...} 가 그대로 발송되어 카카오 측 본문 불일치(다운스트림 KAKAO_RESULT=1108 — API 응답에는 노출 안 됨)로 거부됩니다.
발송 이력
GET /api/v1/alimtalk/logs
알림톡 발송 이력을 조회합니다. (참고: 채널 무관 통합 이력은 /api/v1/sms/logs 사용 가능)
| 파라미터 | 설명 |
|---|---|
| page | 페이지 번호 (기본 1) |
| size | 페이지 크기 (기본 20) |
| status | DELIVERED·FAILED·PENDING·ALL 필터 |
| startDate·endDate | 기간 필터 (YYYY-MM-DD) |
GET /api/v1/alimtalk/logs?page=1&size=20&status=DELIVERED
X-API-Key: your_api_key_here
필드 상세 안내
templateCode
가맹점이 imsend 에 등록한 템플릿의 식별 코드입니다. 대소문자·하이픈·언더스코어 자유로 사용 가능 (예: mpd_005, orderShipped001, WELCOME-V1). 단 카카오 비즈센터에 등록된 코드와 정확히 일치해야 발송 시 매칭됩니다.
senderKey
카카오 비즈센터에서 발급받은 40자리 소문자 16진수 발신프로필 키입니다.
형식: ^[0-9a-f]{40}$
보안상 응답 시 일부 마스킹되어 반환됩니다 (예: 2b5cc1be***c371c3).
kakaoChId
@ 로 시작하는 카카오 채널 ID. 현재 정규식 ^@[A-Za-z0-9_\-]{1,49}$ 검증 (영문·숫자·하이픈·언더스코어). 한글 채널명은 self-service API 에서 거부되므로 관리자 직접 등록이 필요합니다.
content (템플릿 본문)
imsend 가 등록·수정 시 각 라인 끝의 공백·탭을 자동 제거합니다. 카카오 비즈센터 등록본과의 글자 단위 일치를 위함입니다.
에러 / K-코드 진단
알림톡 발송·템플릿 엔드포인트 에러 (/api/v1/alimtalk/*)
알림톡 발송·템플릿 관리 엔드포인트의 일반 에러 응답에는 code 필드가 없으며 HTTP 상태 코드와 message 로 오류를 전달합니다. 예외: 발송 시 카카오 설정 관련 두 종(409)만 code 를 포함합니다.
{
"success": false,
"message": "사람이 읽을 수 있는 설명"
}
| HTTP | code / message | 의미 |
|---|---|---|
| 401 | "유효하지 않은 API Key" | API 키 누락 또는 무효 (code 없음) |
| 400 | "phone 필수" / "templateCode 필수" | 발송 필수 필드 누락 |
| 400 | "유효하지 않은 전화번호" | 숫자만 남긴 phone 길이가 10자 미만 |
| 409 | KAKAO_NOT_CONFIGURED | 카카오 설정 미등록 또는 senderKey 비어있음. PUT /api/v1/tenant/kakao 먼저 호출 (code 포함) |
| 409 | KAKAO_DISABLED | 카카오 설정 비활성 (enabled=false) (code 포함) |
| 400 | "미승인 또는 존재하지 않는 템플릿입니다: ..." | templateCode 가 APPROVED 상태로 존재하지 않음 (발송) |
| 402 | "잔액 부족 ..." / "신용한도 초과 ..." | PREPAID: 잔액 부족 / POSTPAID: 신용한도 초과. 응답에 balance·available 필드 추가 |
| 409 | "이미 사용 중인 템플릿 코드입니다: ..." | 템플릿 등록 시 동일 가맹점 내 templateCode 중복 |
| 404 | "존재하지 않는 템플릿입니다." | 상세·수정·삭제·검수 시 본인 가맹점 소유 템플릿이 없음 |
| 409 | "이미 검수 요청된 템플릿입니다." 등 | 검수 요청 재호출 (INSPECTING / 재검수 진행중) |
| 400 | "검수중 상태에서는 ..." / "이미 삭제된 템플릿입니다." | INSPECTING 수정·삭제 차단, DELETED 재삭제 |
카카오 설정 엔드포인트 에러 (/api/v1/tenant/kakao)
카카오 설정 조회·등록(GET·PUT) 엔드포인트는 code 필드를 포함합니다.
{
"success": false,
"code": "ERROR_CODE",
"message": "사람이 읽을 수 있는 설명"
}
| HTTP | code | 의미 |
|---|---|---|
| 401 | INVALID_API_KEY | API 키 누락 또는 무효 |
| 400 | INVALID_JSON_BODY | 요청 본문이 유효한 JSON 아님 |
| 400 | MISSING_REQUIRED_FIELD | kakaoChId 또는 senderKey 누락 |
| 400 | INVALID_CHANNEL_ID | kakaoChId 형식 오류 (@로 시작 안함 등) |
| 400 | INVALID_SENDER_KEY | senderKey 형식 오류 (40자 소문자 hex 아님) |
| 500 | INTERNAL_ERROR | 서버 내부 오류 |
참고: 카카오 / 게이트웨이 다운스트림 코드
MSG_RESULT.KAKAO_RESULT 는 imsend 가 저장하지 않으며, /logs 의 result_code 는 GT Agent RESULT 값입니다. 아래 표는 운영자 디버깅 참고용이며 API 로는 조회할 수 없습니다.
| 코드 | TELECOM | 의미 | 대응 |
|---|---|---|---|
| (빈 값) | KKO | 알림톡 정상 도달 | — |
1102 | — | 발신프로필 일시중지/휴면 | 카카오 비즈센터에서 휴면 해제 |
1104 | SK/KT/LG | 발신프로필 카테고리 미지원 또는 휴면. 인증번호는 별도 발신프로필 필요 | SMS 폴백 도달. 인증번호는 SMS API 사용 권장 |
1108 | SK/KT/LG | 본문/버튼 등록본과 불일치 | 카카오 등록본과 imsend content/buttons 글자 단위 일치 확인 |
1119 | SK/KT/LG | 알림톡 수신거부/한도 | failover SMS 로 자동 대체 |
604 | KKO | 알림톡이 카카오에서 반려됐고 SMS 대체발송(failover)이 OFF 라 최종 실패 (/logs 의 result_code=604) | 가맹점 'SMS 자동대체' ON 시 카카오 반려돼도 SMS 자동 전환. 세부 반려 사유는 KAKAO_RESULT(1104/1108 등) 참고 |
913 | — | 카카오 알림톡 인증 실패 (SENDER_KEY / TEMPLATE_CODE / 발신프로필 확인) | senderKey·templateCode·발신프로필 상태 점검 |
docs/operations/TROUBLESHOOTING.md 와 ALIMTALK_BUTTONS_AND_TEMPLATE_FORMAT.md 에 상세히 정리되어 있습니다.