새로운 문서를 작성 중입니다.새 문서로 이동
ClawOps Docs
배치 발신 (캠페인)

빠른 시작

배치 발신(캠페인) API 로 명단을 등록하고 발신을 시작·일시정지·취소하는 방법. curl 예제와 오류 코드 표 포함.

준비물

  • API KeyAccount 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통을 받습니다.

OnmachineMachineDetection 을 함께 켠 배치에서만 동작합니다. 감지를 끈 채로 넣으면 요청이 거절되지는 않지만 아무 일도 일어나지 않습니다 — 맞출 판정값(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 로 조회합니다. 수신자별 결과는 결과 조회 를 참고하세요.

주요 파라미터

파라미터타입필수설명
Namestring필수배치 이름
Fromstring필수발신 번호 — 계정에 등록된 번호여야 합니다
Tasksarray필수수신자 목록. 각 항목은 To(필수)와 Variables(선택)
CallFlowId / AgentId / Urlstring필수발신 대상. 셋 중 정확히 하나
Statusstring선택생성 직후 상태. running(기본) 또는 paused
MaxConcurrencyinteger선택이 배치가 동시에 유지할 통화 수. 기본 1
PacingPerMinuteinteger선택분당 최대 발신 수. 기본 10
Timezonestring선택발신 시간대 판정 기준. 기본 Asia/Seoul
Roundsarray선택발신 차수(최대 5). 배열 인덱스가 곧 차수이고 Rounds[0]이 1차. 각 항목은 After(분, 2차부터 필수 · 1~1440) · On(직전 결과 조건, 2차부터 필수) · Windows(이 차수의 시간대. Days 1=월~7=일 · Start · End). 생략하면 한 번만 걸고 시간대는 법정 허용 시간 전체
StartAtstring선택이 시각 이후부터 발신 시작 (ISO 8601)
EndAtstring선택이 시각이 지나면 남은 대상은 발신하지 않고 종료 (ISO 8601)
Priorityinteger선택같은 계정에 배치가 여럿일 때 우선순위(높을수록 먼저). 기본 0
MachineDetectionstring선택자동응답기 감지. None(기본·사용 안 함) · Enable(감지만) · Hangup(자동응답기면 끊기). AMD 부가서비스가 필요하고 감지한 통화마다 요금이 붙습니다
MessagePolicyobject선택통화가 안 된 분께 보낼 문자. OnFirstFail(첫 실패 직후 · 재시도 차수 필요) · OnFinalFail(끝내 미연결). 각각 { Body } 이며 본문은 2000자 이하, {{변수}}는 그 수신자의 Variables 로 치환됩니다

자동응답기 감지 (선택)

MachineDetection 을 주면 사람이 받았는지 자동응답기(음성사서함)인지 판별합니다. 기본은 사용 안 함입니다.

동작
None (기본)판별하지 않습니다
Enable판별만 하고 통화는 그대로 진행합니다. 결과의 answeredByhuman · machine · unknown 이 담깁니다
Hangup자동응답기로 판별되면 통화를 끊습니다

AMD 부가서비스가 활성화된 계정만 쓸 수 있습니다(없으면 amd_addon_disabled 422). 판별한 통화마다 요금이 붙으므로, 결과를 실제로 활용할 때만 켜세요. 판별이 항상 성공하지는 않아 unknown 이 나올 수 있습니다.

오류 코드

코드상태원인
batch_disabled403배치 발신이 활성화되지 않은 계정
missing_field400Name 또는 From 누락
from_not_registered400From 이 계정에 등록된 번호가 아님
target_invalid400CallFlowId · AgentId · Url 중 하나만 지정해야 함
call_flow_not_found404CallFlowId 에 해당하는 콜 플로우 없음
agent_not_found404AgentId 에 해당하는 에이전트 없음
tasks_required400Tasks 가 비어 있음
task_to_required400Tasks[].To 누락
task_to_invalid400수신 번호 형식 오류
task_duplicate400같은 요청 안에 중복 번호
rounds_invalid400Rounds 형식 오류 — 개수(15) · 1차에 After/On 사용 · 2차부터 After(11440)/On 누락 · WindowsDays 범위나 HH:MM 형식 · 법정 허용 시간(08:00~21:00)과 겹치는 구간 없음
timezone_invalid400알 수 없는 시간대
start_at_invalid · end_at_invalid400시각 형식 오류 또는 EndAtStartAt 보다 앞섬
status_invalid400Statusrunning · paused 만 가능
machine_detection_invalid400MachineDetectionNone · Enable · Hangup 만 가능
amd_addon_disabled422AMD 부가서비스가 비활성 상태에서 감지를 요청
message_policy_invalid400Body 누락·2000자 초과 · 본문의 {{변수}} 가 없는 수신자 존재 · 재시도 차수 없이 OnFirstFail 사용
batch_not_found404배치 없음
batch_closed409이미 종료된 배치에 대한 추가·제어