openapi: 3.1.0 info: title: 平台代注册火山与设备凭据下发 version: 1.1.0 description: 已部署到82.157.201.114。设备HTTPS接口使用既有DEVREQ1签名请求头;成功响应均有ok/code/request_id/server_time_ms/data外层。设备不再调用DynamicRegister。 servers: - url: https://82.157.201.114 security: - DeviceRequest: [] paths: /api/v1/device/chat/recording: post: summary: 在加入RTC房间前启动云端完整对话录音 description: 使用现有DEVREQ1设备签名,只传房间标识,不上传音频。必须先申请chat/start,并使用硬件网关返回的RoomID、UserID及RTC AppID。平台核对当前绑定、会话、房间归属与原音频保存同意,发起纯音频合流录制。相同会话与房间重试使用固定任务ID。云端未配置或未授权保存时返回DISABLED或NOT_AUTHORIZED,设备仍可正常聊天。 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [session_id, rtc_app_id, room_id, rtc_user_id] properties: device_id: {type: string} session_id: {type: string, format: uuid} rtc_app_id: {type: string, maxLength: 128} room_id: {type: string, maxLength: 128} rtc_user_id: {type: string, maxLength: 128} responses: '200': {description: 'data.recording为STARTED、DISABLED或NOT_AUTHORIZED'} '400': {description: 请求格式错误或房间不匹配} '409': {description: 会话已结束、绑定已变化或录音身份冲突} '503': {description: 火山录制启动暂不可用} default: {description: 设备鉴权失败} /api/v1/device/chat/start: post: summary: 绑定后直接申请或续期聊天参数,无需平台注册开机与SDK初始化回执 description: 平台检查当前老人绑定、火山设备注册结果和老人智能体。设备保存ble-bind下发的5个凭据,在本地初始化SDK后请求本接口。相同session_id每10秒续期,不重复创建火山任务。旧boot_id可兼容但不用于准入。未绑定返回409 DEVICE_UNBOUND。 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [session_id] properties: device_id: {type: string, description: 设备factory_id,应与签名头一致;旧固件可省略} session_id: {type: string, format: uuid, description: 每通新聊天生成;重试及续期不变} boot_id: {type: string, format: uuid, deprecated: true, description: 仅兼容旧固件;新设备省略} responses: '200': {description: 'data包含session_id、bot_id、params、lease_expires_at_ms和expires_at_ms。params.AgentConfig的回调地址与签名按本通session_id原样传给火山。'} '409': {description: DEVICE_UNBOUND、DEVICE_NOT_READY(平台注册未完成)、VOICE_AGENT_NOT_READY、CHAT_ENDED等} default: {description: 设备鉴权失败、请求格式错误、并发通话、配额或供应商配置失败} /api/v1/device/chat/end: post: summary: 设备停止本次聊天后上报结束 description: 同一session_id可重复上报;解绑后仍允许本设备补报旧会话结束。没有boot_id或初始化回执要求。 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [session_id, reason] properties: device_id: {type: string} session_id: {type: string, format: uuid} reason: {type: string, enum: [hangup, start_failed, disconnected, reboot, timeout]} sdk_stopped: {type: boolean, default: false, description: 仅确认SDK已停止时填true} responses: '200': {description: 'data包含session_id和ended=true'} default: {description: 设备鉴权失败或请求格式错误} /api/v1/device/voice-config: post: summary: 可选恢复接口:重新取得本设备的火山凭据 description: 正常ble-bind已直接返回5个字段,无需再查本接口。此接口保留原voice_status/voice格式;body为空对象。不要求先登记boot_id;未绑定返回409 DEVICE_UNBOUND;非ready状态voice为null。 requestBody: $ref: '#/components/requestBodies/Empty' responses: '200': description: data包含voice_status和voice content: application/json: schema: $ref: '#/components/schemas/VoiceEnvelope' default: {description: 设备鉴权失败、未绑定或状态冲突} /api/v1/device/voice-runtime: post: deprecated: true summary: 旧固件兼容:当前开机SDK初始化配置(新设备不调用) description: 仅供旧固件兼容。新设备直接保存ble-bind返回的凭据,在本地初始化SDK后请求chat/start,不调用register、voice-runtime或activation-acks。旧返回仍含state、command和call_contract。 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [boot_id] properties: boot_id: {type: string, format: uuid} responses: '200': {description: 当前绑定的语音状态及签名配置;preparing时每5秒查询} default: {description: 设备未绑定、开机编号不匹配或设备鉴权失败} /api/v1/device/voice-credentials: post: summary: 已注册旧固件一次性迁移本机凭据 description: 只接受平台已有已注册记录、当前绑定有效、实例/产品/设备名匹配的原凭据。重复相同内容幂等,不覆盖已有不同凭据。新设备不调用此接口。 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/VoiceCredential' responses: '200': {description: 'data: {accepted: true},然后重新获取voice-runtime'} default: {description: 未注册、未绑定、身份不匹配或VOICE_CREDENTIAL_CONFLICT} components: securitySchemes: DeviceRequest: type: apiKey in: header name: Authorization description: Device-HMAC-SHA256签名;另需X-Device-ID/X-Key-Version/X-Timestamp-Ms/X-Nonce/X-Request-ID和Content-Type。 requestBodies: Empty: required: true content: application/json: schema: {type: object, additionalProperties: false} schemas: VoiceCredential: type: object additionalProperties: false required: [instance_id, product_key, device_name, device_secret, RTCAppID] properties: instance_id: {type: string} product_key: {type: string} device_name: {type: string} device_secret: {type: string, minLength: 16, maxLength: 256} RTCAppID: {type: string, minLength: 1, maxLength: 128} VoiceEnvelope: type: object required: [ok, code, request_id, server_time_ms, data] properties: ok: {const: true} code: {const: OK} request_id: {type: string, format: uuid} server_time_ms: {type: integer, format: int64} data: type: object required: [voice_status, voice] properties: voice_status: type: string enum: [preparing, ready, paused, reconcile_required, migration_required] voice: oneOf: - {$ref: '#/components/schemas/VoiceCredential'} - {type: 'null'}