Voicelen Open API

通过 API 集成 Voicelen 的外呼任务、Agent 管理和通话记录功能。

概述

基础 URL

https://api.voicelen.com

所有接口路径相对于此基础 URL。

认证方式

在请求头中携带 API Key 进行认证:

Authorization: Bearer <api_key>

响应格式

所有接口统一返回以下 JSON 格式:

标准响应
{
  "code": 0,
  "message": "success",
  "data": { ... }
}
列表响应
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [...],
    "total": 100
  }
}

错误码

Code 含义
0成功
1001API Key 无效
1002API Key 已禁用
2001参数校验失败
3001资源不存在
3002状态不允许操作
3003数据重复
5001系统内部错误

外呼任务

POST /api/open/outbound-tasks

创建一个新的外呼任务,包含任务配置和呼叫条目。

请求参数
字段 类型 必填 说明
name string 必填 任务名称
agent_uuid string 必填 AI Agent UUID
number_uuid string 必填 外显号码 UUID
start_date string 必填 开始日期,格式 YYYY-MM-DD
end_date string 可选 结束日期,格式 YYYY-MM-DD
time_slots string 必填 时间段 JSON,如 [{"start":"09:00","end":"18:00"}]
items array 必填 呼叫条目列表,至少 1 条
items 子项
字段 类型 必填 说明
phone string 必填 电话号码
name string 必填 客户姓名
extra string 可选 JSON 字符串;通话时可在 Agent Prompt 里用 {{customer.extra.xxx}} 引用,详见 Prompt 变量 章节
请求示例
curl -X POST https://api.voicelen.com/api/open/outbound-tasks \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "春季促销外呼",
  "agent_uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
  "number_uuid": "a1b2c3d4-5678-90ab-cdef-222222222222",
  "start_date": "2026-04-16",
  "end_date": "2026-04-30",
  "time_slots": "[{\"start\":\"09:00\",\"end\":\"12:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}]",
  "items": [
    {"phone": "13800138001", "name": "张三"},
    {"phone": "13800138002", "name": "李四", "extra": "{\"vip\":true}"}
  ]
}'
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "uuid": "e5f6a7b8-1234-5678-abcd-999999999999",
    "name": "春季促销外呼",
    "start_date": "2026-04-16",
    "end_date": "2026-04-30",
    "time_slots": "[{\"start\":\"09:00\",\"end\":\"12:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}]",
    "target_type": "robot",
    "agent_uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
    "status": "pending",
    "status_remark": "",
    "status_at": "2026-04-15T10:30:00Z",
    "total_count": 2,
    "called_count": 0,
    "answered_count": 0,
    "answer_rate": 0,
    "created_at": "2026-04-15T10:30:00Z"
  }
}
GET /api/open/outbound-tasks/:uuid

查询外呼任务详情,包含统计数据。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
请求示例
curl https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999 \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "uuid": "e5f6a7b8-1234-5678-abcd-999999999999",
    "name": "春季促销外呼",
    "start_date": "2026-04-16",
    "end_date": "2026-04-30",
    "time_slots": "[{\"start\":\"09:00\",\"end\":\"12:00\"},{\"start\":\"14:00\",\"end\":\"18:00\"}]",
    "target_type": "robot",
    "agent_uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
    "status": "running",
    "status_remark": "",
    "status_at": "2026-04-16T09:00:00Z",
    "total_count": 2,
    "called_count": 1,
    "answered_count": 1,
    "answer_rate": 50,
    "created_at": "2026-04-15T10:30:00Z"
  }
}
POST /api/open/outbound-tasks/:uuid/pause

暂停外呼任务。仅 pending 或 running 状态的任务可操作。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
请求示例
curl -X POST https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999/pause \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": null
}
POST /api/open/outbound-tasks/:uuid/resume

恢复已暂停的外呼任务。仅 paused 状态的任务可操作。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
请求示例
curl -X POST https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999/resume \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": null
}
POST /api/open/outbound-tasks/:uuid/cancel

取消外呼任务。completed 和 cancelled 状态的任务不可操作。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
请求示例
curl -X POST https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999/cancel \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": null
}
GET /api/open/outbound-tasks/:uuid/items

查询外呼任务的呼叫条目列表,支持分页和关键词搜索。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
查询参数
字段 类型 必填 说明
page int 可选 页码,默认 1
page_size int 可选 每页数量,默认 20
keyword string 可选 按姓名或电话搜索
请求示例
curl "https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999/items?page=1&page_size=20" \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "phone": "13800138001",
        "name": "张三",
        "extra": "",
        "status": "answered",
        "call_id": "task-abc123",
        "start_time": "2026-04-16T09:01:00Z",
        "answer_time": "2026-04-16T09:01:08Z",
        "end_time": "2026-04-16T09:02:35Z",
        "duration": 95,
        "billsec": 87,
        "hangup_cause": "NORMAL_CLEARING",
        "attempts": 1,
        "created_at": "2026-04-15T10:30:00Z"
      }
    ],
    "total": 2
  }
}
POST /api/open/outbound-tasks/:uuid/items

向已有外呼任务追加导入呼叫条目。

路径参数
字段 类型 必填 说明
uuid string 必填 任务 UUID
请求参数
字段 类型 必填 说明
items array 必填 呼叫条目列表(字段同创建任务的 items)
请求示例
curl -X POST https://api.voicelen.com/api/open/outbound-tasks/e5f6a7b8-1234-5678-abcd-999999999999/items \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {"phone": "13800138003", "name": "王五"},
    {"phone": "13800138004", "name": "赵六", "extra": "{\"source\":\"web\"}"}
  ]
}'
响应示例
{
  "code": 0,
  "message": "success",
  "data": null
}

号码

GET /api/open/numbers

查询当前企业的外显号码列表,用于创建外呼任务时指定号码。

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "uuid": "a1b2c3d4-...",
        "number": "010-12345678",
        "direction": "both",
        "status": 0
      }
    ],
    "total": 1
  }
}

响应字段

字段类型说明
uuidstring号码 UUID,创建任务时传入 number_uuid
numberstring号码
directionstring方向:inbound / outbound / both
statusint状态:0 正常,1 禁用

Agent

GET /api/open/agents

获取 Agent 列表。

请求示例
curl https://api.voicelen.com/api/open/agents \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
        "name": "客服小助手",
        "created_at": "2026-03-01T08:00:00Z"
      }
    ],
    "total": 1
  }
}
GET /api/open/agents/:uuid

获取 Agent 详情。

路径参数
字段 类型 必填 说明
uuid string 必填 Agent UUID
请求示例
curl https://api.voicelen.com/api/open/agents/a1b2c3d4-5678-90ab-cdef-111111111111 \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
    "name": "客服小助手",
    "created_at": "2026-03-01T08:00:00Z"
  }
}

通话记录

GET /api/open/call-records

查询通话记录列表,支持按任务和号码筛选。

查询参数
字段 类型 必填 说明
page int 可选 页码,默认 1
page_size int 可选 每页数量,默认 20
task_uuid string 可选 按外呼任务筛选
phone string 可选 按电话号码筛选
请求示例
curl "https://api.voicelen.com/api/open/call-records?page=1&page_size=20&task_uuid=e5f6a7b8-1234-5678-abcd-999999999999" \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "call_id": "task-abc123",
        "direction": "outbound",
        "customer_phone": "13800138001",
        "task_uuid": "e5f6a7b8-1234-5678-abcd-999999999999",
        "agent_uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
        "agent_name": "客服小助手",
        "start_time": "2026-04-16T09:01:00Z",
        "answer_time": "2026-04-16T09:01:08Z",
        "end_time": "2026-04-16T09:02:35Z",
        "duration": 95,
        "billsec": 87,
        "hangup_cause": "NORMAL_CLEARING",
        "hangup_by": "customer",
        "created_at": "2026-04-16T09:01:00Z"
      }
    ],
    "total": 1
  }
}
GET /api/open/call-records/:call_id

查询通话详情,包含 Agent 对话记录(conversations 数组)。

路径参数
字段 类型 必填 说明
call_id string 必填 通话 ID
请求示例
curl https://api.voicelen.com/api/open/call-records/task-abc123 \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "call_id": "task-abc123",
    "direction": "outbound",
    "customer_phone": "13800138001",
    "task_uuid": "e5f6a7b8-1234-5678-abcd-999999999999",
    "agent_uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
    "agent_name": "客服小助手",
    "start_time": "2026-04-16T09:01:00Z",
    "answer_time": "2026-04-16T09:01:08Z",
    "end_time": "2026-04-16T09:02:35Z",
    "duration": 95,
    "billsec": 87,
    "hangup_cause": "NORMAL_CLEARING",
    "hangup_by": "customer",
    "conversations": [
      {
        "seq": 1,
        "role": "agent.say",
        "text": "您好,这里是 Voicelen 客服中心,请问有什么可以帮您?",
        "asr_first_ms": 0,
        "asr_duration": 0,
        "llm_first_ms": 320,
        "llm_duration": 1450,
        "tts_first_ms": 180,
        "tts_duration": 820,
        "interrupted": false,
        "interrupted_text": ""
      },
      {
        "seq": 2,
        "role": "customer.say",
        "text": "我想了解一下你们的促销活动",
        "asr_first_ms": 220,
        "asr_duration": 1200,
        "llm_first_ms": 0,
        "llm_duration": 0,
        "tts_first_ms": 0,
        "tts_duration": 0,
        "interrupted": false,
        "interrupted_text": ""
      },
      {
        "seq": 3,
        "role": "agent.say",
        "text": "好的,我们目前有春季促销活动,新用户可享八折优惠...",
        "asr_first_ms": 0,
        "asr_duration": 0,
        "llm_first_ms": 450,
        "llm_duration": 1820,
        "tts_first_ms": 210,
        "tts_duration": 980,
        "interrupted": true,
        "interrupted_text": "好的,我们目前有春季促销"
      }
    ],
    "created_at": "2026-04-16T09:01:00Z"
  }
}
GET /api/open/call-records/:call_id/recording-url

