Studio API
ZeroCall Studio API를 사용하여 문자 메시지 발송, 수신 관리, 통화 기록 조회, 그룹 관리 등의 기능을 외부 시스템과 연동할 수 있습니다.
Base URL
https://studio-gateway.zerocall.krRate Limit
1,200 requests / 60초| 항목 | 값 |
|---|---|
| 인증 방식 | API Key (x-api-key 헤더) |
| Content-Type | application/json |
| 문자 인코딩 | UTF-8 |
공통 성공 응답
성공 응답은 기본적으로 code,message,result 구조를 사용합니다. 아래 API 예시에서는 가독성을 위해 result 값만 표시할 수 있습니다.
{
"code": "0",
"message": "Success",
"result": {
"example": "value"
}
}인증
모든 API 요청에는 x-api-key 헤더가 필요합니다. API Key는 ZeroCall 콘솔에서 발급받을 수 있습니다.
API Key 사용 예시
콘솔에서 발급받은 API Key 전체 문자열을 x-api-key 헤더에 그대로 넣어 사용하세요.
x-api-key: {API_KEY}인증 확인
API Key가 유효한지 확인합니다.
/auth-check// Response
{
"apiKeyId": 123,
"userId": 456,
"name": "My API Key",
"groupIdList": [1, 2, 3]
}그룹 관리
그룹은 전화번호와 연결된 서비스 단위입니다. 그룹을 생성하면 전화번호가 자동 발급됩니다.
그룹 목록 조회
API Key로 접근 가능한 그룹 목록을 조회합니다.
/group// Response
[
{
"id": 1,
"title": "매장A",
"phoneNumber": "07012345678",
"channelId": 100,
"status": "ACTIVE",
"createdAt": "2024-01-15T09:00:00.000Z"
}
]그룹 생성
새 그룹을 생성하고 전화번호를 발급받습니다.
/groupRequest Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| phoneNumber | string | 선택 | 특정 번호 지정 (미입력 시 랜덤 발급) |
| groupTitle | string | 선택 | 그룹 이름 (미입력 시 자동 생성) |
// Request
{
"groupTitle": "신규 매장",
"phoneNumber": "07098765432"
}
// Response
{
"groupId": 123
}그룹 삭제
그룹을 삭제하고 전화번호를 반납합니다.
/group/{groupId}| 파라미터 | 타입 | 설명 |
|---|---|---|
| groupId | number | 삭제할 그룹 ID |
성공 시 204 No Content 응답
전화번호 풀
발급 가능한 전화번호를 확인합니다.
/phone-number-pool/available// Response
{
"isAvailable": true,
"phoneNumber": "07012345678"
}| 필드 | 타입 | 설명 |
|---|---|---|
| isAvailable | boolean | 발급 가능 여부 |
| phoneNumber | string | 샘플 번호 (1개만 반환) |
메시지 발송
SMS/LMS/MMS 메시지를 발송합니다. 메시지 길이, 제목, 이미지 첨부 여부에 따라 타입이 자동 결정됩니다.
MMS 이미지 업로드
MMS 발송 전에 이미지 파일을 업로드합니다. 반환된 key를 /message/send의 imageList에 넣어 사용합니다.
/message/media/uploadRequest Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| files | File[] | 필수 | multipart/form-data 파일 목록. 최대 3개 |
응답의 result.urls에는 업로드에 성공한 파일의 key 목록이 들어갑니다. 업로드에 실패한 파일은 이 배열에 포함되지 않습니다.
curl -X POST \
"https://studio-gateway.zerocall.kr/message/media/upload" \
-H "accept: */*" \
-H "x-api-key: {API_KEY}" \
-H "Content-Type: multipart/form-data" \
-F "files=@sample1.png;type=image/png" \
-F "files=@sample2.jpg;type=image/jpg"// Response result
{
"urls": [
"chat-media/123456/1713776400000-abcd123.jpg",
"chat-media/123456/1713776400001-efgh456.jpg"
]
}이미지 파일 조건
- • 한 번에 최대 3개까지 업로드할 수 있습니다.
- • 이미지 파일은 업로드 후 JPG로 자동 변환되고, 가능하면 MMS 규격에 맞게 축소됩니다.
- • 권장 조건은 최대 1280px, 300KB 이하입니다.
- • 자동 축소 후에도 300KB 이하로 충분히 줄지 않는 이미지가 있을 수 있으니, 가능하면 권장 크기에 맞춰 업로드해 주세요.
- • 일부 이미지는 자동 축소 후에도 MMS 규격을 만족하지 못해 전송이 실패할 수 있습니다.
- • 반환된 key를 그대로 `/message/send`의 `imageList`에 넣으면 MMS로 발송됩니다.
메시지 전송
/message/sendRequest Body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| toPhoneNumber | string | 필수 | 수신자 전화번호 (숫자만) |
| content | string | 필수 | 메시지 내용 (최대 2,000자) |
| fromPhoneNumber | string | 선택 | 발신 번호 (숫자만, 내 그룹 번호만 가능) |
| subject | string | 선택 | LMS 제목 (최대 64자) |
| imageList | string[] | 선택 | 이미지/동영상 목록 (S3 key 또는 URL). 값이 있으면 MMS로 발송 |
이 API의 result에는 32자 chatId 문자열이 들어갑니다. 이 값은 이후 SEND_RESULT 웹훅의 data.chatId와 매칭됩니다.
// Request
{
"toPhoneNumber": "01098765432",
"content": "안녕하세요. 예약이 확정되었습니다.",
"fromPhoneNumber": "07012345678",
"subject": "예약 확정 안내"
}
// Response result
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"메시지 타입 자동 결정
- • SMS - 90바이트 이하
- • LMS - 90바이트 초과 또는 제목 포함
- • MMS - imageList에 값이 1개 이상 존재
result에 들어 있는 chatId는 웹훅의 SEND_RESULT 이벤트에서 발송 결과를 식별하는 데 사용됩니다.
메시지 발송 결과 조회
/message/send에서 반환된 chatId로 최종 발송 결과를 조회합니다. 웹훅을 사용하지 않거나, 웹훅 수신 전 상태를 직접 확인해야 할 때 사용할 수 있습니다.
/message/send-result/{chatId}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| chatId | string | 필수 | /message/send 응답으로 받은 메시지 ID (32자) |
이 API는 SEND_RESULT 웹훅과 동일한 최종 결과 정보를 조회용으로 제공합니다. 성공 여부는 resultStatus로 판단하세요.
curl -X GET \
"https://studio-gateway.zerocall.kr/message/send-result/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "x-api-key: zpa.123.your-secret-key"// Response result
{
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"content": "안녕하세요. 예약이 확정되었습니다.",
"subject": "예약 확정 안내",
"imageList": [],
"externalMessageId": "biz_1234567890",
"fromPhoneNumber": "07012345678",
"toPhoneNumber": "01098765432",
"sendStatus": "SUCCESS",
"chatType": "SMS",
"resultStatus": "4100",
"resultMessage": "전달",
"createdAt": "2024-03-05T10:30:05.000Z"
}필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
| id | string | 메시지 ID (32자) |
| content | string | 메시지 내용 |
| subject | string | 제목. 없으면 필드가 생략될 수 있음 |
| imageList | string[] | 이미지 URL 목록 (MMS인 경우) |
| externalMessageId | string | 메시지 사업자 측 외부 메시지 ID |
| fromPhoneNumber | string | 발신 번호 |
| toPhoneNumber | string | 수신 번호 |
| sendStatus | SUCCESS | FAILED | ZeroCall이 메시지 사업자에게 요청을 넘긴 상태 |
| chatType | SMS | LMS | MMS | RCS | KAKAO | 메시지 타입 |
| resultStatus | string | 최종 전달 결과 코드 |
| resultMessage | string | 결과 코드의 한글 메시지 |
| createdAt | string | 메시지 생성 시각 (ISO 8601) |
최종 발송 성공 여부는 resultStatus가 4100,6600,7000 중 하나인지로 판단하세요.
/message/send 요청 실패 시 에러 코드
| HTTP | 코드 | 설명 |
|---|---|---|
| 400 | Validation Error | 요청 형식 오류. 전화번호 형식, 본문 길이, 제목 길이, imageList 항목 길이 등을 확인하세요. |
| 404 | CH001 | 발신에 사용할 채널을 찾을 수 없습니다. |
| 503 | CH002 | 문자 발송에 실패했습니다. |
통화 기록
그룹 단위 통화 기록 목록과 단건 상세 정보를 조회할 수 있습니다.
통화 기록 목록 조회
오프셋 기반 페이지네이션으로 통화 기록을 조회합니다.
/call-historyQuery Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| groupId | number | 필수 | 그룹 ID |
| channelId | number | 선택 | 채널 ID (미입력 시 그룹 전체) |
| offset | number | 선택 | 시작 인덱스 (기본값: 0) |
| limit | number | 선택 | 조회 개수 (기본값: 20, 최대: 100) |
GET /call-history?groupId=1&offset=0&limit=20// Response
{
"data": [
{
"callHistoryId": "8f3f8fd9-7ab8-4a26-b523-4f8eb7d38b85",
"fromNumber": "01012345678",
"toNumber": "07012345678",
"isInbound": true,
"status": "ANSWERED",
"tag": "AI_TO_DIRECT",
"duration": 96,
"summary": "예약 변경 요청 후 담당자 연결하여 상담 완료",
"sttAI": [
{ "role": "agent", "text": "안녕하세요. 제로콜입니다. 무엇을 도와드릴까요?", "timestamp": 1.2 },
{ "role": "customer", "text": "내일 예약 시간을 변경하고 싶은데요.", "timestamp": 4.3 },
{ "role": "agent", "text": "네, 예약 변경 도와드리겠습니다. 원하시는 시간대가 있으신가요?", "timestamp": 7.1 },
{ "role": "customer", "text": "오후 3시로 바꿀 수 있을까요? 그리고 담당자랑 직접 통화하고 싶어요.", "timestamp": 11.5 },
{ "role": "agent", "text": "네, 담당자에게 연결해드리겠습니다. 잠시만 기다려주세요.", "timestamp": 16.2 }
],
"sttDirect": [
{ "role": "agent", "text": "안녕하세요, 담당자 김민수입니다.", "timestamp": 1.2 },
{ "role": "customer", "text": "네, 내일 오후 3시로 예약 변경하고 싶어서요.", "timestamp": 4.5 },
{ "role": "agent", "text": "확인해보겠습니다. 오후 3시 자리 있네요. 변경 도와드릴게요.", "timestamp": 9.0 },
{ "role": "customer", "text": "감사합니다.", "timestamp": 14.3 }
],
"recordingAI": {
"url": "https://storage.example.com/recording-ai.wav",
"expiresAt": "2026-03-12T03:40:00.000Z",
"contentLength": 1234567,
"contentType": "audio/wav"
},
"recordingDirect": {
"url": "https://storage.example.com/recording-direct.wav",
"expiresAt": "2026-03-12T03:40:00.000Z",
"contentLength": 2345678,
"contentType": "audio/wav"
},
"channelId": 100,
"groupId": 1,
"createdAt": "2026-03-12T02:40:00.000Z"
}
],
"total": 231,
"offset": 0,
"limit": 20
}통화 기록 상세 조회
특정 통화 기록 ID 기준으로 상세 정보를 조회합니다.
/call-history/{callHistoryId}Path Parameters
| 파라미터 | 타입 | 설명 |
|---|---|---|
| callHistoryId | string | 통화 기록 ID |
Query Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| groupId | number | 필수 | 그룹 ID |
GET /call-history/{callHistoryId}?groupId=1status / tag 값
| 필드 | 가능 값 |
|---|---|
| status | ANSWERED`, `MISSED`, `REJECTED`, `UNKNOWN |
| tag | AI`, `DIRECT`, `AI_TO_DIRECT`, `UNKNOWN |
녹음 파일 (recordingAI / recordingDirect)
응답 완료된 통화(status: ANSWERED)의 경우, 통화 유형에 따라 녹음 파일 정보가 포함됩니다.
| 필드 | 타입 | 설명 |
|---|---|---|
| url | string | S3 Presigned URL (재생/다운로드용) |
| expiresAt | string | URL 만료 시각 (ISO 8601, 1시간) |
| contentLength | number | 파일 크기 (bytes) |
| contentType | string | Content-Type (audio/wav) |
녹음 파일 URL은 1시간 후 만료됩니다. 파일을 보관해야 하는 경우, URL 수신 후 다운로드하여 별도 저장소에 저장하시기 바랍니다.
웹훅
이벤트 발생 시 등록된 URL로 HTTP POST 요청을 전송합니다.
| 이벤트 | 설명 |
|---|---|
MESSAGE_RECEIVED | 고객으로부터 메시지 수신 |
SEND_RESULT | 메시지 발송 결과 수신 |
CALL_COMPLETED | 통화 종료 후 분석 결과 수신 |
MESSAGE_RECEIVED
고객으로부터 메시지를 수신했을 때 전송됩니다.
{
"eventType": "MESSAGE_RECEIVED",
"timestamp": "2024-03-05T10:30:00.000Z",
"data": {
"chatId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"chatRoomId": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"groupId": 1,
"channelId": 100,
"phoneNumber": "07012345678",
"senderPhoneNumber": "01098765432",
"content": "안녕하세요, 예약 문의드립니다.",
"imageList": [],
"receivedAt": "2024-03-05T10:30:00.000Z"
}
}필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
| data.chatId | string | 메시지 고유 ID (32자) |
| data.chatRoomId | string | 채팅방 ID (30자) |
| data.groupId | number | 그룹 ID |
| data.channelId | number | 채널 ID |
| data.phoneNumber | string | 수신 번호 (ZeroCall 번호) |
| data.senderPhoneNumber | string | 발신자 번호 (고객) |
| data.content | string | 메시지 내용 |
| data.subject | string | 제목. 없으면 필드가 생략될 수 있음 |
| data.imageList | string[] | 이미지 URL (MMS) |
| data.receivedAt | string | 수신 시각 (ISO 8601) |
이미지 URL 만료 안내
imageList에 포함된 이미지 URL은 일정 시간이 지나면 만료됩니다. 이미지를 보관해야 하는 경우, 웹훅 수신 즉시 다운로드하여 별도 저장소에 저장하시기 바랍니다.
SEND_RESULT
메시지 사업자가 최종 발송 결과를 회신했을 때 전송됩니다.
data.chatId는/message/send의result로 받은 32자 문자열과 동일합니다.
아래 값들은 /message/send의result에는 포함되지 않고,SEND_RESULT 웹훅의data 안에서 내려옵니다.
{
"eventType": "SEND_RESULT",
"timestamp": "2024-03-05T10:30:05.000Z",
"data": {
"chatId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"chatRoomId": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"groupId": 1,
"channelId": 100,
"sendPhoneNumber": "07012345678",
"recvPhoneNumber": "01098765432",
"content": "예약이 확정되었습니다.",
"chatType": "SMS",
"sendStatus": "SUCCESS",
"resultStatus": "4100",
"resultMessage": "전달",
"sentAt": "2024-03-05T10:30:05.000Z"
}
}필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
| data.chatId | string | 메시지 고유 ID (32자) |
| data.chatRoomId | string | 채팅방 ID (30자) |
| data.groupId | number | 그룹 ID |
| data.channelId | number | 채널 ID |
| data.sendPhoneNumber | string | 발신 번호 |
| data.recvPhoneNumber | string | 수신 번호 |
| data.content | string | 메시지 내용 |
| data.chatType | SMS | LMS | MMS | RCS | KAKAO | 메시지 타입 |
| data.sendStatus | SUCCESS | FAILED | ZeroCall이 메시지 사업자에게 요청을 넘긴 상태 |
| data.resultStatus | string | 최종 전달 결과 코드 |
| data.resultMessage | string | 결과 코드의 한글 메시지 |
| data.sentAt | string | 메시지 생성 시각 (ISO 8601) |
sendStatus 값
| 값 | 설명 |
|---|---|
SUCCESS | ZeroCall이 메시지 사업자에게 요청을 넘김 |
FAILED | 메시지 사업자 요청 단계에서 실패 |
chatType 값
| 값 | 설명 |
|---|---|
SMS | 단문 메시지 |
LMS | 장문 메시지 |
MMS | 멀티미디어 메시지 |
RCS | RCS 메시지 |
KAKAO | 카카오톡 메시지 |
최종 발송 결과 성공 코드
| 구분 | 성공 코드 | 설명 |
|---|---|---|
| SMS | 4100 | 전달 |
| LMS/MMS | 6600 | 전달 |
| 카카오 | 7000 | 전달 |
정리하면 /message/send는 즉시 code: "0",message: "Success", 그리고 result에 32자chatId를 반환하고, 최종 성공 여부는 나중에 오는 SEND_RESULT 웹훅의 resultStatus가4100,6600,7000 중 하나인지로 판단하세요.
CALL_COMPLETED
통화 종료 후 STT/요약 분석이 완료되면 전송됩니다.
{
"eventType": "CALL_COMPLETED",
"timestamp": "2026-03-12T02:45:30.000Z",
"data": {
"callHistoryId": "8f3f8fd9-7ab8-4a26-b523-4f8eb7d38b85",
"groupId": 1,
"channelId": 100,
"fromNumber": "01012345678",
"toNumber": "07012345678",
"isInbound": true,
"status": "ANSWERED",
"tag": "AI_TO_DIRECT",
"duration": 96,
"summary": "예약 변경 요청을 접수하고 변경 가능한 시간대를 안내함",
"sttAI": [
{ "role": "agent", "text": "안녕하세요. 제로콜입니다.", "timestamp": 1.2 }
],
"sttDirect": [
{ "role": "customer", "text": "직원 연결 부탁드립니다.", "timestamp": 30.1 }
],
"recordingUrl": "https://storage.example.com/recording.wav",
"startedAt": "2026-03-12T02:40:00.000Z",
"completedAt": "2026-03-12T02:41:36.000Z"
}
}필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
| data.callHistoryId | string | 통화 기록 ID |
| data.groupId | number | 그룹 ID |
| data.channelId | number | 채널 ID |
| data.fromNumber | string | 발신 전화번호 |
| data.toNumber | string | 수신 전화번호 |
| data.isInbound | boolean | 수신 통화 여부 |
| data.status | string | 통화 상태 (`ANSWERED`/`MISSED`/`REJECTED`/`UNKNOWN`) |
| data.tag | string | 통화 태그 (`AI`/`DIRECT`/`AI_TO_DIRECT`/`UNKNOWN`) |
| data.duration | number | 통화 시간(초) |
| data.summary | string | 통화 요약 |
| data.sttAI | object[] | AI 구간 STT (timestamp: 초 단위, 소수점 포함) |
| data.sttDirect | object[] | Direct 구간 STT (timestamp: 초 단위, 소수점 포함) |
| data.recordingUrl | string | 녹음 파일 URL (선택) |
| data.startedAt | string | 통화 시작 시각 (ISO 8601) |
| data.completedAt | string | 통화 완료 시각 (ISO 8601) |
웹훅 처리 권장사항
- • Timeout: 10초
- • HTTP 2xx 응답 시 성공 처리
- • 비동기 처리 후 즉시 응답 권장
에러 처리
API 요청 실패 시 아래 형식으로 에러가 반환됩니다.
{
"status": 401,
"code": "AU002",
"message": "올바르지 않은 토큰입니다."
}HTTP 상태 코드
| 코드 | 설명 |
|---|---|
| 400 | 잘못된 요청 (파라미터 오류) |
| 401 | 인증 실패 (API Key 없음/무효) |
| 403 | 권한 없음 (그룹 접근 불가) |
| 404 | 리소스 없음 |
| 429 | Rate Limit 초과 |
| 500 | 서버 오류 |
메시지 발송 결과 코드
`resultStatus`는 결과 코드이며, `resultMessage`는 해당 코드의 한글 메시지입니다. 성공 판정은 아래 성공 코드 기준으로 처리하세요.
성공 판정 규칙
| 항목 | 값 |
|---|---|
| successCodes | 4100, 6600, 7000 |
| successMessage | 전달 |
SMS 결과 코드
| resultStatus | resultMessage |
|---|---|
4100 | 전달 |
4400 | 음영 지역 |
4401 | 단말기 전원 꺼짐 |
4402 | 단말기 메시지 저장 초과 |
4403 | 메시지 삭제 됨 |
4404 | 가입자 위치 정보 없음 |
4405 | 단말기 BUSY |
4410 | 잘못된 번호 |
4411 | NPDB 에러 |
4412 | 착신거절 |
4420 | 기타에러 |
4430 | 스팸 |
4431 | 발송 제한 수신거부(스팸) |
LMS/MMS 결과 코드
| resultStatus | resultMessage |
|---|---|
6600 | 전달 |
6601 | 폰 꺼짐 |
6602 | 음영지역 |
6603 | 단말기 문제 |
6604 | 메시지 삭제 됨 |
6605 | 단말기 메시지 저장 개수 초과 |
6610 | 잘못된 번호 |
6611 | 스팸 차단 |
6612 | Spam Content |
6613 | 형식불일치 |
6614 | MMS 미가입자 |
6615 | 기타에러 |
6616 | 통신사 시스템 에러 |
6617 | FDS 차단 |
6618 | 발송불가 시간 |
6619 | MESSAGE RATE EXCEED |
6620 | 서비스 불가 단말 |
6621 | 헤더오류 |
6622 | 잘못된 수신번호 |
6623 | 메시지 길이 오류 |
6624 | 중복메시지 |
6625 | 스팸 차단 |
6626 | 첨부파일 문제 |
6627 | 미지원 단말 |
6628 | 이통사 Timeout |
카카오(알림톡/친구톡) 결과 코드
| resultStatus | resultMessage |
|---|---|
7000 | 전달 |
7001 | 발송 권한 없음 |
7002 | 메시지 형식 오류 |
7003 | 메시지 내용 오류 |
7004 | 메시지 길이 초과 |
7005 | 메시지 버튼 오류 |
7006 | 수신자 번호 오류 |
7007 | 발신프로필키 오류 |
7008 | 발신프로필 접근 권한 없음 |
7009 | 발신프로필 상태 오류 |
7010 | 템플릿 없음 |
7011 | 등록되지 않은 템플릿 |
7012 | 검수 중인 템플릿 |
7013 | 반려된 템플릿 |
7014 | 승인되지 않은 템플릿 |
7015 | 휴면 템플릿 |
7016 | 삭제된 템플릿 |
7017 | 차단된 수신자 |
7018 | 수신자 스팸차단 |
7019 | 수신자 번호 없음 |
7020 | 대체문자 발송 실패 |
7021 | 대체문자 형식 오류 |
7022 | 친구톡 발송 불가 시간 |
7023 | 친구톡 템플릿 없음 |
7999 | 기타 오류 |
코드 예시
cURL
# 그룹 목록 조회
curl -X GET "https://studio-gateway.zerocall.kr/group" \
-H "x-api-key: zpa.123.your-secret-key"
# 메시지 발송
curl -X POST "https://studio-gateway.zerocall.kr/message/send" \
-H "x-api-key: zpa.123.your-secret-key" \
-H "Content-Type: application/json" \
-d '{
"toPhoneNumber": "01098765432",
"content": "안녕하세요. 예약이 확정되었습니다."
}'
# 통화 기록 조회
curl -X GET "https://studio-gateway.zerocall.kr/call-history?groupId=1&offset=0&limit=20" \
-H "x-api-key: zpa.123.your-secret-key"JavaScript
const axios = require('axios');
const client = axios.create({
baseURL: 'https://studio-gateway.zerocall.kr',
headers: {
'x-api-key': 'zpa.123.your-secret-key',
'Content-Type': 'application/json'
}
});
// 메시지 발송
async function sendMessage(to, content) {
const response = await client.post('/message/send', {
toPhoneNumber: to,
content: content
});
return response.data.result; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
// 그룹 목록 조회
async function getGroups() {
const response = await client.get('/group');
return response.data;
}
// 통화 기록 조회
async function getCallHistories(groupId) {
const response = await client.get('/call-history', {
params: { groupId, offset: 0, limit: 20 }
});
return response.data;
}Python
import requests
BASE_URL = 'https://studio-gateway.zerocall.kr'
API_KEY = 'zpa.123.your-secret-key'
headers = {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
}
# 메시지 발송
def send_message(to: str, content: str) -> str:
response = requests.post(
f'{BASE_URL}/message/send',
headers=headers,
json={
'toPhoneNumber': to,
'content': content
}
)
return response.json()['result'] # "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 그룹 목록 조회
def get_groups() -> list:
response = requests.get(f'{BASE_URL}/group', headers=headers)
return response.json()
# 통화 기록 조회
def get_call_histories(group_id: int) -> dict:
response = requests.get(
f'{BASE_URL}/call-history',
headers=headers,
params={'groupId': group_id, 'offset': 0, 'limit': 20}
)
return response.json()웹훅 수신 (Node.js)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const { eventType, data } = req.body;
switch (eventType) {
case 'MESSAGE_RECEIVED':
// 메시지 수신 처리
console.log('메시지 수신:', data.content);
handleIncomingMessage(data);
break;
case 'SEND_RESULT':
// 발송 결과 처리
console.log('chatId:', data.chatId);
console.log('최종 결과:', data.resultStatus, data.resultMessage);
handleSendResult(data);
break;
case 'CALL_COMPLETED':
// 통화 종료 처리
console.log('통화 완료:', data.callHistoryId, data.status, data.tag);
handleCallCompleted(data);
break;
}
// 즉시 200 응답 (비동기 처리 권장)
res.status(200).send('OK');
});
app.listen(3000);