---
title: "发起外呼（API）"
description: "从您自己的代码触发 AI 驱动的外呼——用于问卷调查、跟进或确认流程。"
---

外呼功能允许您将目标号码和智能体配置交给 ThunderPhone，由 AI 代表您拨打电话。典型使用场景：

- 预约确认
- 问卷回访
- 未接来电后的“第二次尝试”跟进
- 调度式通知

<Note>
  要呼叫整个名单？控制台的
  [**营销活动**](/zh/guides/outbound-campaigns) 功能
  （`/dashboard/campaigns`）可接收联系人 CSV，并为您处理
  时区感知的呼叫时间窗口、并发数和重试策略。本指南介绍单次编程调用。
</Note>

## 前提条件

<Steps>
  <Step title="选择已启用外呼的号码">
    使用您通过
    [VoIP 连接](/api-reference/voip-connections)拥有的号码，或在“电话号码”
    页面申请允许将您的 ThunderPhone 号码用于外呼。ThunderPhone 号码初始仅支持呼入。
    ThunderPhone 会人工审核每项申请；审核通过后，这些号码可在获批的每日限额内拨打电话
    （每日 00:00 UTC 重置）并运行营销活动，您也可以申请提高限额。客户的 VoIP 号码没有每日限额，
    因此我们建议将其用于外呼。请参阅
    [使用您自己的号码](/zh/guides/bring-your-own-numbers)。
  </Step>
  <Step title="创建智能体">
    适用于外呼的提示词通常以智能体说明自身身份和目的开始——“您好，这里是 Acme，致电是为了
    确认您明天下午 3 点的预约……”将
    `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` webhook](/zh/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` webhook](/zh/webhooks/events)——这是了解通话已结束的最快方式。如果您无法接收入站
webhook，请每隔几秒轮询一次 `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` | 您在不足 10 秒前呼叫过相同的 `to_number`。在 `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` 与您组织中的有效电话号码一致。已处于开通中、失败、释放中或已释放状态的号码也会返回此响应 |
| 仅包含 `detail` 字段的 `500` | 未配置外呼中继。请联系支持团队；这不是您可以修正的号码状态问题 |
| `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="/zh/webhooks/call-complete">
    将已完成的出站通话流式传输到您的系统。
  </Card>
  <Card title="计费" icon="credit-card" href="/api-reference/billing">
    启用自动充值，确保出站通话不会因余额不足而失败。
  </Card>
  <Card title="测试出站智能体" icon="flask" href="/zh/guides/test-agents">
    在生产环境前对您的出站智能体进行试运行。
  </Card>
</CardGroup>
