빠른 시작
배치 발신(캠페인) API 로 명단을 등록하고 발신을 시작·일시정지·취소하는 방법. curl 예제와 오류 코드 표 포함.
준비물
- API Key 와 Account ID — 콘솔 > 설정 > API 키
- 계정에 등록된 발신 번호
- 발신 시 실행할 대상 —
CallFlowId·AgentId·Url중 하나 - 계정의 배치 발신 활성화 (미활성 시 생성이
403입니다)
모든 요청은 Authorization: Bearer <api_key> 헤더로 인증하며, 기본 주소는 https://api.claw-ops.com 입니다.
명단을 담아 배치를 만듭니다. 필수값은 Name · From · Tasks 입니다.
curl -X POST https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/call-batches \
-H "Authorization: Bearer $CLAWOPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Name": "7월 예약 확인",
"From": "07052358010",
"CallFlowId": "cf_9a8b7c6d",
"MaxConcurrency": 3,
"PacingPerMinute": 20,
"Rounds": [
{ "Windows": [{ "Days": [1, 2, 3, 4, 5], "Start": "09:00", "End": "18:00" }] }
],
"Tasks": [
{ "To": "01012345678", "Variables": { "customer_name": "홍길동", "visit_date": "7월 30일" } },
{ "To": "01087654321", "Variables": { "customer_name": "김영희", "visit_date": "7월 31일" } }
]
}'응답으로 배치 정보가 돌아옵니다. batchId 를 이후 요청에 사용합니다.
{
"batchId": "clx1a2b3c4d5e",
"name": "7월 예약 확인",
"status": "running",
"from": "07052358010",
"callFlowId": "cf_9a8b7c6d",
"maxConcurrency": 3,
"pacingPerMinute": 20,
"timezone": "Asia/Seoul",
"counts": { "pending": 2 }
}기본 상태는 running — 만들면 바로 발신 대기입니다. 명단을 먼저 확인하고 싶다면
"Status": "paused" 로 만든 뒤, 준비되면 resume 하세요.
여기까지가 기본형이고, 실무에서는 대개 세 가지를 함께 켭니다 — 자동응답기 감지로 누가 받았는지 가리고, 다시 걸기로 안 받은 분께 재발신하고, 그래도 안 되면 문자를 남깁니다. 셋 다 배치 생성 한 번에 들어갑니다.
curl -X POST https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/call-batches \
-H "Authorization: Bearer $CLAWOPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Name": "7월 예약 확인",
"From": "07052358010",
"CallFlowId": "cf_9a8b7c6d",
"MaxConcurrency": 3,
"PacingPerMinute": 20,
"MachineDetection": "Enable",
"Rounds": [
{ "Windows": [{ "Days": [1,2,3,4,5], "Start": "10:00", "End": "18:00" }] },
{ "After": 30, "On": ["no-answer", "busy"],
"Windows": [{ "Days": [1,2,3,4,5], "Start": "18:00", "End": "21:00" }] },
{ "After": 45, "On": ["no-answer", "busy"],
"Windows": [{ "Days": [1,2,3,4,5], "Start": "18:00", "End": "21:00" }] }
],
"MessagePolicy": {
"OnFinalFail": {
"Body": "{{customer_name}}님, {{visit_date}} 예약 확인차 전화드렸는데 연결이 어려워 문자 남깁니다."
}
},
"Tasks": [
{ "To": "01012345678", "Variables": { "customer_name": "홍길동", "visit_date": "7월 30일" } }
]
}'이 배치에서 한 수신자가 겪는 일은 이렇습니다.
| 시점 | 일어나는 일 |
|---|---|
| 1차 통화 (낮 10~18시) | 안 받음 → dialRound: 1, 30분 뒤로 재예약 |
| 30분 뒤가 아직 낮이면 | 2차는 저녁 차수라 18시까지 기다립니다 |
| 2차 통화 (18~21시) | 또 안 받음 → dialRound: 2, 45분 뒤로 재예약 |
| 3차 통화 (18~21시) | 또 안 받음 → 남은 차수 없음, status: "failed" |
| 그 직후 | OnFinalFail 문자 발송 |
정책상의 재시도 시각이 그 차수의 시간대 밖이면 시간대가 열릴 때까지 기다렸다가 겁니다.
화면과 API 의 expectedDialAt 이 그 보정을 반영한 값입니다(nextAttemptAt 은 보정 전).
통화가 연결된 분께는 문자가 가지 않습니다. OnFirstFail 을 함께 주면 1차 실패 직후에도
한 통 나가므로, 끝내 안 받은 분은 총 2통을 받습니다.
On 의 machine 은 MachineDetection 을 함께 켠 배치에서만 동작합니다. 감지를 끈 채로
넣으면 요청이 거절되지는 않지만 아무 일도 일어나지 않습니다 — 맞출 판정값(answeredBy)이
아예 없기 때문입니다.
MachineDetection 은 발신할 때마다 애드온 활성 여부를 다시 확인합니다. 배치를 만든 뒤
애드온을 해지하면 남은 통화는 감지 없이 걸립니다(배치가 실패하지는 않습니다).
OnFirstFail 은 재시도 차수가 있어야(Rounds 가 2개 이상) 씁니다. 다시 걸지 않으면 첫 실패가
곧 최종 실패라 OnFinalFail 과 같은 뜻이 되기 때문이며, 함께 주지 않으면
message_policy_invalid 400 입니다.
문자는 통화가 실패한 직후 나갑니다 — 차수 시간대를 따로 기다리지 않습니다. 저녁 차수로 설정한 배치라도 낮에 실패한 통화의 문자는 낮에 갑니다(법정 금지 시간 21~08시에 걸리면 다음 날 아침으로 밀립니다).
생성 응답의 warnings 를 꼭 확인하세요. 거절할 정도는 아니지만 시작한 뒤에는 손쓸 수 없는
것들이 여기 담깁니다.
{
"batchId": "clx1a2b3c4d5e",
"status": "running",
"machineDetection": "Enable",
"retryPolicy": { "delaysMinutes": [30, 180], "retryOn": ["no-answer", "busy"] },
"messagePolicy": { "onFinalFail": { "body": "{{customer_name}}님, ..." } },
"warnings": [
"07052358010 번호로 문자가 전송된 이력이 없습니다. 문자 발신번호 등록은 음성과 별개 절차라, 등록되지 않은 번호는 발송 요청은 성공해도 통신사에서 전량 거절될 수 있습니다."
],
"counts": { "pending": 1 }
}문자가 실제로 도달했는지는 결과 조회의 messageDeliveryStatus
로 확인합니다. messageStatus: "queued" 는 통신사에 넘겼다는 뜻일 뿐 전달 성공이 아닙니다.
수신자마다 다른 값을 쓰려면 Tasks[].Variables 에 넣습니다.
콜 플로우에서는 {{customer_name}} 처럼 이중 중괄호로 참조합니다.
변수 이름은 영문·숫자·밑줄만 가능합니다. 값에는 한글을 써도 됩니다.
명단이 크거나 나중에 추가해야 하면 별도 요청으로 더할 수 있습니다.
curl -X POST https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/call-batches/clx1a2b3c4d5e/tasks \
-H "Authorization: Bearer $CLAWOPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "Tasks": [ { "To": "01099998888", "Variables": { "customer_name": "이철수" } } ] }'{ "added": 1 }건수 제한은 없습니다. 상한은 요청 본문 크기(10MB)이며, 3만 건 규모까지 한 번에 넣을 수 있습니다.
초과하면 413 이 반환되므로 그럴 땐 나눠서 요청하세요. 이미 종료된 배치에는 추가할 수 없습니다(409).
세 동작 모두 같은 엔드포인트에서 Action 값으로 구분합니다.
curl -X POST https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/call-batches/clx1a2b3c4d5e/actions \
-H "Authorization: Bearer $CLAWOPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "Action": "pause" }'| Action | 동작 |
|---|---|
pause | 신규 발신만 중단합니다. 진행 중인 통화는 그대로 유지됩니다 |
resume | 다시 발신을 시작합니다 |
cancel | 남은 대상을 모두 취소합니다. 이미 걸린 통화는 유지되며, 개별 종료가 필요하면 통화 제어 API 를 사용하세요 |
배치 상세 조회의 counts 가 상태별 수신자 수입니다.
curl https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/call-batches/clx1a2b3c4d5e \
-H "Authorization: Bearer $CLAWOPS_API_KEY"{
"batchId": "clx1a2b3c4d5e",
"status": "running",
"counts": { "pending": 120, "dialing": 3, "done": 77 }
}계정의 배치 목록은 GET /v1/accounts/{accountId}/call-batches 로 조회합니다.
수신자별 결과는 결과 조회 를 참고하세요.
주요 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| Name | string | 필수 | 배치 이름 |
| From | string | 필수 | 발신 번호 — 계정에 등록된 번호여야 합니다 |
| Tasks | array | 필수 | 수신자 목록. 각 항목은 To(필수)와 Variables(선택) |
| CallFlowId / AgentId / Url | string | 필수 | 발신 대상. 셋 중 정확히 하나 |
| Status | string | 선택 | 생성 직후 상태. running(기본) 또는 paused |
| MaxConcurrency | integer | 선택 | 이 배치가 동시에 유지할 통화 수. 기본 1 |
| PacingPerMinute | integer | 선택 | 분당 최대 발신 수. 기본 10 |
| Timezone | string | 선택 | 발신 시간대 판정 기준. 기본 Asia/Seoul |
| Rounds | array | 선택 | 발신 차수(최대 5). 배열 인덱스가 곧 차수이고 Rounds[0]이 1차. 각 항목은 After(분, 2차부터 필수 · 1~1440) · On(직전 결과 조건, 2차부터 필수) · Windows(이 차수의 시간대. Days 1=월~7=일 · Start · End). 생략하면 한 번만 걸고 시간대는 법정 허용 시간 전체 |
| StartAt | string | 선택 | 이 시각 이후부터 발신 시작 (ISO 8601) |
| EndAt | string | 선택 | 이 시각이 지나면 남은 대상은 발신하지 않고 종료 (ISO 8601) |
| Priority | integer | 선택 | 같은 계정에 배치가 여럿일 때 우선순위(높을수록 먼저). 기본 0 |
| MachineDetection | string | 선택 | 자동응답기 감지. None(기본·사용 안 함) · Enable(감지만) · Hangup(자동응답기면 끊기). AMD 부가서비스가 필요하고 감지한 통화마다 요금이 붙습니다 |
| MessagePolicy | object | 선택 | 통화가 안 된 분께 보낼 문자. OnFirstFail(첫 실패 직후 · 재시도 차수 필요) · OnFinalFail(끝내 미연결). 각각 { Body } 이며 본문은 2000자 이하, {{변수}}는 그 수신자의 Variables 로 치환됩니다 |
자동응답기 감지 (선택)
MachineDetection 을 주면 사람이 받았는지 자동응답기(음성사서함)인지 판별합니다. 기본은 사용 안 함입니다.
| 값 | 동작 |
|---|---|
None (기본) | 판별하지 않습니다 |
Enable | 판별만 하고 통화는 그대로 진행합니다. 결과의 answeredBy 에 human · machine · unknown 이 담깁니다 |
Hangup | 자동응답기로 판별되면 통화를 끊습니다 |
AMD 부가서비스가 활성화된 계정만 쓸 수 있습니다(없으면 amd_addon_disabled 422). 판별한 통화마다 요금이 붙으므로, 결과를 실제로 활용할 때만 켜세요. 판별이 항상 성공하지는 않아 unknown 이 나올 수 있습니다.
오류 코드
| 코드 | 상태 | 원인 |
|---|---|---|
batch_disabled | 403 | 배치 발신이 활성화되지 않은 계정 |
missing_field | 400 | Name 또는 From 누락 |
from_not_registered | 400 | From 이 계정에 등록된 번호가 아님 |
target_invalid | 400 | CallFlowId · AgentId · Url 중 하나만 지정해야 함 |
call_flow_not_found | 404 | CallFlowId 에 해당하는 콜 플로우 없음 |
agent_not_found | 404 | AgentId 에 해당하는 에이전트 없음 |
tasks_required | 400 | Tasks 가 비어 있음 |
task_to_required | 400 | Tasks[].To 누락 |
task_to_invalid | 400 | 수신 번호 형식 오류 |
task_duplicate | 400 | 같은 요청 안에 중복 번호 |
rounds_invalid | 400 | Rounds 형식 오류 — 개수(1After/On 사용 · 2차부터 After(1On 누락 · Windows 의 Days 범위나 HH:MM 형식 · 법정 허용 시간(08:00~21:00)과 겹치는 구간 없음 |
timezone_invalid | 400 | 알 수 없는 시간대 |
start_at_invalid · end_at_invalid | 400 | 시각 형식 오류 또는 EndAt 이 StartAt 보다 앞섬 |
status_invalid | 400 | Status 는 running · paused 만 가능 |
machine_detection_invalid | 400 | MachineDetection 은 None · Enable · Hangup 만 가능 |
amd_addon_disabled | 422 | AMD 부가서비스가 비활성 상태에서 감지를 요청 |
message_policy_invalid | 400 | Body 누락·2000자 초과 · 본문의 {{변수}} 가 없는 수신자 존재 · 재시도 차수 없이 OnFirstFail 사용 |
batch_not_found | 404 | 배치 없음 |
batch_closed | 409 | 이미 종료된 배치에 대한 추가·제어 |