会话心跳:缺 sessionId 开新会话(sessions.api_key_id 归账)并回 sessionId;在册触碰 last_seen_at;meta 白名单(零留存);配置失效订阅:请求可携客户端 configVersion,响应恒回 configVersion 与 configStale(不一致=true → 重拉 /t1/config;未携恒 false);请求签名三头可选(在场恒校验);所有鉴权径的 configVersion/bundleEtag 与 /t1/config 使用同一 x-tansr-client-features 声明,三径须同携同值;在册心跳续租恒走并发守门 acquire,判限先于 last_seen_at 刷新;已归档会话恒 410 session_archived(detail.sessionId;不复活、不入位;SDK 停心跳、下轮 exchange 开新会话)
const url = 'https://api.tansr.com/t1/heartbeat';const options = { method: 'POST', headers: { 'x-tansr-key-id': '<x-tansr-key-id>', 'x-tansr-key': '<x-tansr-key>', 'Content-Type': 'application/json' }, body: '{"sessionId":"example","client":"cli","configVersion":"example","meta":{"clientVersion":"example","platform":"example"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.tansr.com/t1/heartbeat \ --header 'Content-Type: application/json' \ --header 'x-tansr-key: <x-tansr-key>' \ --header 'x-tansr-key-id: <x-tansr-key-id>' \ --data '{ "sessionId": "example", "client": "cli", "configVersion": "example", "meta": { "clientVersion": "example", "platform": "example" } }'Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”客户端可理解的可选扩展词表,逗号分隔,未知词忽略。platform-audio 控制旧令牌端音频可见性;tts-input-limit-v1 声明原子输入上限;bound-device-v1 声明绑定终端段;nonchat-operations-v1 声明六个非聊天能力;adjudicator-policy-slots-v1 声明裁决主备独立策略及预算模式,未声明时 independent 配置只发有效主选并禁用备用,旧 shared 策略保持原备用。新能力对所有未声明客户端剥除,owner 仅保留原音频可见性。响应 Vary 本头,正文和规范化特性集合共同生成 ETag;config、handshake、heartbeat 必须携相同特性。
签名时间戳(unix 秒,十进制串;T-A34):与服务器时钟偏差 >300s → 401 signature_invalid
签名随机数(≥16 字符;T-A34):同 keyId 600s 窗内重现 → 401 nonce_replayed
请求签名(hex 小写;T-A34):HMAC-SHA256(K=sha256(SK 明文) 原始摘要, TWP1-HMAC-SHA256\n{METHOD}\n{path+query}\n{ts}\n{nonce}\n{sha256hex(rawBody)});三头须同现,在场恒校验;app signRequired 或 TANSR_API_TWP_REQUIRE_SIGNATURE=1 时未签名恒 401 signature_invalid
Request Bodyrequired
Section titled “Request Bodyrequired”Responses
Section titled “Responses”心跳受理
object
服务端当前 configVersion(内容稳定指纹)
配置已失效(不一致=true;请求未携 configVersion 恒 false)
此刻 GET /t1/config 的 ETag(不带引号;= configVersion 同源;sdk 比对缓存条目 etag,不同即失效重拉)
Harness 许可状态提示位(O-A0 冻结;O-A3 起下发)
能力协商位(与 handshake 同词表 TWP_FEATURES;未知串恒忽略)
Examplegenerated
{ "sessionId": "example", "serverTime": "example", "configVersion": "example", "configStale": true, "bundleEtag": "example", "licenseStatus": "example", "features": [ "example" ]}App_key_invalid / signature_invalid / nonce_replayed(T-A34)
object
object
错误码注册表单源派生(src/http/errors.ts ERROR_CODES;码稳定,消费方按码翻译)
object
Example
{ "error": { "code": "adjudicator_not_authorized" }}Not_found(未知/他人会话)
object
object
错误码注册表单源派生(src/http/errors.ts ERROR_CODES;码稳定,消费方按码翻译)
object
Example
{ "error": { "code": "adjudicator_not_authorized" }}Session_archived(已归档会话;detail.sessionId;终态——开新会话)
object
object
错误码注册表单源派生(src/http/errors.ts ERROR_CODES;码稳定,消费方按码翻译)
object
Example
{ "error": { "code": "adjudicator_not_authorized" }}Plan_concurrency_exceeded(enforce:新会话首见 / 出窗会话重入达硬帽;Retry-After 30)/ rate_limited
object
object
错误码注册表单源派生(src/http/errors.ts ERROR_CODES;码稳定,消费方按码翻译)
object
Example
{ "error": { "code": "adjudicator_not_authorized" }}Plan_gate_unavailable(enforce 守门 Redis 故障;在册窗内会话为唯一放行例外)
object
object
错误码注册表单源派生(src/http/errors.ts ERROR_CODES;码稳定,消费方按码翻译)
object
Example
{ "error": { "code": "adjudicator_not_authorized" }}本文是否有帮助?
感谢反馈,我们会持续改进这篇文章。