获取通话录音的临时下载 URL,有效期 1 小时。

路径参数
字段 类型 必填 说明
call_id string 必填 通话 ID
请求示例
curl https://api.voicelen.com/api/open/call-records/task-abc123/recording-url \
  -H "Authorization: Bearer your_api_key"
响应示例
{
  "code": 0,
  "message": "success",
  "data": {
    "url": "https://storage.voicelen.com/recordings/task-abc123.wav?token=xxx&expires=1713348000",
    "expires_at": "2026-04-16T10:01:00Z"
  }
}

Webhook

Voicelen 会在关键业务事件发生时,主动 POST JSON 到你配置的 URL。适合用于 CRM 同步、工单触发、实时告警等场景。

配置入口

登录控制台 → 管理 → Webhook 填写接收 URL、订阅事件、超时等。首次创建会生成一次性 Secret,用于签名验证,请立即保存。

请求规范

  • POST 你配置的 URL
  • Content-Type: application/json
  • 请求体为事件对象,所有事件统一信封
  • 2xx 视为投递成功,其它状态码或超时视为失败,触发重试

请求头

名称说明
X-Voicelen-Event-Id事件唯一 ID,用于幂等去重
X-Voicelen-Event-Type事件类型,如 call.ended
X-Voicelen-Timestamp请求发出的 Unix 秒级时间戳
X-Voicelen-Signaturesha256={body 的 HMAC-SHA256 hex}

事件统一信封

{
  "id": "evt_7a3f...",
  "type": "call.ended",
  "company_uuid": "c_xxx",
  "timestamp": 1713600000000,
  "data": { ... }
}

签名验证

服务端用你的 Secret 对完整 body(bytes)做 HMAC-SHA256,十六进制写入 X-Voicelen-Signature。客户端应用相同方法验证,防止伪造。

// Node.js 示例
const crypto = require('crypto')
const sig = req.headers['x-voicelen-signature']
const expected = 'sha256=' + crypto.createHmac('sha256', SECRET)
  .update(req.rawBody).digest('hex')
if (sig !== expected) return res.status(401).end()

重试机制

  • 首次投递失败后延迟 1 分钟重试一次
  • 仍失败再延迟 10 分钟重试一次
  • 2 次重试都失败后标记为 failed,不再投递
  • Event ID 幂等:同一事件 ID 永远只投递一次

事件列表

call.started通话开始

{
  "call_id": "task-xxx",
  "direction": "outbound",
  "source_type": "outbound_task",
  "customer_phone": "138...",
  "trunk_number": "xxx",
  "agent_uuid": "a_xxx",
  "agent_name": "售后 Agent",
  "outbound_task_uuid": "t_xxx",
  "start_time": "2026-04-20T10:00:00+08:00"
}

call.ended通话结束

{
  "call_id": "task-xxx",
  "direction": "outbound",
  "customer_phone": "138...",
  "agent_uuid": "a_xxx",
  "agent_name": "售后 Agent",
  "user_uuid": "u_xxx",
  "user_name": "张三",
  "start_time": "2026-04-20T10:00:00+08:00",
  "answer_time": "2026-04-20T10:00:03+08:00",
  "end_time": "2026-04-20T10:02:15+08:00",
  "duration": 135,
  "billsec": 132,
  "hangup_cause": "NORMAL_CLEARING",
  "hangup_by": "customer",
  "recording_url": "https://..."
}

call.analyzedAI 分析完成

{
  "call_id": "task-xxx",
  "customer_phone": "138...",
  "agent_uuid": "a_xxx",
  "quality_score": 85,
  "sentiment": "positive",
  "violations": [],
  "ai_summary": "客户对 A 套餐感兴趣...",
  "intent": "high",
  "tags_added": ["高意向"]
}

outbound_task.item_answered外呼任务客户接通

{
  "task_uuid": "t_xxx",
  "task_name": "春节回访",
  "call_id": "task-xxx",
  "customer_phone": "138...",
  "customer_name": "张总",
  "extra": { "order_id": "A123" },
  "answer_time": "2026-04-20T10:00:03+08:00"
}

outbound_task.completed外呼任务完成

{
  "task_uuid": "t_xxx",
  "task_name": "春节回访",
  "total_count": 1000,
  "answered_count": 872,
  "no_answer_count": 98,
  "busy_count": 20,
  "failed_count": 10,
  "answer_rate": 0.872,
  "start_date": "2026-04-20",
  "end_date": "2026-04-20"
}

Prompt 变量

在 Agent 的 System Prompt 中可以使用 {{xxx}} 语法引用客户数据。通话发起时,系统会根据本次通话的客户手机号自动注入变量值。

数据查找顺序

1) 通过 call_id 查 CallRecord 得到 customer_phone 与 outbound_task_id
2) 按 company_id + phone 查 customers 表
3) 若是任务外呼,再按 task_id + phone 查 outbound_task_items
4) 合并结果,items 字段覆盖 customers(name、extra 均如此)

可用变量

变量 来源 说明
{{customer.phone}} CallRecord.customer_phone 本次通话的客户手机号
{{customer.name}} items.name > customers.name 客户姓名;任务 item 有则优先,否则用 customer 表
{{customer.extra.xxx}} items.extra > customers.extra 合并后 extra 里的字段,支持嵌套(如 {{customer.extra.profile.level}})

规则

  • 未命中(字段不存在或客户未找到)→ 替换为空字符串。
  • 数组 → 逗号连接,如 ['VIP', '老客户']'VIP, 老客户'
  • 布尔值 → '是' / '否'。
  • 对象不展开(需用点号继续取)。

示例

创建外呼任务时,在 items 的 extra 字段里塞自定义数据(JSON 字符串):

{
  "items": [
    {
      "phone": "13800138001",
      "name": "张总",
      "extra": "{\"order_id\":\"A123\",\"amount\":998,\"level\":\"VIP\"}"
    }
  ]
}

Agent 的 System Prompt 写成:

您好 {{customer.name}},这里是 Voicelen 客服。
您的订单号 {{customer.extra.order_id}} 金额 {{customer.extra.amount}} 元
# 通话时替换为:您好 张总,这里是 Voicelen 客服。
# 您的订单号 A123 金额 998 元

数据模型

OpenOutboundTaskResponse

字段 类型 说明
uuidstring任务唯一标识
namestring任务名称
start_datestring开始日期
end_datestring结束日期
time_slotsstring时间段配置 JSON
target_typestring目标类型:robot
agent_uuidstringAgent UUID
statusstring
pending running paused completed cancelled
status_remarkstring状态备注
status_atstring状态变更时间
total_countint总条目数
called_countint已呼叫数
answered_countint已接听数
answer_ratefloat接通率(百分比)
created_atstring创建时间

OpenOutboundTaskItemResponse

字段 类型 说明
phonestring电话号码
namestring客户姓名
extrastring扩展字段
statusstring
pending calling answered no_answer busy failed retrying
call_idstring通话 ID
start_timestring呼叫开始时间
answer_timestring接听时间
end_timestring结束时间
durationint通话时长(秒)
billsecint计费时长(秒)
hangup_causestring挂断原因
attemptsint呼叫次数
created_atstring创建时间

OpenAgentResponse

字段 类型 说明
uuidstringAgent 唯一标识
namestringAgent 名称
created_atstring创建时间

OpenCallRecordResponse

字段 类型 说明
call_idstring通话 ID
directionstring
inbound outbound
customer_phonestring客户电话
task_uuidstring外呼任务 UUID
agent_uuidstringAgent UUID
agent_namestringAgent 名称
start_timestring呼叫开始时间
answer_timestring接听时间
end_timestring结束时间
durationint通话时长(秒)
billsecint计费时长(秒)
hangup_causestring挂断原因
hangup_bystring
customer user system
created_atstring创建时间

OpenAgentConversationResponse

字段 类型 说明
seqint对话序号
rolestring
customer.say agent.say
textstring对话文本
asr_first_msintASR 首包延迟:调用开始 → 首个非空识别结果(ms)
asr_durationintASR 完整耗时:调用开始 → 最终结果返回(ms)
llm_first_msintLLM 首包延迟:ChatStream 调用 → 首个 chunk(ms)
llm_durationintLLM 完整耗时:ChatStream 调用 → 全部读完(ms)
tts_first_msintTTS 首包延迟:首段 SynthesizeStream 调用 → 首个音频 chunk(ms)
tts_durationintTTS 完整耗时:首段合成的全部音频(ms)
interruptedbool是否被打断
interrupted_textstring被打断时已播放的文本