KAT Cloud로그인

채팅 API로 문자 보내기: /chat-room과 /chat 사용법

KAT Cloud 채팅 API로 문자를 보내는 방법입니다. POST /chat-room으로 고객 번호의 채팅방을 만들고 POST /chat으로 보내면 SMS·LMS가 자동으로 정해집니다. subject 필드, 응답 필드, 오류 처리까지 정리했습니다.

가이드KAT Cloud 팀9분 읽기
채팅 API로 문자 보내기: /chat-room과 /chat 사용법

KAT Cloud 채팅 API로 문자를 보내려면 POST /chat-room으로 내 채널과 고객 전화번호를 묶은 채팅방을 만들고, 받은 채팅방 ID로 POST /chat을 호출하면 됩니다. 메시지 타입은 KAT Cloud가 자동으로 정합니다. API 문서의 기준에 따르면 90바이트 이하 본문은 SMS, 90바이트를 넘거나 제목(subject)이 있으면 LMS, 이미지가 있으면 MMS로 나갑니다.

채팅 API의 구조: 채널, 채팅방, 채팅

KAT Cloud(캣클라우드)의 문자는 "누구에게 보내는가"보다 "어느 대화에 쓰는가"로 다룹니다. 그래서 수신 번호만 넣는 단건 발송 대신, 채널과 고객 번호의 조합인 채팅방을 먼저 정하고 그 안에 메시지를 씁니다.

리소스의미이 글에서 쓰는 값
그룹서비스 운영 단위. 생성 시 전화번호가 자동 발급됨GET /group의 id
채널그룹에 연결된 전화번호(070 기본)channelId, phoneNumber
채팅방채널과 고객 전화번호 조합의 대화 스레드POST /chat-room의 결과
채팅채팅방 안의 개별 메시지POST /chat 응답의 chatId

같은 채널과 같은 고객 번호는 항상 같은 채팅방을 씁니다. 그래서 고객이 답장하면 같은 채팅방에 이력이 이어지고, 내가 보낸 메시지와 고객 메시지를 한 스레드로 조회할 수 있습니다. 채팅 API는 비즈니스 요금제 그룹 또는 별도 허용된 그룹에서 쓸 수 있으며, 조건이 맞지 않으면 403 AU017이 반환됩니다. 범위 규칙은 API 문서의 사용 범위에 있습니다.

내 서버가 그룹 조회로 채널 ID를 얻고, 채팅방을 만든 뒤 채팅을 발송하면 KAT Cloud가 고객 휴대폰으로 문자를 전달하는 순서도
채팅방은 한 번 만들면 같은 고객에게 계속 재사용합니다.

1단계: 채널 ID 확인하기

채팅방을 만들려면 발신할 채널의 channelId가 필요합니다. GET /group은 API 키로 접근할 수 있는 그룹 목록을 돌려주고, 각 그룹에 phoneNumber와 channelId가 들어 있습니다.

Shell
export KAT_API_KEY="콘솔에서 발급받은 키"
BASE="https://studio-gateway.zerocall.kr"

curl -s "$BASE/group" -H "x-api-key: $KAT_API_KEY"
JSON
{
  "code": "0",
  "message": "Success",
  "result": [
    {
      "id": 1,
      "title": "매장A",
      "phoneNumber": "07012345678",
      "channelId": 100,
      "status": "ACTIVE",
      "recordingEnabled": true,
      "createdAt": "2026-01-15T09:00:00.000Z"
    }
  ]
}

channelId는 자주 바뀌는 값이 아니므로 설정 파일이나 DB에 저장해 두고 씁니다. 그룹이 여러 개라면 매장이나 서비스별로 어느 채널에서 보낼지 미리 정해 둡니다.

2단계: 채팅방 만들기

POST /chat-room에 channelId와 고객 phoneNumber를 보냅니다. 전화번호는 숫자만, 0으로 시작하는 형식이어야 합니다. 응답 result에는 채팅방 ID 문자열이 들어 있습니다.

Shell
curl -s -X POST "$BASE/chat-room" \
  -H "x-api-key: $KAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channelId": 100, "phoneNumber": "01098765432"}'
# {"code":"0","message":"Success","result":"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"}

이 API는 같은 채널과 전화번호 조합의 채팅방이 이미 있으면 새로 만들지 않고 기존 채팅방 ID를 돌려줍니다. 따라서 보낼 때마다 호출해도 채팅방이 늘어나지 않습니다. 호출 수를 줄이고 싶다면 고객 번호와 채팅방 ID를 묶어 캐시해 둡니다.

3단계: 메시지 보내기

POST /chat의 필수 필드는 chatRoomId와 content 두 개입니다. 선택 필드로 subject(LMS 제목), imageList(MMS 이미지), externalMessageId(중복 방지용 외부 메시지 ID)가 있습니다.

Shell
curl -s -X POST "$BASE/chat" \
  -H "x-api-key: $KAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"chatRoomId": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", "content": "예약 확인되었습니다.", "externalMessageId": "ext-msg-001"}'

응답에서 주로 보는 필드는 다음과 같습니다.

필드설명
chatId메시지 ID. 발송 결과를 맞춰 볼 때 쓰는 키
sendPhoneNumber, recvPhoneNumber발신 번호(내 채널), 수신 번호(고객)
sendStatus발송 상태. 처음에는 PENDING, 이후 SENT 또는 FAILED
chatType자동으로 정해진 메시지 타입(SMS, LMS, MMS)
resultStatus, resultMessage결과 코드와 메시지. 발송 완료 전에는 null

Node.js 18 이상에서는 내장 fetch로 두 호출을 묶은 함수를 만들 수 있습니다.

JavaScript
// send-text.js — Node.js 18+
const BASE_URL = 'https://studio-gateway.zerocall.kr';
const API_KEY = process.env.KAT_API_KEY;

async function kat(method, path, body) {
  const res = await fetch(`${BASE_URL}${path}`, {
    method,
    headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
    body: body ? JSON.stringify(body) : undefined,
  });
  const json = await res.json().catch(() => ({}));
  if (!res.ok || json.code !== '0') {
    // 에러 형식: { status, code, message }
    throw new Error(`${method} ${path} 실패: ${res.status} ${json.code} ${json.message}`);
  }
  return json.result;
}

const toDigits = (phone) => String(phone).replace(/\D/g, ''); // 010-9876-5432 → 01098765432

async function sendText({ channelId, to, content, subject, externalMessageId }) {
  const chatRoomId = await kat('POST', '/chat-room', { channelId, phoneNumber: toDigits(to) });
  return kat('POST', '/chat', { chatRoomId, content, subject, externalMessageId });
}

(async () => {
  const [group] = await kat('GET', '/group');

  const sms = await sendText({
    channelId: group.channelId,
    to: '010-9876-5432',
    content: '예약 확인되었습니다.',
  });
  console.log(sms.chatId, sms.chatType, sms.sendStatus); // ... SMS PENDING

  const lms = await sendText({
    channelId: group.channelId,
    to: '010-9876-5432',
    subject: '예약 안내',
    content: '내일 오후 3시 예약이 확정되었습니다. 변경이 필요하면 이 번호로 답장해 주세요.',
    externalMessageId: 'booking-20261030-0001',
  });
  console.log(lms.chatId, lms.chatType); // ... LMS
})();

JSON.stringify는 값이 undefined인 필드를 빼고 직렬화하므로, subject를 넘기지 않으면 요청에도 들어가지 않습니다. Python이라면 같은 흐름을 이렇게 씁니다.

Python
import os
import re

import requests

BASE_URL = "https://studio-gateway.zerocall.kr"
HEADERS = {"x-api-key": os.environ["KAT_API_KEY"], "Content-Type": "application/json"}


def kat(method: str, path: str, body: dict | None = None):
    r = requests.request(method, f"{BASE_URL}{path}", headers=HEADERS, json=body, timeout=10)
    data = r.json()
    if r.status_code >= 400 or data.get("code") != "0":
        raise RuntimeError(f"{r.status_code} {data.get('code')} {data.get('message')}")
    return data["result"]


def send_text(channel_id: int, to: str, content: str, subject: str | None = None) -> dict:
    room_id = kat("POST", "/chat-room", {"channelId": channel_id, "phoneNumber": re.sub(r"\D", "", to)})
    body = {"chatRoomId": room_id, "content": content}
    if subject:
        body["subject"] = subject
    return kat("POST", "/chat", body)

subject 필드와 SMS·LMS 자동 결정

채팅 API에는 메시지 타입을 고르는 필드가 없습니다. KAT Cloud가 본문 길이, 제목, 이미지 여부를 보고 정합니다. API 문서에 적힌 자동 결정 기준은 다음과 같습니다.

  • SMS: 본문 90바이트 이하
  • LMS: 본문 90바이트 초과, 또는 제목(subject) 포함
  • MMS: imageList에 값이 1개 이상

여기서 놓치기 쉬운 점이 subject입니다. 본문이 짧아도 제목을 넣으면 LMS로 나갑니다. KAT Cloud 요금표 기준 초과분 1구간 단가는 SMS 10원, LMS 32원(부가세 별도)이므로, 짧은 알림에 습관처럼 제목을 붙이면 비용이 세 배 넘게 늘어납니다. 제목은 긴 공지처럼 받는 사람이 제목을 보고 내용을 가늠해야 할 때만 넣는 것이 좋습니다. 요금표는 요금 안내에서 확인할 수 있습니다.

SMS, LMS, MMS가 각각 본문 길이, 제목 포함 여부, 이미지 포함 여부로 자동 결정되는 기준과 초과분 1구간 단가를 비교한 표
요금은 부가세 별도, 초과분 1구간 단가 기준입니다.

90바이트는 일반적으로 영문·숫자 1바이트, 한글 2바이트로 계산하므로 한글만 쓰면 약 45자입니다. 길이 제한의 기준으로는 문자 발송 API(/message/send) 문서가 본문 최대 2,000자, 제목 최대 64자로 안내하고 있으니 채팅 API에서도 이 범위 안에서 쓰는 것이 안전합니다. 이미지를 붙이는 방법은 이미지 문자(MMS) 보내기에서, 문자 종류별 차이는 SMS·LMS·MMS·알림톡 차이에서 다룹니다.

발송 후 확인과 오류 처리

POST /chat이 성공했다는 것은 발송 요청이 접수됐다는 뜻이고, 고객에게 전달됐다는 뜻은 아닙니다. 응답의 sendStatus는 PENDING에서 시작해 SENT 또는 FAILED로 바뀌고, 최종 전달 여부는 resultStatus 결과 코드로 판단합니다. SMS는 4100, LMS·MMS는 6600이 성공 코드입니다. 상태는 GET /chat?chatRoomId=...의 대화 조회로 확인하거나 SEND_RESULT 웹훅으로 받습니다. 결과 코드를 다루는 방법은 문자 발송 결과 확인 글에 정리했습니다.

요청 단계에서 만나는 오류는 대부분 다음 셋입니다.

  • 401: API 키가 없거나 잘못됨. x-api-key 헤더 값을 확인합니다.
  • 403 AU017: 비즈니스 요금제 그룹이나 별도 허용된 그룹이 아님. 키에 연결된 그룹을 확인합니다.
  • 429: Rate Limit(60초당 1,200회) 초과. 대량 발송은 큐에서 속도를 조절하고 잠시 뒤 재시도합니다. 재시도 설계는 API 에러 처리와 Rate Limit 대응 글을 참고합니다.

참고로 POST /message/send도 문자를 보낼 수 있지만 문서에 Deprecated로 표시되어 있고, 새 연동에는 채팅 API가 권장됩니다.

항목채팅 API(/chat-room → /chat)POST /message/send
문서상 상태새 연동에 권장Deprecated
사용 범위비즈니스 요금제 그룹 또는 허용 그룹모든 사용자
대화 관리채팅방 단위로 이력 누적수신 번호 단위 단건 발송
상태 확인GET /chat, SEND_RESULT 웹훅GET /message/send-result/{chatId}, SEND_RESULT 웹훅

필드별 상세는 채팅방 API 문서와 채팅 API 문서에 있습니다.

자주 묻는 질문

채팅방은 메시지를 보낼 때마다 새로 만들어야 하나요?

KAT Cloud의 POST /chat-room은 같은 채널과 고객 전화번호 조합의 채팅방이 이미 있으면 기존 채팅방 ID를 그대로 돌려줍니다. 그래서 보낼 때마다 호출해도 채팅방이 늘어나지 않고, 한 고객과 주고받은 메시지는 같은 채팅방에 계속 쌓입니다.

subject를 넣으면 요금이 달라지나요?

KAT Cloud 채팅 API에서 subject를 넣으면 본문이 90바이트 이하라도 LMS로 발송됩니다. LMS는 SMS보다 단가가 높으므로(초과분 1구간 기준 SMS 10원, LMS 32원, 부가세 별도), 짧은 알림에는 제목을 넣지 않는 것이 비용 면에서 유리합니다.

개인 요금제에서도 채팅 API를 쓸 수 있나요?

KAT Cloud 채팅 API는 비즈니스 요금제 그룹 또는 별도 허용된 그룹에서만 쓸 수 있고, 조건이 맞지 않으면 403 AU017이 반환됩니다. 문자 발신 API인 POST /message/send와 GET /message/send-result/{chatId}는 모든 사용자가 쓸 수 있지만, 문서상 Deprecated이므로 새로 만드는 연동이라면 채팅 API를 기준으로 설계하는 것이 좋습니다.

  • #문자 발송
  • #채팅 API
  • #SMS
  • #LMS

Get started

만든 AI에게 전화번호를 주세요.

070 번호 발급, SIP 직접 연결, 음성 AI 모델 연결, 문자·웹훅까지 API 하나로. 월 10,000원부터.