You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用Vonage内联NCCO转移呼叫异常400报错问题

Vonage Voice API 内联NCCO呼叫转移400错误修复

问题复现特征

  • 直接运行官方内联NCCO呼叫转移示例代码,呼叫仅播放首个语音内容后自动挂断
  • 执行呼叫更新接口时抛出错误:vonage.errors.ClientError: 400 response from api.nexmo.com
  • 公开渠道无同类问题排查方案与可运行参考实现

原复现代码如下:

import vonage

client = vonage.Client(
    application_id="<ID>",
    private_key=r"private.key",
)

voice = vonage.Voice(client)


response = voice.create_call({
    'to': [{'type': 'phone', 'number': "<mynumber>"}],
    'from': {'type': 'phone', 'number': "<vonagenumber>"},
    "ncco": [
        {
            "action": "talk",
            "text": "This is just a text whilst you tranfer to another NCCO"
        }
    ]
})

response = voice.update_call(
    response["uuid"], {
        "action": "transfer",
        "destination": {
            "type": "ncco",
            "ncco": [{"action": "talk", "text": "hello world"}]
        }
    }
)


print(response)

故障根因

官方示例代码存在时序逻辑缺陷:

  1. 发起呼叫后立即同步执行转移请求,此时呼叫尚未完成接通,状态不支持转移操作
  2. 初始NCCO仅包含一个短时长的语音动作,语音播放完成后无后续待执行动作,呼叫会被平台自动挂断,后续到达的转移请求自然返回400错误

修复方案

执行转移操作必须满足两个前置条件:

  • 等待呼叫进入answered状态,确认呼叫链路已正常建立
  • 初始NCCO预留足够的时间窗口,确保转移操作执行完成前呼叫不会因无动作可执行被挂断

本地测试可运行版本(无需配置webhook)

通过轮询呼叫状态+初始NCCO加等待动作的方式规避时序问题,代码如下:

import vonage
import time

client = vonage.Client(
    application_id="<替换为你的应用ID>",
    private_key=r"private.key",
)
voice = vonage.Voice(client)

# 发起呼叫,初始NCCO预留足够等待时长
call_resp = voice.create_call({
    'to': [{'type': 'phone', 'number': "<替换为你的接听号码>"}],
    'from': {'type': 'phone', 'number': "<替换为你的Vonage号码>"},
    "ncco": [
        {
            "action": "talk",
            "text": "正在为您转接,请稍候"
        },
        # 加入长等待动作,避免转移执行前呼叫挂断
        {
            "action": "talk",
            "text": "请不要挂机,我们正在为您连接目标坐席",
            "loop": 3
        }
    ]
})
call_uuid = call_resp["uuid"]

# 轮询检查呼叫状态,接通后再执行转移
max_wait_second = 20
for _ in range(max_wait_second):
    call_detail = voice.get_call(call_uuid)
    if call_detail["status"] == "answered":
        break
    time.sleep(1)
else:
    raise RuntimeError("呼叫接听超时,请检查号码状态")

# 执行内联NCCO转移
transfer_resp = voice.update_call(
    call_uuid,
    {
        "action": "transfer",
        "destination": {
            "type": "ncco",
            "ncco": [{"action": "talk", "text": "转接成功,您好,有什么可以帮您"}]
        }
    }
)
print(transfer_resp)

生产环境推荐方案

不要使用本地轮询逻辑,在Vonage应用后台配置呼叫状态回调地址,当平台推送answered状态事件到你的服务端时,再调用转移接口,时序更精准,资源消耗更低。

注:官方公开的示例代码缺失了状态等待的必要逻辑,属于文档疏漏,直接运行必然触发时序类报错。


内容的提问来源于stack exchange,提问作者xliquid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 14:01:25