-
Notifications
You must be signed in to change notification settings - Fork 12.9k
WeChat iLink Typing Indicator API — undocumented but works #1553
btxro3han-code
started this conversation in
Show and tell
-
TL;DR
You can show the native "对方正在输入..." (typing indicator) in WeChat using the iLink bot API. This is undocumented but fully functional. We implemented it in our WeChat bot and it works great — much better than sending a temporary "thinking..." message.
The API
Step 1: Get a typing_ticket
POST {baseUrl}/ilink/bot/getconfig
Headers:
Content-Type: application/json
AuthorizationType: ilink_bot_token
Authorization: Bearer {bot_token}
X-WECHAT-UIN: {base64(randomUint32())}
Body:
{
"ilink_user_id": "{user_id}", // ⚠️ REQUIRED — omitting this returns ret:-2
"base_info": { "channel_version": "2.0.1" }
}
Response:
{
"ret": 0,
"typing_ticket": "AARTBK8FAAAB..."
}
The ticket can be cached for ~20 hours.
Step 2: Send/cancel typing status
POST {baseUrl}/ilink/bot/sendtyping
Body:
{
"ilink_user_id": "{user_id}", // ⚠️ REQUIRED here too
"to_user_id": "{user_id}",
"typing_ticket": "{ticket}",
"command": 1, // 1 = show typing, 2 = cancel
"base_info": { "channel_version": "2.0.1" }
}
Response:
{ "ret": 0 }
Key Gotcha
Both getconfig and sendtyping require the ilink_user_id field. Without it you get {"ret":-2,"errmsg":"ilink_user_id required"}. This is not documented anywhere we could find — we discovered it by trial and error.
TypeScript Implementation
// Typing ticket cache let typingTicket: string | null = null; let typingTicketExpiry = 0; async function ensureTypingTicket( baseUrl: string, token: string, userId: string ): Promise<string | null> { if (typingTicket && Date.now() < typingTicketExpiry) return typingTicket; const res = await fetch(`${baseUrl}/ilink/bot/getconfig`, { method: 'POST', headers: buildIlinkHeaders(token), body: JSON.stringify({ ilink_user_id: userId, base_info: { channel_version: '2.0.1' }, }), }); const data = await res.json(); if (data.typing_ticket) { typingTicket = data.typing_ticket; typingTicketExpiry = Date.now() + 20 * 3600_000; return typingTicket; } return null; } async function sendTyping( baseUrl: string, token: string, userId: string, command: 1 | 2 = 1 ) { const ticket = await ensureTypingTicket(baseUrl, token, userId); if (!ticket) return; await fetch(`${baseUrl}/ilink/bot/sendtyping`, { method: 'POST', headers: buildIlinkHeaders(token), body: JSON.stringify({ ilink_user_id: userId, to_user_id: userId, typing_ticket: ticket, command, base_info: { channel_version: '2.0.1' }, }), }); }
Usage Pattern
// When a message arrives: await sendTyping(baseUrl, token, userId, 1); // Show typing // Process with AI... const response = await queryAI(message); await sendTyping(baseUrl, token, userId, 2); // Cancel typing await sendMessage(baseUrl, token, userId, response);
Why This Matters
Most WeChat bots either:
- Show no feedback while processing (user wonders if bot is alive)
- Send a temporary "thinking..." message (creates noise in chat history)
The native typing indicator solves both — user sees the bot is working, no extra messages.
Hope this helps anyone building WeChat bots with iLink! 🎉
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment