API 参考
小部件 API
Widget API 是捆绑的 JavaScript 对话的公共 HTTP 表面。 您通常不会自己调用它 — widget loader 会这样做 — 但这里的契约已记录在案, 因此您可以构建自定义客户端、审计流量或模拟小部件进行测试。
所有端点都在 /api/v1/widget 下。
身份验证是由 /init 颁发的签名 JWT。
CORS 对跨源嵌入的 POST 是宽松的。
POST POST /v1/widget/init
为访客启动小部件。无需身份验证 — 但请求的 Origin 标头必须匹配智能体的 allowed_origins(参见 Allowed origins)。
请求
POST /api/v1/widget/init
Origin: https://your-site.com
Content-Type: application/json
{
"agent_id": "01HXY...",
"page_url": "https://your-site.com/pricing",
"anon_id": "anon_abc123" // 可选;在重新加载时持久化访客
}
响应 (200)
{
"data": {
"conversation_id": "01HXZ...",
"visitor_id": "01HXY...",
"anonymous_id": "anon_abc123",
"jwt": "eyJhbGciOiJIUzI1NiI...",
"expires_at": "2026-05-07T13:00:00Z",
"agent": {
"id": "01HXY...",
"name": "Aria",
"persona": { "name": "Aria", "tone": "friendly" },
"theme": { "primary": "#111827", ... },
"starter_prompts": [ "..." ],
"language_default": "en"
},
"branding": { "show": true, "label": "...", "url": "...", "logo_url": "...", "display_mode": "logo_only" },
"behavior_rules": [ ... ],
"messages": [ ... ], // last 30 messages of the resumed conversation
"reverb": { "app_key": "...", "host": "...", "port": 8080, "scheme": "wss" }
}
}
错误响应
| 状态 | 代码 | 原因 |
|---|---|---|
| 404 | agent_not_found | 智能体不存在或未发布。 |
| 403 | origin_forbidden | Origin 不在 allowed_origins 中。 |
| 429 | plan_limit_reached | 工作区超过其每月对话配额。 |
| 429 | (throttled) | 每 IP 速率限制命中(默认 60 rpm)。 |
POST POST /v1/widget/messages/stream
流式端点。SSE 响应。身份验证:Authorization: Bearer <jwt>。
将此用于访客体验 — 所有其他方法都是同步且较慢的。
请求
POST /api/v1/widget/messages/stream
Authorization: Bearer eyJhbGciOiJIUzI1NiI...
Content-Type: application/json
{
"message": "What's your refund policy?",
"page_url": "https://your-site.com/pricing",
"page_context": { ... } // optional; structured data extracted from the current page
}
响应 (Server-Sent Events)
HTTP/1.1 200 OK
content-type: text/event-stream
data: {"event":"token","token":"Our "}
data: {"event":"token","token":"refund "}
data: {"event":"token","token":"policy is 30 days "}
data: {"event":"citations","citations":[{"id":1,"url":"https://your-site.com/refunds"}]}
data: {"event":"done","conversation_id":"01HXZ..."}
Token 事件在前几百毫秒内最快到达 — 这是热路径上 1 秒到首个 token 的目标。
citations 事件在流式传输完成后到达一次;done 关闭流。
POST POST /v1/widget/messages
/messages/stream 的同步版本。在一个 JSON 有效负载中返回完整响应。
较慢(访客等待完整响应)但更容易与非浏览器客户端集成。
响应
{
"data": {
"message_id": "01HXZ...",
"conversation_id": "01HXZ...",
"content": "Our refund policy is 30 days...",
"citations": [{"id": 1, "url": "..."}],
"low_confidence": false
}
}
POST POST /v1/widget/leads
提交捕获的联系信息。身份验证:与消息相同的 JWT。
POST /api/v1/widget/leads
Authorization: Bearer eyJhbGciOiJIUzI1NiI...
{
"name": "Alex",
"email": "alex@example.com",
"phone": "+1...",
"fields": { "company": "Acme" } // 任何智能体定义的自定义字段
}
在 (agent_id, email) 上去重:重复提交更新现有潜在客户而不是创建新的。 每个 JWT 每个窗口速率限制为 5 个请求 — 抗滥用。
POST POST /v1/widget/events
轻量级客户端分析。小部件用遥测事件调用此端点(启动器打开、CTA 点击、关闭、滚动触发器触发)。 身份验证:JWT。速率限制。
{
"event": "cta.click",
"rule_id": "01HXY...",
"metadata": { ... }
}
JWT 格式
HS256,使用 WIDGET_JWT_SECRET 签名。声明:
{
"iss": "hukeyu",
"iat": 1714900000,
"exp": 1714903600, // 60 分钟
"agent_id": "01HXY...",
"visitor_id": "01HXY...",
"conversation_id": "01HXZ..."
}
Token 范围限定为单个对话。重新初始化以获取新对话的新 token。
验证发生在 WidgetJwt::verify() 中 — 无效签名、过期 token 或篡改的声明都返回 401。
速率限制
| 端点 | 限制 | 键 |
|---|---|---|
/init | 60 rpm | 每 IP + agent_id (throttle:widget-init) |
/messages, /messages/stream, /events, /conversation/*, DELETE /me | 30 rpm | 每 JWT (throttle:widget-session) |
/leads | 5 rpm | 每 JWT (throttle:widget-leads) |
All return 429 with a Retry-After header on limit.