指南 · chat:write
客服聊天机器人
回复给您账号发消息的人:订单问题、营业时间、常见问题。必要时转交给真人处理。
权限范围:chat:read、chat:write(可选:orders:read,用于查询订单)。
反垃圾消息规则#
机器人只能在对方已经发过消息的会话中发消息,或给关注了该账号的人发消息。其他情况都会返回 403 CHAT_NOT_ALLOWED。屏蔽始终有效(403 CHAT_BLOCKED)。这让客服机器人易于实现,而主动陌生推广则无法实现 — 这是有意为之的设计。
相关端点#
| 端点 | 用途 |
|---|---|
GET /conversations | 您的会话,按最近活动排序(分页)。 |
GET /conversations/{id}/messages | 会话中的消息,按从新到旧排序(分页)。 |
POST /conversations/{id}/messages | 在现有会话中回复。 |
POST /messages | 按用户 ID 给用户发消息(必要时会开启会话)。受反垃圾消息规则约束。 |
1. 查找需要回复的会话#
curl "https://api.linework.app/open/v1/conversations?limit=20" \
-H "Authorization: Bearer $LINEWORK_API_KEY"
对于每个有新活动的会话,读取最新消息并检查最后发消息的人:如果不是您,机器人可能需要回复。
curl "https://api.linework.app/open/v1/conversations/c_3391/messages?limit=10" \
-H "Authorization: Bearer $LINEWORK_API_KEY"
2. 回复#
curl https://api.linework.app/open/v1/conversations/c_3391/messages \
-H "Authorization: Bearer $LINEWORK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "text": "Hi! We are open Monday to Saturday, 9:00–19:00." }'
3. 完整的轮询机器人#
const API = "https://api.linework.app/open/v1";
const headers = { Authorization: `Bearer ${process.env.LINEWORK_API_KEY}`, "Content-Type": "application/json" };
const get = (p) => fetch(API + p, { headers }).then((r) => r.json());
const me = await get("/me");
const answered = new Set(); // in production: a database
async function tick() {
const convs = await get("/conversations?limit=20");
for (const conv of convs.data) {
const msgs = await get(`/conversations/${conv.id}/messages?limit=5`);
const last = msgs.data[0]; // newest first
if (!last || last.senderId === me.id || answered.has(last.id)) continue;
const reply = answer(last.text);
answered.add(last.id);
if (!reply) continue; // a human will answer
const res = await fetch(`${API}/conversations/${conv.id}/messages`, {
method: "POST", headers, body: JSON.stringify({ text: reply }),
});
if (res.status === 429) return; // quota or rate limit: try again later
}
}
function answer(text = "") {
if (/hours|open|orari/i.test(text)) return "We are open Monday to Saturday, 9:00–19:00.";
if (/order|ordine/i.test(text)) return "Send me your order number and I will check it for you.";
return null;
}
setInterval(() => tick().catch(console.error), 30_000);
import os, re, time, requests
API = "https://api.linework.app/open/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['LINEWORK_API_KEY']}"
me = s.get(API + "/me", timeout=30).json()
answered = set() # in production: a database
def answer(text):
if re.search(r"hours|open|orari", text or "", re.I):
return "We are open Monday to Saturday, 9:00–19:00."
if re.search(r"order|ordine", text or "", re.I):
return "Send me your order number and I will check it for you."
return None
def tick():
convs = s.get(API + "/conversations", params={"limit": 20}, timeout=30).json()
for conv in convs["data"]:
msgs = s.get(f"{API}/conversations/{conv['id']}/messages", params={"limit": 5}, timeout=30).json()
last = msgs["data"][0] if msgs["data"] else None # newest first
if not last or last["senderId"] == me["id"] or last["id"] in answered:
continue
answered.add(last["id"])
reply = answer(last.get("text"))
if not reply:
continue # a human will answer
r = s.post(f"{API}/conversations/{conv['id']}/messages", json={"text": reply}, timeout=30)
if r.status_code == 429:
return # quota or rate limit: try again later
while True:
tick()
time.sleep(30)
senderId 等字段名仅作示意:请在 API 参考中查看消息结构。
礼貌地轮询#
- 每 15–60 秒轮询一次。每次轮询调用一次
/conversations,再读取少量消息,远低于每分钟 120 个请求的限制。 - 只打开自上次轮询以来最后活动时间有变化的会话。
- 每日配额为每个账号 500 条消息。
做一个好机器人#
- 在第一条回复中说明自己是机器人,并告诉对方如何联系真人。
- 切勿向没有提出请求的人发送推广信息,也切勿向许多人发送相同的消息。
- 不要在聊天中索要密码、支付信息或验证码。
- 当对方要求停止时,请停止发送。