{
  "title": "Vox平台-API接入文档",
  "version": "V1.0.4",
  "sourcePath": "docs/api/Vox平台-API接入文档V1.0.4.md",
  "canonicalHtmlPath": "/docs",
  "markdownPath": "/docs.md",
  "llmsPath": "/llms.txt",
  "headings": [
    {
      "id": "vox平台-api接入文档v104",
      "level": 1,
      "label": "Vox平台-API接入文档V1.0.4"
    },
    {
      "id": "1修订记录",
      "level": 2,
      "label": "1、修订记录"
    },
    {
      "id": "2概述",
      "level": 2,
      "label": "2、概述"
    },
    {
      "id": "21-接入流程",
      "level": 3,
      "label": "2.1 接入流程"
    },
    {
      "id": "22-安全机制",
      "level": 3,
      "label": "2.2 安全机制"
    },
    {
      "id": "221-通讯安全",
      "level": 4,
      "label": "2.2.1 通讯安全"
    },
    {
      "id": "222-会话安全",
      "level": 4,
      "label": "2.2.2 会话安全"
    },
    {
      "id": "223-生成签名方式",
      "level": 4,
      "label": "2.2.3 生成签名方式"
    },
    {
      "id": "加密方式",
      "level": 5,
      "label": "加密方式"
    },
    {
      "id": "参数",
      "level": 5,
      "label": "参数"
    },
    {
      "id": "代码示例",
      "level": 5,
      "label": "代码示例"
    },
    {
      "id": "23-域名信息",
      "level": 3,
      "label": "2.3 域名信息"
    },
    {
      "id": "24-术语解释",
      "level": 3,
      "label": "2.4 术语解释"
    },
    {
      "id": "25-公共参数",
      "level": 3,
      "label": "2.5 公共参数"
    },
    {
      "id": "3业务接口",
      "level": 2,
      "label": "3、业务接口"
    },
    {
      "id": "31-发起外呼",
      "level": 3,
      "label": "3.1 发起外呼"
    },
    {
      "id": "4webhook-回调",
      "level": 2,
      "label": "4、Webhook 回调"
    },
    {
      "id": "41-sse-协议方式实现",
      "level": 3,
      "label": "4.1 SSE 协议方式实现"
    },
    {
      "id": "411-协议概述",
      "level": 4,
      "label": "4.1.1 协议概述"
    },
    {
      "id": "412-接口地址",
      "level": 4,
      "label": "4.1.2 接口地址"
    },
    {
      "id": "413-请求方法",
      "level": 4,
      "label": "4.1.3 请求方法"
    },
    {
      "id": "414-请求头",
      "level": 4,
      "label": "4.1.4 请求头"
    },
    {
      "id": "415-请求体",
      "level": 4,
      "label": "4.1.5 请求体"
    },
    {
      "id": "416-sse-响应协议",
      "level": 4,
      "label": "4.1.6 SSE 响应协议"
    },
    {
      "id": "417-交互流程",
      "level": 4,
      "label": "4.1.7 交互流程"
    },
    {
      "id": "418-错误处理",
      "level": 4,
      "label": "4.1.8 错误处理"
    },
    {
      "id": "419-特殊说明",
      "level": 4,
      "label": "4.1.9 特殊说明"
    },
    {
      "id": "5附录",
      "level": 2,
      "label": "5、附录"
    },
    {
      "id": "51通用状态码",
      "level": 3,
      "label": "5.1通用状态码"
    }
  ],
  "markdown": "# Vox平台-API接入文档V1.0.4\n\n\n\n[TOC]\n\n## 1、修订记录\n\n| 版本   | 修订内容                               | 修订人 | 修订时间   |\n| ------ | -------------------------------------- | ------ | ---------- |\n| V1.0.1 | 编写初稿                               | 李欢   | 2026-03-19 |\n| V1.0.2 | 完善接口规范                           | 李欢   | 2026-03-26 |\n| V1.0.3 | 外呼接口增加扩展字段，实现额外扩展功能 | 李欢   | 2026-05-11 |\n| V1.0.4 | 外呼接口增加botType和agentProfile配置  | 李欢   | 2026-05-20 |\n\n## 2、概述\n\n### 2.1 接入流程\n\n1. 商家与泰迪熊移动签订相关合作授权协议。\n2. 商家通过统一平台注册企业账号，并提交资质认证。\n3. 商家联系泰迪熊审核账号资质，并分配相关权限。\n4. 泰迪熊提供企业账号appId和签名秘钥。\n\n### 2.2 安全机制\n\n#### 2.2.1 通讯安全\n\n- 泰迪熊移动商家开放平台基于https协议搭建，并要求合作商家同样采用https协议\n- 泰迪熊移动商家开放平台通过IP白名单机制限制访问来源，非白名单无法访问服务。\n- 泰迪熊移动商家开放平台会根据访问商家检测访问量和访问频率，超出预定数值将自动发出预警，必要时会临时切断商家访问，为避免此情况发生，请在申请阶段如实告知预计访问量。\n\n#### 2.2.2 会话安全\n\n- 泰迪熊移动商家开放平台采用签名校验安全机制，通过接口信息和客户唯一secret生成签名。\n\n#### 2.2.3 生成签名方式\n\n将参与生成签名的参数按顺序拼接字符串，按对应加密方式获得签名。\n\n##### 加密方式\n\nhmac-sha256\n\n##### 参数\n\n|   参数    |  类型  |      描述      |                             备注                             |\n| :-------: | :----: | :------------: | :----------------------------------------------------------: |\n|  method   | String |    请求方式    | 需转为大写，如：GET/PUT/POST/DELETE/OPTIONS/HEADER等HTTP协议中定义的method |\n|   path    | String |    接口路径    |                       例：/vox/api/xx                        |\n| uriParams | String |    uri参数     | uri中\"?\"后的部分，不包括\"?\"，例如：key1=value 1&key2 = value 2 |\n|   appid   | String | 企业账号appId  |                         由泰迪熊分配                         |\n|  dateGMT  | String |    请求时间    |      GMT格式的时间，必须与HTTP Header中的HMAC-DATE一致       |\n|  secret   | String | 企业账号的密钥 |                         由泰迪熊分配                         |\n\n##### 代码示例\n\n```\npublic class SignatureHelper {\n   private static String signatureHmacSHA256(String message, String secret) {\n       try {\n           Mac hasher = Mac.getInstance(\"HmacSHA256\");\n           hasher.init(new SecretKeySpec(secret.getBytes(), \"HmacSHA256\"));\n           byte[] hash = hasher.doFinal(message.getBytes(\"UTF-8\"));\n           // to base64\n           return DatatypeConverter.printBase64Binary(hash);\n      } catch (NoSuchAlgorithmException e) {\n \n      } catch (InvalidKeyException e) {\n \n      }\n       return null;\n  }\n \n   /**\n    * @param method   HTTP Method，例如：GET/PUT/POST/DELETE/OPTIONS/HEADER等HTTP协议中定义的method，必须是大写。\n    * @param path     接口路径，例如：/sm/api/statistic/event，必须以\"/\"开头。\n    * @param uriParams uri中\"?\"后的部分，不包括\"?\"，例如：key1=value 1&key2 = value 2,参数字符串要按照各参数名称的字符顺序进行排列。\n    * @param appid     主账号的appid\n    * @param dateGMT   GMT格式的时间，必须与HTTP Header中的HMAC-DATE一致\n    * @param secret   主账号的密钥\n    * @return 生成好的签名\n    */\n   public static String buildSignature(String method, String path, String uriParams, String appid, String dateGMT, String secret) {\n       StringBuilder s = new StringBuilder();\n       s.append(method.toUpperCase() + \"\\n\");\n       if (!path.startsWith(\"/\")) {\n           path = \"/\" + path;\n      }\n       s.append(path + \"\\n\");\n       if (uriParams == null) {\n           uriParams = \"\";\n      }\n       s.append(sortParam(uriParams.split(\"&\")) + \"\\n\");\n       s.append(appid + \"\\n\");\n       s.append(dateGMT + \"\\n\");\n       s.append(\"HMAC-APPID:\" + appid + \"\\n\");\n       String message = s.toString();\n       return buildSignature(message, secret);\n  }\n  \n  private static String sortParam(String[] params) {\n        Arrays.sort(params);\n        StringBuilder builder = new StringBuilder();\n        for (int i = 0; i < params.length; i++) {\n            builder.append(params[i]);\n            if (i < params.length - 1) {\n                builder.append(\"&\");\n            }\n        }\n        return builder.toString();\n   }\n \n   public static String buildSignature(String message, String secret) {\n       return signatureHmacSHA256(message, secret);\n  }\n}\n```\n\n```\n// 加密Demo\nclass SignatureHelperTest {\n \n   @Test\n   void buildSignature() {\n       String appid = \"demouser\";\n       String secret = \"demosecret\";\n       \n       String method = \"POST\";\n       String path = \"/sms/api/xx\";\n       String uriParams = \"a=b&x=y\";\n \n       //此处生成的GMT格式时间在发起HTTP请求时会使用到\n       SimpleDateFormat sdf = new SimpleDateFormat(\"EEE, dd MMM yyyy HH:mm:ss 'GMT'\", Locale.US);\n       sdf.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n       String dateGMT = sdf.format(new Date());\n       \n       //获取签名\n       String signature = SignatureHelper.buildSignature(method, path, uriParams, appid, dateGMT, secret);\n       System.out.println(signature);\n       \n       //j+DiLfTZoYyviAjSXejL0RyAvPHa8z4YR72n2/YUD4I=\n  }\n}\n```\n\n\n\n### 2.3 域名信息\n\n| 环境     | 域名地址                   |\n| -------- | -------------------------- |\n| 生产环境 | https://vox.teddymobile.cn |\n\n### 2.4 术语解释\n\n### 2.5 公共参数\n\n- HTTP请求头必须添加5个HMAC-xxx参数\n\n|       参数名        |  类型  |    描述    |                             备注                             |\n| :-----------------: | :----: | :--------: | :----------------------------------------------------------: |\n|     HMAC-APPID      | String |   appId    |                     泰迪熊分配的appId。                      |\n|      HMAC-DATE      | String |  请求时间  | GMT格式的时间，必须与签名时生成的GMT时间保持一致。务必确保服务器时钟准确，时钟偏移过大会导致身份认证失败。 |\n|   HMAC-SIGNATURE    | String |    签名    |       例：j+DiLfTZoYyviAjSXejL0RyAvPHa8z4YR72n2/YUD4I=       |\n|   HMAC-ALGORITHM    | String |  加密算法  |                      固定值 hmac-sha256                      |\n| HMAC-SIGNED-HEADERS | String | 签名头信息 |                      固定值 HMAC-APPID                       |\n\n- 响应体\n\n  | 参数名 |  类型  | 是否必填 |     描述     |  备注   |\n  | :----: | :----: | :------: | :----------: | :-----: |\n  |  code  |  int   |    是    |    状态码    | 成功：0 |\n  |  msg   | String |    否    |   返回说明   |         |\n  |  data  | Object |    否    | 具体业务数据 |         |\n  |  time  |  long  |    是    |   响应时间   | 时间戳  |\n  \n  \n\n## 3、业务接口\n\n### 3.1 发起外呼\n\n发起一个 outbound call（外呼）请求。\n\n**接口地址**：`/vox/v1/outbound`\n\n**请求方法**：`POST`\n\n**请求参数**：\n\n通话类bot请求示例：\n\n```\n{\n  \"appId\": \"d63dd1e9-3aa3-4f88-8d3e-2be7461dff56\",\n  \"botid\": \"bot_10001\",\n  \"callee\": \"131****1234\",\n  \"requestId\": \"66016fe1fa414ca48596aad35c457106\"\n}\n```\n\n通知类bot请求示例：\n\n```\n{\n  \"appId\": \"d63dd1e9-3aa3-4f88-8d3e-2be7461dff56\",\n  \"botid\": \"bot_10001\",\n  \"callee\": \"131****1234\",\n  \"requestId\": \"req_20260313144300001\",\n  \"extra\": \"{\\\"notification\\\":{\\\"text\\\":\\\"您好,这是一条通知\\\",\\\"times\\\":2}}\"\n}\n```\n\n自定义bot请求示例：\n\n```json\n{\n  \"appId\": \"d63dd1e9-3aa3-4f88-8d3e-2be7461dff56\",\n  \"botid\": \"\",\n  \"callee\": \"131****1234\",\n  \"requestId\": \"66016fe1fa414ca48596aad35c457106\",\n  \"botType\": \"custom\",\n  \"extra\": \"{\\\"agent_profile\\\":{\\\"name\\\":\\\"小美\\\",\\\"gender\\\":\\\"女\\\",\\\"age\\\":25,\\\"role\\\":\\\"销售顾问\\\",\\\"communicationStyle\\\":[\\\"热情\\\",\\\"专业\\\",\\\"亲切\\\"],\\\"background\\\":\\\"春季新品推广活动\\\",\\\"goals\\\":\\\"了解客户购买意向，促成交易\\\",\\\"skills\\\":\\\"产品介绍、需求挖掘、促成交易\\\",\\\"workflow\\\":\\\"问候 -> 了解需求 -> 介绍产品 -> 处理异议 -> 促成合作\\\",\\\"constraint\\\":\\\"保持礼貌、尊重对方意愿、不强制推销\\\",\\\"openingPrompt\\\":\\\"您好，我是小美，春季新品推广活动的销售顾问\\\"}}\"\n}\n```\n\n**请求字段说明**：\n\n| 字段                     | 类型       | 必填 | 说明                                     | 示例                                 |\n| ------------------------ | ---------- | ---- | ---------------------------------------- | ------------------------------------ |\n| appId                    | string     | 是   | 身份标识                                 | d63dd1e9-3aa3-4f88-8d3e-2be7461dff56 |\n| botid                    | string     | 是   | 机器人 ID（平台侧生成），当botType为\"custom\"时非必填 | `10001`                              |\n| callee                   | string     | 是   | 被叫号码（用户手机号）                   | `13800138000`                        |\n| requestId                | string     | 是   | 请求 ID（由调用方生成，用于幂等性保证）  | `66016fe1fa414ca48596aad35c457106`   |\n| botType                  | string     | 否   | Bot 类型，当前仅支持 \"custom\"（自定义Bot） | `custom`                             |\n| extra                    | JSONString | 否   | 扩展功能字段                             |                                      |\n| extra.voiceType          | string     | 否   | TTS音色类型编码。<br/>可选值及适用场景：<br/>• `0` - 知愈（女）：情绪安抚、心理陪伴、售后回访、不知道选什么<br/>• `1` - 安辰（男）：给长辈/老人做的任何语音内容<br/>• `2` - 景珩（男）：商务沟通、企业合作、科普讲解类内容<br/>• `3` - 知言（女）：发通知、公告、正式播报类内容<br/>• `4` - 星苒（女）：日常闲聊、陪伴、电商带货、生活服务类内容 | `0`                                  |\n| extra.agent_profile      | Object     | 否   | 自定义Bot配置，当botType为\"custom\"时必填 |                                      |\n| extra.agent_profile.name | string     | 是   | Bot名称                                  | `小美`                               |\n| extra.agent_profile.gender | string   | 是   | Bot性别                                  | `女`                                 |\n| extra.agent_profile.age  | int        | 是   | Bot年龄                                  | `25`                                 |\n| extra.agent_profile.role | string     | 是   | Bot角色定位                              | `销售顾问`                           |\n| extra.agent_profile.communicationStyle | array | 是 | 沟通风格列表                           | `[\"热情\", \"专业\", \"亲切\"]`           |\n| extra.agent_profile.background | string | 是 | 业务背景                               | `春季新品推广活动`                   |\n| extra.agent_profile.goals | string    | 是   | Bot目标                                  | `了解客户购买意向，促成交易`          |\n| extra.agent_profile.skills | string   | 是   | Bot技能                                  | `产品介绍、需求挖掘、促成交易`       |\n| extra.agent_profile.workflow | string | 是   | 工作流程                                 | `问候 -> 了解需求 -> 介绍产品 -> 处理异议 -> 促成合作` |\n| extra.agent_profile.constraint | string | 是 | 约束条件                               | `保持礼貌、尊重对方意愿、不强制推销` |\n| extra.agent_profile.openingPrompt | string | 是 | 开场白                                 | `您好，我是小美，春季新品推广活动的销售顾问` |\n| extra.notification       | Object     | 否   | 通知类bot相关的额外配置内容              |                                      |\n| extra.notification.text  | string     | 是   | 通知内容，extra.notification不为空时必填 | 您好,这是一条通知                    |\n| extra.notification.times | int        | 否   | 播放次数，默认为播放1次                  | 2                                    |\n\n**响应示例**：\n\n```json\n{\n  \"code\": 0,\n  \"msg\": \"success\",\n  \"data\": {\n    \"requestId\": \"66016fe1fa414ca48596aad35c457106\",\n    \"status\": \"accepted\"\n  }\n}\n```\n\n**响应字段说明**：\n\n| 字段           | 类型   | 说明                                                 |\n| -------------- | ------ | ---------------------------------------------------- |\n| code           | int    | 响应码，0 表示成功                                   |\n| msg            | string | 响应消息                                             |\n| data.requestId | string | 请求 ID，与请求中的 requestId 一致                   |\n| data.status    | string | 任务状态：`accepted`（已成功接收） \\| failed（失败） |\n\n**HTTP 状态码**：\n\n- `202 Accepted` - 请求已被接受处理\n\n## 4、Webhook 回调\n\n### 4.1 SSE 协议方式实现\n\n Vox通过 HTTP POST + SSE（Server-Sent Events）流式交互协议与第三方开发者系统进行实时双向通信。\n\n#### 4.1.1 协议概述\n\n- **方向**：Vox 作为 HTTP Client 主动发起请求，第三方系统作为 HTTP Server 提供 API\n- **传输方式**：单次 HTTP POST 请求，第三方返回 `text/event-stream` 持续流式响应\n- **会话连续性**：通过 `conversation_uuid` 维护，而非长连接\n- **适用场景**：需要流式输出、支持打断的多轮对话场景\n\n#### 4.1.2 接口地址\n\n由第三方开发者自行提供 HTTPS 端点地址，在创建机器人时配置。\n\n#### 4.1.3 请求方法\n\n`POST`\n\n#### 4.1.4 请求头\n\n| 参数名 | 类型 | 必填 | 说明 |\n|--------|------|------|------|\n| Content-Type | String | 是 | `application/json` |\n| Accept | String | 是 | `text/event-stream` |\n\n#### 4.1.5 请求体\n\n```json\n{\n    \"turn\": 6,\n    \"calltype\": \"inbound\",\n    \"callee\": \"18600013645\",\n    \"caller\": \"+8652780515543\",\n    \"callid\": \"4e0c4ecf-1ad6-42c3-b343-e1eb90ee18c6\",\n    \"requestid\": \"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n    \"message\": \"好，请问你是哪里的人？\"\n}\n```\n\n**字段说明**：\n\n| 字段 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| message | String | 是 | 用户输入文本(电话接通后第一次请求为\"\") | `\"我想了解套餐\"` |\n| callid | String | 是 | 通话的唯一id标识 |  |\n| requestid | String | 是 | 本次请求的唯一id标识 |  |\n| caller | String | 是 | 主叫号码 |  |\n| callee | String | 是 | 被叫号码 |  |\n| calltype | String | 是 | inbound-呼入  outbound-呼出 |  |\n| turn | int | 是 | 通话轮次，接通后第一次为1 |  |\n\n#### 4.1.6 SSE 响应协议\n\n**Media Type**: `text/event-stream`\n\n**响应块类型**：\n\n**1. 文本流块**（持续返回文本片段）\n\n```text\ndata: {\"id\":\"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n\"created\":1678901234,\"message\":\"你好\"}\n```\n\n继续：\n\n```text\ndata: {\"id\":\"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n\"created\":1678901234,\"message\":\"，我愿意倾听你。\"}\n```\n\n**2. 完成标记**（必须发送）\n\n```text\ndata: [DONE]\n```\n\n**响应字段说明**：\n\n| 字段 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| id | String | 是 | 消息唯一标识，与请求体中requestid一致，原样返回 |\n| created | Long | 是 | 消息创建时间戳 |\n| message | String | 是 | 非空文本片段，Vox 按到达顺序拼接并切句 |\n| action  | JSON | 否 | 扩展功能字段，例：{\"cmd\": \"hangup\"}表示需要主动挂断 |\n\n#### 4.1.7 交互流程\n\n**1. 通话开始**（call.started）\n\n```\nVox -> 第三方：POST /developer-api\nRequest:\n{\n    \"turn\": 1,\n    \"calltype\": \"inbound\",\n    \"callee\": \"18600013645\",\n    \"caller\": \"+8652780515543\",\n    \"callid\": \"4e0c4ecf-1ad6-42c3-b343-e1eb90ee18c6\",\n    \"requestid\": \"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n    \"message\": \"\"\n}\n\n第三方 -> Vox: SSE Stream\ndata: {\"id\":\"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n\"created\":1678901234,\"message\":\"您好\"}\ndata: {\"id\":\"1ad64ecf-b343-42c3-1ad6-e1eb90eeb343\",\n\"created\":1678901234,\"message\":\"，我愿意倾听你。\"}\ndata: [DONE]\n```\n\n**2. 用户说话**（asr.transcript）\n\n```\nVox -> 第三方：POST /developer-api\nRequest:\n{\n    \"turn\": 2,\n    \"calltype\": \"inbound\",\n    \"callee\": \"18600013645\",\n    \"caller\": \"+8652780515543\",\n    \"callid\": \"4e0c4ecf-1ad6-42c3-b343-e1eb90ee18c6\",\n    \"requestid\": \"550e8400-e29b-41d4-a716-446655440000\",\n    \"message\": \"我想办理宽带业务\"\n}\n\n第三方 -> Vox: SSE Stream\ndata: {\"id\":\"550e8400-e29b-41d4-a716-446655440000\",\n\"created\":1678901234,\"message\":\"好的\"}\ndata: {\"id\":\"550e8400-e29b-41d4-a716-446655440000\",\n\"created\":1678901234,\"message\":\"，请问您需要办理哪种宽带套餐？\"}\ndata: [DONE]\n```\n\n**3. 用户打断**（barge-in）\n\n当用户打断时：\n1. Vox 主动关闭当前 SSE 流\n2. 标记旧 response 为废弃\n3. 基于新 transcript 发起下一轮 HTTP + SSE 请求\n\n#### 4.1.8 错误处理\n\n| HTTP 状态码 | 含义 | Vox 处理方式 |\n|------------|------|----------------------|\n| 401 | 认证失败 | 结束通话或播放兜底文案 |\n| 400 | 请求参数错误 | 记录协议错误并结束通话 |\n| 429 | 限流 | 记录并播放兜底文案 |\n| 500 | 第三方内部错误 | 记录并播放兜底文案 |\n\n**SSE 中断处理**：\n- 首包前中断：视为本轮失败\n- 中途文本流中断且未收到 `[DONE]`：只播放已切出的内容，结束当前轮\n\n#### 4.1.9 特殊说明\n\n1. **打断语义**：第三方无需提供 cancel API，Vox 通过关闭当前 SSE 连接完成打断\n3. **会话管理**：Vox 不维护电话级长连接，每轮对话独立发起 HTTP 请求\n4. **文本切句**：Vox 负责对接收到的文本流进行切句和 TTS 播放\n\n## 5、附录\n\n### 5.1通用状态码\n\n| http状态码 | 含义                       | 备注                             |\n| ---------- | -------------------------- | -------------------------------- |\n| 401        | 未知用户，身份认证未通过   | 需联系泰迪熊配置开放平台用户信息 |\n| 403        | 无接口访问权限，鉴权未通过 | 需联系泰迪熊开通接口权限         |\n"
}