---
title: "발신 전화 걸기(API)"
description: "자체 코드에서 AI 기반 발신 전화를 트리거합니다. 설문조사, 후속 조치 또는 확인 흐름에 활용할 수 있습니다."
---

발신 통화를 사용하면 대상 번호와 에이전트 구성을 ThunderPhone에 전달하여 AI가 대신 전화를 걸도록 할 수 있습니다. 일반적인 사용 사례는 다음과 같습니다.

- 예약 확인
- 설문조사 재통화
- 부재중 전화 후 "두 번째 시도" 후속 연락
- 배차 방식 알림

<Note>
  전체 연락처 목록에 전화를 거시나요? 대시보드의
  [**캠페인**](/ko/guides/outbound-campaigns) 기능
  (`/dashboard/campaigns`)은 연락처 CSV를 받아 시간대를 고려한 통화 가능 시간, 동시 처리 및 재시도 정책을 대신 관리합니다. 이 가이드에서는 단일 프로그래밍 방식 통화를 다룹니다.
</Note>

## 사전 요구 사항

<Steps>
  <Step title="발신이 활성화된 번호 선택">
    [VoIP 연결](/api-reference/voip-connections)을 통해 소유한 번호를 사용하거나,
    전화번호 페이지에서 ThunderPhone 번호를 발신 통화에 사용할 수 있도록 권한을 요청합니다.
    ThunderPhone 번호는 처음에는 수신 전용으로 시작합니다. ThunderPhone은 각 요청을
    수동으로 검토합니다. 승인되면 해당 번호로 승인된 일일 한도(00:00 UTC에 재설정)까지
    전화를 걸고 캠페인을 실행할 수 있으며, 더 높은 한도를 요청할 수도 있습니다. 고객 VoIP 번호에는
    일일 한도가 없으므로 발신 통화에 사용하는 것을 권장합니다. 자세한 내용은
    [자체 번호 사용](/ko/guides/bring-your-own-numbers)을 참조합니다.
  </Step>
  <Step title="에이전트 생성">
    발신용 프롬프트는 일반적으로 에이전트가 자신과 통화 목적을 소개하는 것으로 시작합니다.
    "안녕하세요, 내일 오후 3시 예약을 확인하기 위해 Acme에서 전화드렸습니다…" `outbound_speak_order`를
    `agent_first`(기본값)로 설정합니다.
  </Step>
  <Step title="잔액을 양수로 유지">
    잔액이 `$0.00` 이하이면 발신 통화는 `402 Payment Required`를 반환합니다.
    대시보드의 **조직 → 결제 설정**에서 잔액을 충전하거나 자동 충전을 활성화합니다. `sk_live_`
    키로 [`GET /v1/billing`](/api-reference/billing#get-billing-account)을 사용해 잔액을 확인할 수 있지만,
    잔액을 충전하거나 자동 충전 설정을 변경할 수는 없습니다.
  </Step>
</Steps>

## 저장된 에이전트로 통화 걸기

가장 간단한 방법은 ID로 에이전트를 참조하는 것입니다.

```bash
curl -X POST https://api.thunderphone.com/v1/call \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from_number": "+15551234567",
    "to_number":   "+14155552671",
    "agent_id":    12
  }'
```

응답:

```json
{ "call_id": 987654321, "status": "initiated" }
```

<Warning>
  `status: "initiated"`는 요청이 수락되었음을 의미할 뿐이며, 통화가 **아직 연결되지 않았습니다**. 실시간 상태는 [`GET /v1/calls/{call_id}`](/api-reference/calls#retrieve-a-call)를 폴링하여 확인합니다 (`in_progress` → `completed` / `failed`).
</Warning>

## 인라인 구성으로 통화 걸기

에이전트로 저장할 가치가 없는 일회성 프롬프트가 필요한 경우에는 대신 `config`를 전달합니다. 구조는 [`call.incoming` 웹훅](/ko/webhooks/call-incoming)의 응답 스키마와 일치합니다.

```bash
curl -X POST https://api.thunderphone.com/v1/call \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from_number": "+15551234567",
    "to_number":   "+14155552671",
    "config": {
      "prompt":  "You are confirming Jane Doe appointment for 3pm tomorrow…",
      "voice":   "john",
      "product": "spark"
    }
  }'
```

## 통화 추적

동시에 [`telephony.complete` 웹훅](/ko/webhooks/events)을 구독합니다.
통화가 종료되었는지 가장 빠르게 확인하는 방법입니다. 인바운드 웹훅을 수신할 수
없다면 몇 초마다 `GET /v1/calls/{call_id}`를 폴링합니다. 통화가 종료되면
레코드에 `end_reason`, `duration_seconds`, 녹음 URL이 포함됩니다.

에이전트가 통화 후 구조화된 데이터를 추출하도록 설정된 경우,
최종 처리가 완료된 후 해당 데이터가 별도로 전달됩니다.

### 저장된 에이전트에 통화별 변수 전달

저장된 에이전트는 프롬프트 텍스트에서 `{{name}}` 또는 `{{name|there}}`와 같은
플레이스홀더를 사용할 수 있습니다. `agent_id`로 아웃바운드 통화를 시작할 때
해당 통화의 값을 포함한 `variables`를 전달합니다.

```json
{
  "from_number": "+[REDACTED_PHONE]",
  "to_number": "+[REDACTED_PHONE]",
  "agent_id": 12,
  "variables": {
    "name": "Jordan"
  }
}
```

플레이스홀더 이름을 키로 하는 문자열 값을 사용합니다. 이 변수는 저장된
에이전트에 적용되며, 이 가이드의 인라인 `config` 예시에서는 사용하지 않습니다.

## 처리해야 할 장애 유형

| 오류 | 해결 방법 |
|-------|-----|
| `402 Payment Required` | 잔액을 충전하거나 자동 충전을 활성화합니다 |
| `400` 및 `code: destination_not_allowed` | ThunderPhone은 해당 번호로 전화할 수 없습니다. 유효하지 않은 번호, 긴급 전화번호, 고가 요금 번호, 단축 번호 또는 제재 대상 국가가 포함됩니다. ThunderPhone 번호에서는 일반 미국 및 캐나다 번호로만 전화할 수 있으며 고가 요금 번호는 제외됩니다. 어떤 사유인지는 `reason`에서 확인합니다. [차단된 수신 번호](/api-reference/outbound-calls#blocked-destinations)를 참조합니다 |
| ThunderPhone 번호에 대한 `409` 및 `retryable: false` | `code`에 따릅니다. 전화번호 페이지에서 아웃바운드 통화를 요청하거나, 보류 중인 검토가 완료될 때까지 기다리거나, 다른 적격 번호를 사용합니다 |
| `429` 및 `code: platform_outbound_daily_limit_reached` | 조직이 오늘 ThunderPhone 번호에서 사용할 수 있는 아웃바운드 통화를 모두 사용했습니다. `resets_at`(00:00 UTC)까지 기다리거나, 전화번호 페이지에서 더 높은 한도를 요청하거나, 자체 VoIP 연결의 번호에서 전화합니다 |
| `429` 및 `code: concurrent_call_limit_reached` | 조직에서 진행 중인 통화 수가 [동시 통화 한도](/api-reference/introduction#call-limits)에 도달했습니다. 기본값은 20이며, 인바운드, 아웃바운드, 웹 및 테스트 통화를 포함합니다. `Retry-After` 헤더에 지정된 초 후 또는 통화가 종료된 후 재시도합니다. 한도를 늘리려면 support@thunderphone.com으로 이메일을 보냅니다 |
| `429` 및 `code: same_number_too_soon` | 동일한 `to_number`로 10초 이내에 이미 전화했습니다. `Retry-After` 헤더에 지정된 초 후 재시도합니다 |
| 고객 VoIP 번호에 대한 `409` 및 `retryable: false` | `code`로 지정된 상태를 수정합니다. 인증에 실패한 경우 [`POST /v1/phone-numbers/{id}/verify-voip`](/api-reference/phone-numbers#verify-a-voip-sourced-number)을 실행합니다 |
| `409` 멱등성 충돌 | 원래의 정규화된 요청에만 키를 재사용하거나 새 키를 전송합니다 |
| `404 from_number is not registered to this organization` | `from_number`가 조직의 활성 전화번호와 일치하는지 확인합니다. 이미 프로비저닝 중이거나, 실패했거나, 해제 중이거나, 해제된 번호도 이 응답을 반환합니다 |
| `500` 및 `detail` 필드만 포함 | 아웃바운드 트렁크가 구성되지 않았습니다. 지원팀에 문의합니다. 이는 수정할 수 있는 번호 상태 문제가 아닙니다 |
| `502 Bad Gateway` | 일시적인 SIP / LiveKit 오류입니다. 안전하게 재시도할 수 있습니다 |

전체 안정적인 적격성 코드 목록과 두 가지 `409` 응답 형식은
[아웃바운드 통화 레퍼런스](/api-reference/outbound-calls#error-responses)를
참조합니다. 활성 번호가 요청 수락 후 통화 시작 전에 부적격 상태가 되면,
최종 확인에서 재시도할 수 없는 `409` 페이로드를 반환합니다.

## 보류 시간 제어

수신자의 응답이 느려 길어지는 아웃바운드 통화(IVR 전화 메뉴, 대기열)는
`max_hold_seconds`로 제한할 수 있습니다.

```json
{
  "from_number": "+15551234567",
  "to_number":   "+14155552671",
  "agent_id":    12,
  "max_hold_seconds": 120
}
```

에이전트는 최근 N초 동안 사람의 음성이 수신되지 않으면 전화를 끊습니다. 기본값은 900초(15분)입니다.

---

## 다음 단계

<CardGroup cols={2}>
  <Card title="아웃바운드 통화 레퍼런스" icon="phone-arrow-up-right" href="/api-reference/outbound-calls">
    모든 요청 필드와 오류 코드입니다.
  </Card>
  <Card title="call.complete 수신" icon="bolt" href="/ko/webhooks/call-complete">
    완료된 아웃바운드 통화를 시스템으로 스트리밍합니다.
  </Card>
  <Card title="청구" icon="credit-card" href="/api-reference/billing">
    잔액 부족으로 아웃바운드가 실패하지 않도록 자동 충전을 설정합니다.
  </Card>
  <Card title="아웃바운드 에이전트 테스트" icon="flask" href="/ko/guides/test-agents">
    프로덕션 배포 전에 아웃바운드 에이전트를 드라이런합니다.
  </Card>
</CardGroup>
